Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Okta React SDK

npm versionbuild status

Okta React SDK builds on top of the Okta Auth SDK.

This SDK is a toolkit to build Okta integration with many common "router" packages, such as react-router, reach-router, and others.

Users migrating from version 1.x of this SDK that required react-router should see Migrating from 1.x to learn what changes are necessary.

With the Okta Auth SDK, you can:

  • Login and logout from Okta using the OAuth 2.0 API
  • Retrieve user information
  • Determine authentication status
  • Validate the current user's session

All of these features are supported by this SDK. Additionally, using this SDK, you can:

This SDK does not provide any UI components.

This SDK does not currently support Server Side Rendering (SSR)

This library currently supports:

Release Status

✔️ The current stable major version series is: 6.x

VersionStatus
6.x✔️ Stable
5.x✔️ Stable
4.x⚠️ Retiring on 2021-12-09
3.x⚠️ Retiring on 2021-08-20
2.x❌ Retired
1.x❌ Retired

The latest release can always be found on the [releases page][github-releases].

Getting Started

  • If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
  • An Okta Application, configured for Single-Page App (SPA) mode. This is done from the Okta Developer Console. When following the wizard, use the default properties. They are are designed to work with our sample applications.

Helpful Links

Installation

This library is available through npm.

Install @okta/okta-react

npm install --save @okta/okta-react

Install peer dependencies

npm install --save react
npm install --save react-dom
npm install --save react-router-dom
npm install --save @okta/okta-auth-js # requires at least version 5.3.1

Usage

okta-react provides the means to connect a React SPA with Okta OIDC information. Most commonly, you will connect to a router library such as react-router.

React-Router components (optional)

okta-react provides a number of pre-built components to connect a react-router-based SPA to Okta OIDC information. You can use these components directly, or use them as a basis for building your own components.

  • SecureRoute - A normal Route except authentication is needed to render the component.

General components

okta-react provides the necessary tools to build an integration with most common React-based SPA routers.

  • Security - Accepts oktaAuth instance (required) and additional configuration as props. This component acts as a React Context Provider that maintains the latest authState and oktaAuth instance for the downstream consumers. This context can be accessed via the useOktaAuth React Hook, or the withOktaAuth Higher Order Component wrapper from it's descendant component.
  • LoginCallback - A simple component which handles the login callback when the user is redirected back to the application from the Okta login site. <LoginCallback> accepts an optional prop errorComponent that will be used to format the output for any error in handling the callback. This component will be passed an error prop that is an error describing the problem. (see the <OktaError> component for the default rendering)

Users of routers other than react-router can use useOktaAuth to see if authState is not null and authState.isAuthenticated is true. If it is false, you can send them to login via oktaAuth.signInWithRedirect(). See the implementation of <LoginCallback> as an example.

Available Hooks

These hooks can be used in a component that is a descendant of a Security component (<Security> provides the necessary context). Class-based components can gain access to the same information via the withOktaAuth Higher Order Component, which provides oktaAuth and authState as props to the wrapped component.

  • useOktaAuth - gives an object with two properties:
    • oktaAuth - the Okta Auth SDK instance.
    • authState - the AuthState object that shows the current authentication state of the user to your app (initial state is null).

Minimal Example in React Router

Create Routes

This example defines 3 routes:

  • / - Anyone can access the home page
  • /protected - Protected is only visible to authenticated users
  • /login/callback - This is where auth is handled for you after redirection

Note: Make sure you have the /login/callback url (absolute url) added in your Okta App's configuration.

A common mistake is to try and apply an authentication requirement to all pages, THEN add an exception for the login page. This often fails because of how routes are evaluated in most routing packages. To avoid this problem, declare specific routes or branches of routes that require authentication without exceptions.

Creating React Router Routes with class-based components

