Okta Sign-In Widget and React
On This Page
This guide will walk you through integrating authentication into a React app with Okta by performing these steps:
- Add an OpenID Connect Client in Okta
- Create a React App
- Install Dependencies
- Create a Widget Wrapper
- Create Routes
- Connect the Routes
- Start Your App
Prerequisites
If you do not already have a Developer Edition Account, you can create one at https://developer.okta.com/signup/.
Add an OpenID Connect Client in Okta
- Sign in to the Okta Developer Dashboard, and select Create New App
- Choose Single Page App (SPA) as the platform, then populate your new OpenID Connect app with values similar to:
Setting | Value |
---|---|
App Name | OpenId Connect App (must be unique) |
Login redirect URIs | http://localhost:3000/implicit/callback |
Logout redirect URIs | http://localhost:3000/login |
Allowed grant types | Authorization Code |
Note: CORS is automatically enabled for the granted login redirect URIs.
Create a React App
To quickly create a React app, we recommend using Create React App.
npx create-react-app okta-app
cd okta-app
If you need more information, see the Create React App getting started guide.
Install Dependencies
A simple way to add authentication into a React app is using the Okta Sign-In Widget library. We can install it via npm
:
cd okta-app
npm install @okta/okta-signin-widget
We'll also need @okta/okta-react
and react-router-dom
to manage our routes:
npm install @okta/okta-react react-router-dom
Create a Widget Wrapper
To provide a fully-featured and customizable sign-in experience, the Okta Sign-In Widget is available to handle User Lifecycle operations, MFA, and more. To render the Sign-In Widget in React, we must create a wrapper that allows us to treat it as a React component.
Create a src/OktaSignInWidget.js
file:
// src/OktaSignInWidget.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import OktaSignIn from '@okta/okta-signin-widget';
import '@okta/okta-signin-widget/dist/css/okta-sign-in.min.css';
export default class OktaSignInWidget extends Component {
componentDidMount() {
const el = ReactDOM.findDOMNode(this);
this.widget = new OktaSignIn({
baseUrl: this.props.baseUrl,
authParams: {
// If your app is configured to use the Implicit Flow
// instead of the Authorization Code with Proof of Code Key Exchange (PKCE)
// you will need to uncomment the below line
// pkce: false
}
});
this.widget.renderEl({el}, this.props.onSuccess, this.props.onError);
}
componentWillUnmount() {
this.widget.remove();
}
render() {
return <div />;
}
};
Create Routes
Some routes require authentication in order to render. Defining those routes is easy using SecureRoute
from @okta/okta-react
. Let's take a look at what routes are needed for this example:
/
: A default page to handle basic control of the app./protected
: A route protected bySecureRoute
./login
: Show the sign-in page./implicit/callback
: A route to parse tokens after a redirect.
/
First, create src/Home.js
to provide links to navigate our app:
// src/Home.js
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { withOktaAuth } from '@okta/okta-react';
export default withOktaAuth(class Home extends Component {
constructor(props) {
super(props);
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
}
async login() {
this.props.authService.login('/');
}
async logout() {
this.props.authService.logout('/');
}
render() {
if (this.props.authState.isPending) return null;
const button = this.props.authState.isAuthenticated ?
<button onClick={this.logout}>Logout</button> :
<button onClick={this.login}>Login</button>;
return (
<div>
<Link to='/'>Home</Link><br/>
<Link to='/protected'>Protected</Link><br/>
{button}
</div>
);
}
});
/protected
This route will only be visible to users with a valid accessToken
.
Create a new component src/Protected.js
:
// src/Protected.js
import React from 'react';
export default () => <h3>Protected</h3>;
/login
This route hosts the Sign-In Widget and redirects if the user is already logged in. If the user is coming from a protected page, they'll be redirected back to the page upon login.
Create a new component src/Login.js
:
// src/Login.js
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import OktaSignInWidget from './OktaSignInWidget';
import { withOktaAuth } from '@okta/okta-react';
export default withOktaAuth(class Login extends Component {
constructor(props) {
super(props);
this.onSuccess = this.onSuccess.bind(this);
this.onError = this.onError.bind(this);
}
onSuccess(res) {
if (res.status === 'SUCCESS') {
return this.props.authService.redirect({
sessionToken: res.session.token
});
} else {
// The user can be in another authentication state that requires further action.
// For more information about these states, see:
// https://github.com/okta/okta-signin-widget#rendereloptions-success-error
}
}
onError(err) {
console.log('error logging in', err);
}
render() {
if (this.props.authState.isPending) return null;
return this.props.authState.isAuthenticated ?
<Redirect to={{ pathname: '/' }}/> :
<OktaSignInWidget
baseUrl={this.props.baseUrl}
onSuccess={this.onSuccess}
onError={this.onError}/>;
}
});
/implicit/callback
The component for this route (LoginCallback) comes with @okta/okta-react
. It handles token parsing, token storage, and redirecting to a protected page if one triggered the login.
Connect the Routes
Our example is using react-router-dom
. By default you can include your components and Routes in src/App.js
. If you need access to particular router properties, such as the history
object that we use to override the default login flow, you need to create a wrapper component around <Router>
.
Update src/App.js
to create a Router and call <AppWithRouterAccess
>` as a child component:
// src/App.js
import React, { Component } from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import AppWithRouterAccess from './AppWithRouterAccess';
class App extends Component {
render() {
return (
<Router>
<AppWithRouterAccess/>
</Router>
);
}
}
export default App;
Create src/AppWithRouterAccess.js
and include your project components and routes. Security
is the component that controls the authentication flows, so it requires your OpenId Connect configuration. By default, @okta/okta-react
redirects to Okta's login page when the user isn't authenticated. In this example, onAuthRequired
is overridden to redirect to the custom login route instead:
// src/AppWithRouterAccess.jsx
import React, { Component } from 'react';
import { Route, withRouter } from 'react-router-dom';
import { Security, SecureRoute, LoginCallback } from '@okta/okta-react';
import Home from './Home';
import Login from './Login';
import Protected from './Protected';
export default withRouter(class AppWithRouterAccess extends Component {
constructor(props) {
super(props);
this.onAuthRequired = this.onAuthRequired.bind(this);
}
onAuthRequired() {
this.props.history.push('/login')
}
render() {
// Note: If your app is configured to use the Implicit Flow
// instead of the Authorization Code with Proof of Code Key Exchange (PKCE)
// you will need to add the below property to what is passed to <Security>
//
// pkce={false}
return (
<Security issuer='https://${yourOktaDomain}/oauth2/default'
clientId='{clientId}'
redirectUri={window.location.origin + '/implicit/callback'}
onAuthRequired={this.onAuthRequired} >
<Route path='/' exact={true} component={Home} />
<SecureRoute path='/protected' component={Protected} />
<Route path='/login' render={() => <Login baseUrl='https://${yourOktaDomain}' />} />
<Route path='/implicit/callback' component={LoginCallback} />
</Security>
);
}
});
Start your app
Finally, start your app:
npm start
Conclusion
You have now successfully authenticated with Okta! Now what? With a user's id_token
, you have basic claims for the user's identity. You can extend the set of claims by modifying the scopes
to retrieve custom information about the user. This includes locale
, address
, groups
, and more.
Want to learn how to use the user's access_token
? Check out our React how to guide to learn about protecting routes on your server, validating the access_token
, and more!
Support
Have a question or see a bug? Post your question on the Okta Developer Forums.