Overview

This guide will walk you through integrating authentication into a React app with Okta by performing these steps:

  1. Add an OpenID Connect Client in Okta
  2. Create a React App
  3. Install Dependencies
  4. Create a Widget Wrapper
  5. Create Routes
  6. Connect the Routes
  7. 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

  • Log into the Okta Developer Dashboard, and 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

Note: CORS is automatically enabled for the granted login redirect URIs.

Create a React App

To quickly create a React app, we recommend the create-react-app CLI. Follow their guide here.

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 --save

We’ll also need @okta/okta-react and react-router-dom to manage our routes:

npm install @okta/okta-react react-router-dom --save

Create a Widget Wrapper

To provide a fully featured and customizable login 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';
import '@okta/okta-signin-widget/dist/css/okta-theme.css';

export default class OktaSignInWidget extends Component {
  componentDidMount() {
    const el = ReactDOM.findDOMNode(this);
    this.widget = new OktaSignIn({
      baseUrl: this.props.baseUrl
    });
    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. Lets 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 by SecureRoute.
  • /login: Show the login 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 { withAuth } from '@okta/okta-react';

export default withAuth(class Home extends Component {
  constructor(props) {
    super(props);
    this.state = { authenticated: null };
    this.checkAuthentication = this.checkAuthentication.bind(this);
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      this.setState({ authenticated });
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  render() {
    if (this.state.authenticated === null) return null;

    const button = this.state.authenticated ?
      <button onClick={this.props.auth.logout}>Logout</button> :
      <button onClick={this.props.auth.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 { withAuth } from '@okta/okta-react';

export default withAuth(class Login extends Component {
  constructor(props) {
    super(props);
    this.onSuccess = this.onSuccess.bind(this);
    this.onError = this.onError.bind(this);
    this.state = {
      authenticated: null
    };
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      this.setState({ authenticated });
    }
  }

  componentDidUpdate() {
    this.checkAuthentication();
  }

  onSuccess(res) {
    return this.props.auth.redirect({
      sessionToken: res.session.token
    });
  }

  onError(err) {
    console.log('error logging in', err);
  }
  
  render() {
    if (this.state.authenticated === null) return null;
    return this.state.authenticated ?
      <Redirect to={{ pathname: '/' }}/> :
      <OktaSignInWidget
        baseUrl={this.props.baseUrl}
        onSuccess={this.onSuccess}
        onError={this.onError}/>;
  }
});

/implicit/callback

The component for this route (ImplicitCallback) 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

Update src/App.js to 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/App.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { Security, SecureRoute, ImplicitCallback } from '@okta/okta-react';
import Home from './Home';
import Login from './Login';
import Protected from './Protected';

function onAuthRequired({history}) {
  history.push('/login');
}

class App extends Component {
  render() {
    return (
      <Router>
        <Security issuer='https://{yourOktaDomain}.com/oauth2/default'
                  client_id='{clientId}'
                  redirect_uri={window.location.origin + '/implicit/callback'}
                  onAuthRequired={onAuthRequired} >
          <Route path='/' exact={true} component={Home} />
          <SecureRoute path='/protected' component={Protected} />
          <Route path='/login' render={() => <Login baseUrl='https://{yourOktaDomain}.com' />} />
          <Route path='/implicit/callback' component={ImplicitCallback} />
        </Security>
      </Router>
    );
  }
}

export default App;

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 Quickstart integrations 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 Okta Developer Forums.