// src/App.jsimportReact,{Component}from'react';import{BrowserRouterasRouter,Route,withRouter}from'react-router-dom';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';importHomefrom'./Home';importProtectedfrom'./Protected';classAppextendsComponent{constructor(props){super(props);this.oktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});this.restoreOriginalUri=async(_oktaAuth,originalUri)=>{props.history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};}render(){return(<SecurityoktaAuth={this.oktaAuth}restoreOriginalUri={this.restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}constAppWithRouterAccess=withRouter(App);exportdefaultclassextendsComponent{render(){return(<Router><AppWithRouterAccess/></Router>);}}

Creating React Router Routes with function-based components

importReactfrom'react';import{SecureRoute,Security,LoginCallback}from'@okta/okta-react';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';import{BrowserRouterasRouter,Route,useHistory}from'react-router-dom';importHomefrom'./Home';importProtectedfrom'./Protected';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});constApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'component={LoginCallback}/></Security>);};constAppWithRouterAccess=()=>(<Router><App/></Router>);exportdefaultAppWithRouterAccesss;

Show Login and Logout Buttons (class-based)

// src/Home.jsimportReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classHomeextendsComponent{constructor(props){super(props);this.login=this.login.bind(this);this.logout=this.logout.bind(this);}asynclogin(){this.props.oktaAuth.signInWithRedirect();}asynclogout(){this.props.oktaAuth.signOut('/');}render(){if(!this.props.authState)return<div>Loading...</div>;returnthis.props.authState.isAuthenticated ?
<buttononClick={this.logout}>Logout</button> :
<buttononClick={this.login}>Login</button>;}});

Show Login and Logout Buttons (function-based)

// src/Home.jsconstHome=()=>{const{ oktaAuth, authState }=useOktaAuth();constlogin=async()=>oktaAuth.signInWithRedirect();constlogout=async()=>oktaAuth.signOut('/');if(!authState){return<div>Loading...</div>;}if(!authState.isAuthenticated){return(<div><p>Not Logged in yet</p><buttononClick={login}>Login</button></div>);}return(<div><p>Logged in!</p><buttononClick={logout}>Logout</button></div>);};exportdefaultHome;

Use the Access Token (class-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{Component}from'react';import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth(classMessageListextendsComponent{constructor(props){super(props)this.state={messages: null}}asynccomponentDidMount(){try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+this.props.authState.accessToken}});constdata=awaitresponse.json();this.setState({messages: data.messages});}catch(err){// handle error as needed}}render(){if(!this.state.messages)return<div>Loading...</div>;constitems=this.state.messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;}});

Use the Access Token (function-based)

When your users are authenticated, your React application has an access token that was issued by your Okta Authorization server. You can use this token to authenticate requests for resources on your server or API. As a hypothetical example, let's say you have an API that provides messages for a user. You could create a MessageList component that gets the access token and uses it to make an authenticated request to your server.

Here is what the React component could look like for this hypothetical example:

importfetchfrom'isomorphic-fetch';importReact,{useState,useEffect}from'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMessageList=()=>{const{ authState }=useOktaAuth();const[messages,setMessages]=useState(null);useEffect(()=>{if(authState.isAuthenticated){constapiCall=async()=>{try{constresponse=awaitfetch('http://localhost:{serverPort}/api/messages',{headers: {Authorization: 'Bearer '+authState.accessToken.accessToken}});constdata=awaitresponse.json();setMessages(data.messages);}catch(err){// handle error as needed}}apiCall();}},[authState]);if(!messages)return<div>Loading...</div>;constitems=messages.map(message=><likey={message}>{message}</li>);return<ul>{items}</ul>;};

Reference

Security

<Security> is the top-most component of okta-react. It accepts oktaAuth instance and addtional configuration options as props.

oktaAuth

(required) The pre-initialized oktaAuth instance. See Configuration Reference for details of how to initialize the instance.

restoreOriginalUri

(required) Callback function. Called to restore original URI during oktaAuth.handleLoginRedirect() is called. Will override restoreOriginalUri option of oktaAuth

onAuthRequired

(optional) Callback function. Called when authentication is required. If this is not supplied, okta-react redirects to Okta. This callback will receive oktaAuth instance as the first function parameter. This is triggered when a SecureRoute is accessed without authentication. A common use case for this callback is to redirect users to a custom login route when authentication is required for a SecureRoute.

Example

import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constcustomAuthHandler=(oktaAuth)=>{// Redirect to the /login page that has a CustomLoginComponent// This example is specific to React-Routerhistory.push('/login');};constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri||'/',window.location.origin));};return(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}restoreOriginalUri={restoreOriginalUri}><Routepath='/login'component={CustomLoginComponent}>{/* some routes here */}</Security>
);
};

