Skip to content

Commit 67626d1

Browse files
chore: update auth-js to 4.8.0
feat: adds handling of interaction_required error updates CHANGELOG and README for onAuthResume fix linting remove stale debugging updates README OKTA-360883 <<<Jenkins Check-In of Tested SHA: 2918f28 for eng_productivity_ci_bot_okta@okta.com>>> Artifact: okta-react
1 parent 459badd commit 67626d1

File tree

14 files changed

+224
-45
lines changed

14 files changed

+224
-45
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 5.1.0
2+
3+
### Features
4+
- [#104](https://github.com/okta/okta-react/pull/104) Adds support for `onAuthResume` to `LoginCallback` for `interaction_required` OAuth errors (requires okta-auth-js 4.8+)
5+
16
# 5.0.0
27

38
### Breaking Changes

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[Okta Auth SDK]: https://github.com/okta/okta-auth-js
2+
[Okta SignIn Widget]: https://github.com/okta/okta-signin-widget
23
[AuthState]: https://github.com/okta/okta-auth-js#authstatemanager
34
[react-router]: https://github.com/ReactTraining/react-router
45
[reach-router]: https://reach.tech/router
@@ -476,6 +477,40 @@ As with `Route` from `react-router-dom`, `<SecureRoute>` can take one of:
476477

477478
`LoginCallback` handles the callback after the redirect to and back from the Okta-hosted login page. By default, it parses the tokens from the uri, stores them, then redirects to `/`. If a `SecureRoute` caused the redirect, then the callback redirects to the secured route. For more advanced cases, this component can be copied to your own source tree and modified as needed.
478479

480+
#### errorComponent
481+
482+
By default, LoginCallback will display any errors from `authState.error`. If you wish to customise the display of such error messages, you can pass your own component as an `errorComponent` prop to `<LoginCallback>`. The `authState.error` value will be passed to the `errorComponent` as the `error` prop.
483+
484+
#### onAuthResume
485+
486+
When an external auth (such as a social IDP) redirects back to your application AND your Okta sign-in policies require additional authentication factors before authentication is complete, the redirect to your application redirectUri callback will be an `interaction_required` error.
487+
488+
An `interaction_required` error is an indication that you should resume the authentication flow. You can pass an `onAuthResume` function as a prop to `<LoginCallback>`, and the `<LoginCallback>` will call the `onAuthResume` function when an `interaction_required` error is returned to the redirectUri of your application.
489+
490+
If using the [Okta SignIn Widget][], redirecting to your login route will allow the widget to automatically resume your authentication transaction.
491+
492+
```jsx
493+
// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route
494+
// This code is wherever you have your <Security> component, which must be inside your <Router> for react-router
495+
const onAuthResume = async () => {
496+
history.push('/login');
497+
};
498+
499+
return (
500+
<Security
501+
oktaAuth={oktaAuth}
502+
restoreOriginalUri={restoreOriginalUri}
503+
>
504+
<Switch>
505+
<SecureRoute path='/protected' component={Protected} />
506+
<Route path='/login/callback' render={ (props) => <LoginCallback {...props} onAuthResume={ onAuthResume } /> } />
507+
<Route path='/login' component={CustomLogin} />
508+
<Route path='/' component={Home} />
509+
</Switch>
510+
</Security>
511+
);
512+
```
513+
479514
### `withOktaAuth`
480515

481516
`withOktaAuth` is a [higher-order component][] which injects an [oktaAuth][Okta Auth SDK] instance and an [authState][AuthState] object as props into the component. Function-based components will want to use the `useOktaAuth` hook instead. These props provide a way for components to make decisions based on [authState][AuthState] or to call [Okta Auth SDK][] methods, such as `.signInWithRedirect()` or `.signOut()`. Components wrapped in `withOktaAuth()` need to be a child or descendant of a `<Security>` component to have the necessary context.

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@
3939
"yarn": "^1.7.0"
4040
},
4141
"dependencies": {
42-
"@babel/runtime": "^7.11.2"
42+
"@babel/runtime": "^7.11.2",
43+
"@okta/okta-auth-js": "^4.8.0"
4344
},
4445
"peerDependencies": {
45-
"@okta/okta-auth-js": "^4.1.0",
4646
"@types/react-router-dom": "^5.1.6",
4747
"react": ">=16.8.0",
4848
"react-dom": ">=16.8.0",
@@ -57,7 +57,6 @@
5757
"@babel/preset-env": "^7.11.5",
5858
"@babel/preset-react": "^7.10.4",
5959
"@babel/register": "^7.12.1",
60-
"@okta/okta-auth-js": "^4.1.2",
6160
"@rollup/plugin-babel": "^5.2.1",
6261
"@rollup/plugin-replace": "^2.3.4",
6362
"@types/enzyme": "^3.10.8",

src/LoginCallback.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,28 @@
1111
*/
1212

1313
import * as React from 'react';
14-
import { useOktaAuth } from './OktaContext';
14+
import { useOktaAuth, OnAuthResumeFunction } from './OktaContext';
1515
import OktaError from './OktaError';
1616

1717
const LoginCallback: React.FC<{
18-
errorComponent?: React.ComponentType<{ error: Error }>
19-
}> = ({ errorComponent }) => {
18+
errorComponent?: React.ComponentType<{ error: Error }>,
19+
onAuthResume?: OnAuthResumeFunction,
20+
}> = ({ errorComponent, onAuthResume }) => {
2021
const { oktaAuth, authState } = useOktaAuth();
2122
const authStateReady = !authState.isPending;
22-
2323
const ErrorReporter = errorComponent || OktaError;
2424

2525
React.useEffect(() => {
26-
oktaAuth.handleLoginRedirect();
26+
27+
if (onAuthResume && oktaAuth.isInteractionRequired?.() ) {
28+
onAuthResume();
29+
return;
30+
}
31+
oktaAuth.handleLoginRedirect()
32+
.catch( err => {
33+
console.log(err); //TODO: handle these errors OKTA-361608
34+
});
35+
2736
}, [oktaAuth]);
2837

2938
if(authStateReady && authState.error) {

src/OktaContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import * as React from 'react';
1313
import { AuthState, OktaAuth } from '@okta/okta-auth-js';
1414

1515
export type OnAuthRequiredFunction = (oktaAuth: OktaAuth) => Promise<void> | void;
16+
export type OnAuthResumeFunction = () => void;
1617

1718
export type RestoreOriginalUriFunction = (oktaAuth: OktaAuth, originalUri: string) => Promise<void> | void;
1819

src/SecureRoute.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const SecureRoute: React.FC<{
5555
if(!authState.isAuthenticated && !authState.isPending) {
5656
handleLogin();
5757
}
58+
5859
}, [
5960
authState.isPending,
6061
authState.isAuthenticated,

test/e2e/harness/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.0.8",
44
"private": true,
55
"dependencies": {
6-
"@okta/okta-auth-js": "^4.1.2",
6+
"@okta/okta-auth-js": "^4.8.0",
77
"@okta/okta-react": "*",
88
"@types/node": "^14.14.7",
99
"@types/react": "^16.9.56",

test/e2e/harness/public/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
Learn how to configure a non-root public URL by running `npm run build`.
2121
-->
2222
<title>React App</title>
23+
<script src="https://global.oktacdn.com/okta-signin-widget/5.4.0/js/okta-sign-in.min.js" type="text/javascript"></script>
24+
<link href="https://global.oktacdn.com/okta-signin-widget/5.4.0/css/okta-sign-in.min.css" type="text/css" rel="stylesheet"/>
2325
</head>
2426
<body>
2527
<noscript>

test/e2e/harness/src/App.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@ import { Security, LoginCallback, SecureRoute } from '@okta/okta-react';
1717
import Home from './Home';
1818
import Protected from './Protected';
1919
import CustomLogin from './CustomLogin';
20+
import WidgetLogin from './WidgetLogin';
2021
import SessionTokenLogin from './SessionTokenLogin';
2122

2223
const App: React.FC<{
2324
oktaAuth: OktaAuth,
24-
customLogin: boolean
25-
}> = ({ oktaAuth, customLogin }) => {
25+
customLogin: boolean,
26+
baseUrl: string,
27+
}> = ({ oktaAuth, customLogin, baseUrl }) => {
2628
const history = useHistory();
2729

2830
const onAuthRequired = async () => {
2931
history.push('/login');
3032
};
3133

34+
const onAuthResume = async () => {
35+
history.push('/widget-login');
36+
};
37+
3238
const restoreOriginalUri = async (_oktaAuth: OktaAuth, originalUri: string) => {
3339
history.replace(toRelativeUrl(originalUri, window.location.origin));
3440
};
@@ -41,12 +47,13 @@ const App: React.FC<{
4147
restoreOriginalUri={restoreOriginalUri}
4248
>
4349
<Switch>
44-
<Route path='/login' component={CustomLogin}/>
45-
<Route path='/sessionToken-login' component={SessionTokenLogin}/>
46-
<SecureRoute exact path='/protected' component={Protected}/>
50+
<Route path='/login' component={CustomLogin} />
51+
<Route path='/widget-login' render={ (props) => <WidgetLogin {...props} baseUrl={baseUrl} /> }/>
52+
<Route path='/sessionToken-login' component={SessionTokenLogin} />
53+
<SecureRoute exact path='/protected' component={Protected} />
4754
<Route path='/implicit/callback' component={LoginCallback} />
48-
<Route path='/pkce/callback' component={LoginCallback} />
49-
<Route path='/' component={Home}/>
55+
<Route path='/pkce/callback' render={ (props) => <LoginCallback {...props} onAuthResume={ onAuthResume } /> } />
56+
<Route path='/' component={Home} />
5057
</Switch>
5158
</Security>
5259
<a href="/?pkce=1">PKCE Flow</a> | <a href="/">Implicit Flow</a>

test/e2e/harness/src/Home.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const Home: React.FC = () => {
4444
<Link to='/'>Home</Link><br/>
4545
<Link to='/protected'>Protected</Link><br/>
4646
<Link to='/sessionToken-login'>Session Token Login</Link><br/>
47+
<Link to='/widget-login'>Widget Login</Link><br/>
4748
{button}
4849
{ authState.isAuthenticated ? <button id="renew-id-token-button" onClick={renewToken('idToken')}>Renew ID Token</button> : null }
4950
{ authState.isAuthenticated ? <button id="renew-access-token-button" onClick={renewToken('accessToken')}>Renew Access Token</button> : null }

0 commit comments

Comments
 (0)