diff --git a/src/components/OIDCLanding.js b/src/components/OIDCLanding.js index 9c164979f..09f3aa375 100644 --- a/src/components/OIDCLanding.js +++ b/src/components/OIDCLanding.js @@ -1,34 +1,39 @@ import React, { useEffect, useState } from 'react'; -import { useLocation, Redirect } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import queryString from 'query-string'; import { useStore } from 'react-redux'; import { FormattedMessage } from 'react-intl'; -import { Loading } from '@folio/stripes-components'; +import { + Button, + Col, + Headline, + Loading, + Row, +} from '@folio/stripes-components'; +import OrganizationLogo from './OrganizationLogo'; import { requestUserWithPerms, setTokenExpiry } from '../loginServices'; import css from './Front.css'; import { useStripes } from '../StripesContext'; /** - * OIDCLanding: un-authenticated route handler for /sso-landing. + * OIDCLanding: un-authenticated route handler for /oidc-landing. * - * Reads one-time-code from URL params, exchanging it for an access_token - * and then leveraging that to retrieve a user via requestUserWithPerms, - * eventually dispatching session and Okapi-ready, resulting in a - * re-render of RoothWithIntl with prop isAuthenticated: true. + * * Read one-time-code from URL params + * * make an API call to /authn/token to exchange the OTP for cookies + * * call requestUserWithPerms to make an API call to .../_self, + * eventually dispatching session and Okapi-ready, resulting in a + * re-render of RoothWithIntl with prop isAuthenticated: true * * @see RootWithIntl */ const OIDCLanding = () => { const location = useLocation(); const store = useStore(); - // const samlError = useRef(); const { okapi } = useStripes(); - const [potp, setPotp] = useState(); - const [samlError, setSamlError] = useState(); - + const [oidcError, setOIDCError] = useState(); /** * Exchange the otp for AT/RT cookies, then retrieve the user. @@ -56,7 +61,6 @@ const OIDCLanding = () => { const otp = getOtp(); if (otp) { - setPotp(otp); fetch(`${okapi.url}/authn/token?code=${otp}&redirect-uri=${window.location.protocol}//${window.location.host}/oidc-landing`, { credentials: 'include', headers: { 'X-Okapi-tenant': okapi.tenant, 'Content-Type': 'application/json' }, @@ -83,7 +87,7 @@ const OIDCLanding = () => { .catch(e => { // eslint-disable-next-line no-console console.error('@@ Oh, snap, OTP exchange failed!', e); - setSamlError(e); + setOIDCError(e); }); } // we only want to run this effect once, on load. @@ -93,22 +97,45 @@ const OIDCLanding = () => { // store: the redux store }, []); // eslint-disable-line react-hooks/exhaustive-deps - if (samlError) { + /** + * formatOIDCError + * Return formatted OIDC error message, or null + * @returns + */ + const formatOIDCError = () => { + if (Array.isArray(oidcError?.errors)) { + return ( + + + {oidcError.errors[0]?.message} + + + ); + } + + return null; + }; + + if (oidcError) { return ( -
-
- -
-
-

code

- {potp} -

error

- - {JSON.stringify(samlError, null, 2)} - -
- -
+
+ + + + + + + + + + + {formatOIDCError()} + + + + + +
); } @@ -117,11 +144,6 @@ const OIDCLanding = () => {
-
-
-          {JSON.stringify(samlError, null, 2)}
-        
-
); }; diff --git a/src/components/OIDCLanding.test.js b/src/components/OIDCLanding.test.js index f7e199c50..17a553ee7 100644 --- a/src/components/OIDCLanding.test.js +++ b/src/components/OIDCLanding.test.js @@ -20,8 +20,7 @@ jest.mock('../StripesContext', () => ({ }), })); -// jest.mock('../loginServices'); - +jest.mock('./OrganizationLogo', () => (() =>
OrganizationLogo
)); const mockSetTokenExpiry = jest.fn(); const mockRequestUserWithPerms = jest.fn(); @@ -79,7 +78,7 @@ describe('OIDCLanding', () => { mockFetchError('barf'); await render(); - await screen.findByText('errors.saml.missingToken'); + await screen.findByText('stripes-core.errors.oidc'); mockFetchCleanUp(); }); }); diff --git a/translations/stripes-core/en.json b/translations/stripes-core/en.json index c0c98413a..ff986668d 100644 --- a/translations/stripes-core/en.json +++ b/translations/stripes-core/en.json @@ -147,6 +147,7 @@ "errors.password.consecutiveWhitespaces.invalid": "The password must not contain consecutive white space characters.", "errors.password.compromised.invalid": "The password must not be commonly-used, expected or compromised", "errors.saml.missingToken": "No code query parameter.", + "errors.oidc": "Error: server is forbidden, unreachable, or unavailable.", "createResetPassword.header": "Choose a password", "createResetPassword.newPassword": "New Password", diff --git a/translations/stripes-core/en_US.json b/translations/stripes-core/en_US.json index e6225264e..f49fa0f0f 100644 --- a/translations/stripes-core/en_US.json +++ b/translations/stripes-core/en_US.json @@ -159,5 +159,7 @@ "tenantLibrary": "Tenant/Library", "errors.saml.missingToken": "No code query parameter.", "rtr.fixedLengthSession.timeRemaining": "Your session will end soon! Time remaining:", - "logoutComplete": "You have logged out." + "logoutComplete": "You have logged out.", + "errors.oidc": "Error: server is forbidden, unreachable, or unavailable." + }