PKCE Example

Assuming you have configured your application to allow the Authorization code grant type, you can implement the PKCE flow with the following steps:

  • Initialize [oktaAuth](Okta Auth SDK) instance (with default PKCE configuration as true) and pass it to the Security component.
  • add /login/callback route with LoginCallback component to handle login redirect from OKTA.
import{OktaAuth}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback',});classAppextendsComponent{render(){return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Routepath='/'exact={true}component={Home}/><Routepath='/login/callback'component={LoginCallback}/></Security>);}}

SecureRoute

SecureRoute ensures that a route is only rendered if the user is authenticated. If the user is not authenticated, it calls onAuthRequired if it exists, otherwise, it redirects to Okta.

onAuthRequired

SecureRoute accepts onAuthRequired as an optional prop, it overrides onAuthRequired from the Security component if exists.

errorComponent

SecureRoute runs internal handleLogin process which may throw Error when authState.isAuthenticated is false. By default, the Error will be rendered with OktaError component. If you wish to customise the display of such error messages, you can pass your own component as an errorComponent prop to <SecureRoute>. The error value will be passed to the errorComponent as the error prop.

react-router related props

SecureRoute integrates with react-router. Other routers will need their own methods to ensure authentication using the hooks/HOC props provided by this SDK.

As with Route from react-router-dom, <SecureRoute> can take one of:

  • a component prop that is passed a component
  • a render prop that is passed a function that returns a component. This function will be passed any additional props that react-router injects (such as history or match)
  • children components

LoginCallback

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.

errorComponent

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.

loadingElement

By default, LoginCallback will display nothing during handling the callback. If you wish to customize this, you can pass your React element (not component) as loadingElement prop to <LoginCallback>. Example: <p>Loading...</p>

onAuthResume

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.

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.

If using the Okta SignIn Widget, redirecting to your login route will allow the widget to automatically resume your authentication transaction.

// Example assumes you are using react-router with a customer-hosted Okta SignIn Widget on your /login route// This code is wherever you have your <Security> component, which must be inside your <Router> for react-routerconstonAuthResume=async()=>{history.push('/login');};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}><Switch><SecureRoutepath='/protected'component={Protected}/><Routepath='/login/callback'render={(props)=><LoginCallback{...props}onAuthResume={onAuthResume}/>}/><Routepath='/login'component={CustomLogin}/><Routepath='/'component={Home}/></Switch></Security>);

withOktaAuth

withOktaAuth is a higher-order component which injects an oktaAuth instance and an 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 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.

useOktaAuth

useOktaAuth() is a React Hook that returns an object containing the authState object and the oktaAuth instance. Class-based components will want to use the withOktaAuth HOC instead. Using this hook will trigger a re-render when the authState object updates. Components calling this hook need to be a child or descendant of a <Security> component to have the necessary context.

Using useOktaAuth

importReactfrom'react';import{useOktaAuth}from'@okta/okta-react';exportdefaultMyComponent=()=>{const{ authState }=useOktaAuth();if(!authState){return<div>Loading...</div>;}if(authState.isAuthenticated){return<div>Hello User!</div>;}return<div>You need to login</div>;};

Migrating between versions

Migrating from 5.x to 6.x

@okta/okta-react 6.x requires @okta/okta-auth-js 5.x (see notes for migration). Some changes affects @okta/okta-react:

  • Initial AuthState is null
  • Removed isPending from AuthState
  • Default value for originalUri is null

Migrating from 4.x to 5.x

From version 5.0, the Security component explicitly requires prop restoreOriginalUri to decouple from react-router. Example of implementation of this callback for react-router:

import{Security}from'@okta/okta-react';import{useHistory}from'react-router-dom';import{OktaAuth,toRelativeUrl}from'@okta/okta-auth-js';constoktaAuth=newOktaAuth({issuer: 'https://{yourOktaDomain}.com/oauth2/default',clientId: '{clientId}',redirectUri: window.location.origin+'/login/callback'});exportdefaultApp=()=>{consthistory=useHistory();constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{history.replace(toRelativeUrl(originalUri,window.location.origin));};return(<SecurityoktaAuth={oktaAuth}restoreOriginalUri={restoreOriginalUri}>{/* some routes here */}</Security>);};

Note: If you use basename prop for <BrowserRouter>, use this implementation to fix basename duplication problem:

import{toRelativeUrl}from'@okta/okta-auth-js';constrestoreOriginalUri=async(_oktaAuth,originalUri)=>{constbasepath=history.createHref({});constoriginalUriWithoutBasepath=originalUri.replace(basepath,'/');history.replace(toRelativeUrl(originalUriWithoutBasepath,window.location.origin));};

Migrating from 3.x to 4.x

Updating the Security component

From version 4.0, the Security component starts to explicitly accept oktaAuth instance as prop to replace the internal authService instance. You will need to replace the Okta Auth SDK related configurations with a pre-initialized oktaAuth instance.

Note
  • @okta/okta-auth-js is now a peer dependency for this SDK. You must add @okta/okta-auth-js as a dependency to your project and install it separately from @okta/okta-react.
  • <Security> still accept onAuthRequired as a prop.
import{OktaAuth}from'@okta/okta-auth-js';import{Security}from'@okta/okta-react';constoktaAuth=newOktaAuth(oidcConfig);exportdefault()=>(<SecurityoktaAuth={oktaAuth}onAuthRequired={customAuthHandler}>
// children component
</Security>);

Replacing authService instance

The authService module has been removed since version 4.0. The useOktaAuth hook and withOktaAuth HOC are exposing oktaAuth instead of authService.

  • Replace authService with oktaAuth when use useOktaAuth

    import{useOktaAuth}from'@okta/okta-react';exportdefault()=>{const{ oktaAuth, authState }=useOktaAuth();// handle rest component logic};
  • Replace props.authService with props.oktaAuth when use withOktaAuth

    import{withOktaAuth}from'@okta/okta-react';exportdefaultwithOktaAuth((props)=>{// use props.oktaAuth});

Replacing authService public methods

The oktaAuth instance exposes similar public methods to handle logic for the removed authService module.

  • login is removed

    This method called onAuthRequired, if it was set in the config options, or redirect if no onAuthRequired option was set. If you had code that was calling this method, you may either call your onAuthRequired function directly or signInWithRedirect.

  • redirect is replaced by signInWithRedirect

  • logout is replaced by signOut

    logout accepted either a string or an object as options. signOut accepts only an options object.

    If you had code like this:

    authService.logout('/goodbye');

    it should be rewritten as:

    oktaAuth.signOut({postLogoutRedirectUri: window.location.origin+'/goodbye'});

    Note that the value for postLogoutRedirectUri must be an absolute URL. This URL must also be on the "allowed list" in your Okta app's configuration. If no options are passed or no postLogoutRedirectUri is set on the options object, it will redirect to window.location.origin after sign out is complete.

  • getAccessToken and getIdToken have been changed to synchronous methods

    With maintaining in-memory AuthState since Okta Auth SDK version 4.1, token values can be accessed in synchronous manner.

  • handleAuthentication is replaced by handleLoginRedirect

    handleLoginRedirect is called by the OktaLoginCallback component as the last step of the login redirect authorization flow. It will obtain and store tokens and then call restoreOriginalUri which will return the browser to the originalUri which was set before the login redirect flow began.

  • authState related methods have been collected in Okta Auth SDK AuthStateManager

    • Change authService.updateAuthState to oktaAuth.authStateManager.updateAuthState
    • Change authService.getAuthState to oktaAuth.authStateManager.getAuthState
    • Change on to oktaAuth.authStateManager.subscribe
    • clearAuthState, emitAuthState and emit have been removed
  • By default isAuthenticated will be true if both accessToken and idToken are valid

    If you have a custom isAuthenticated function which implements the default logic, you should remove it.

  • getTokenManager has been removed

    You may access the TokenManager with the tokenManager property:

    consttokens=oktaAuth.tokenManager.getTokens();

Migrating from 2.x to 3.x

See breaking changes for version 3.0

Migrating from 1.x to 2.0

The 1.x series for this SDK required the use of react-router. These instructions assume you are moving to version 2.0 of this SDK and are still using React Router (v5+)

Replacing Security component

The <Security> component is now a generic (not router-specific) provider of Okta context for child components and is required to be an ancestor of any components using the useOktaAuth hook, as well as any components using the withOktaAuth Higher Order Component.

Auth.js has been renamed AuthService.js.

The auth prop to the <Security> component is now authService. The other prop options to <Security> have not changed from the 1.x series to the 2.0.x series

Replacing the withAuth Higher-Order Component wrapper

This SDK now provides authentication information via React Hooks (see useOktaAuth). If you want a component to receive the auth information as a direct prop to your class-based component, you can use the withOktaAuth wrapper where you previously used the withAuth wrapper. The exact props provided have changed to allow for synchronous access to authentication information. In addition to the authService object prop (previously auth), there is also an authState object prop that has properties for the current authentication state.

Replacing .isAuthenticated(), .getAccessToken(), and .getIdToken() inside a component

Two complications of the 1.x series of this SDK have been simplified in the 2.x series:

  • These functions were asynchronous (because the retrieval layer underneath them can be asynchronous) which made avoiding race conditions in renders/re-renders tricky.
  • Recognizing when authentication had yet to be decided versus when it had been decided and was not authenticated was an unclear difference between null, true, and false.

To resolve these the authService object holds the authentication information and provides it synchronously (following the first async determination) as an authState object. While waiting on that first determination, the authState object is null. When the authentication updates the authService object will emit an authStateChange event after which a new authState object is available.

Any component that was using withAuth() to get the auth object and called the properties above has two options to migrate to the new SDK:

  1. Replace the use of withAuth() with withOktaAuth(), and replace any of these asynchronous calls to the auth methods with the values of the related authState properties. OR
  2. Remove the use of withAuth() and instead use the useOktaAuth() React Hook to get the authService and authState objects. Any use of the auth methods (.isAuthenticated(), .getAccessToken(), and .getIdToken()) should change to use the already calculated properties of authState.

To use either of these options, your component must be a descendant of a <Security> component, in order to have the necessary context.

These changes should result in less complexity within your components as these values are now synchronously available after the initial determination.

If you need access to the authService instance directly, it is provided by withOktaAuth() as a prop or is available via the useOktaAuth() React Hook. You can use the examples in this README to see how to use authService to perform common tasks such as login/logout, or inspect the provided <LoginCallback> component to see an example of the use of the authService managing the redirect from the Okta site.

Updating your ImplicitCallback component

  • If you were using the provided ImplicitCallback component, you can replace it with LoginCallback
  • If you were using a modified version of the provided ImplicitCallback component, you will need to examine the new version to see the changes. It may be easier to start with a copy of the new LoginCallback component and copy your changes to it. If you want to use a class-based version of LoginCallback, wrap the component in the [withOktaAuth][] HOC to have the authService and authState properties passed as props.
  • If you had your own component that handled the redirect-back-to-the-application after authentication, you should examine the new LoginCallback component as well as the notes in this migration section about the changes to .isAuthenticated(), .getAccessToken(), and .getIdToken().

Contributing

We welcome contributions to all of our open-source packages. Please see the contribution guide to understand how to structure a contribution.

Development

Installing dependencies for contributions

We use yarn for dependency management when developing this package:

yarn install

Commands

CommandDescription
yarn installInstall dependencies
yarn startStart the sample app using the SDK
yarn testRun unit and integration tests
yarn lintRun eslint linting tests

About

Okta OIDC SDK for React

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages