Skip to content

React Frontend Integration

This guide will show you how PropelAuth makes it easy to integrate your full hosted authentication service into your React application. For the full React Library Reference, click here.

Quick example

The following example will display a different message for logged-in users vs logged out. We'll go into more detail about how it works and show more advanced examples below.

import {AuthProvider, withAuthInfo} from "@propelauth/react";

const App = withAuthInfo((props) => {
    // isLoggedIn and user are injected automatically from withAuthInfo
    if (props.isLoggedIn) {
        return <div>You are logged in as {props.user.email}</div>
    } else {
        return <div>You are not logged in</div>
    }
})

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        <AuthProvider authUrl={process.env.REACT_APP_AUTH_URL}> //(1)
            <App />
        </AuthProvider>
    </React.StrictMode>
);
  1. Your auth URL can be found in your PropelAuth dashboard. We are using an ENV variable because you will have a different URL for your test and production environment.

How it works

auth overview

When a user visits your frontend application, your frontend can make a request to PropelAuth to determine if the current user is logged in. If the user is logged in, you will receive a JSON Web Token (JWT) access token and the user’s metadata. For more information on JWTs, view our blog here. Once you have the user’s access token, your backend can validate and identify the token’s owner. This validation is done entirely on your backend and does not need to make any requests to PropelAuth. Access tokens are short-lived, and our libraries will refresh them both periodically and when the user switches tabs or reconnects to the internet.

auth frontend

A secure HTTP-only cookie is created once a user logs into your hosted authentication page. This cookie allows PropelAuth to identify logged-in users. In your production environment, we require you use a custom domain to avoid third-party cookie issues for your users. Browsers like Safari, for example, will block cookies across domains. For this reason, we include custom domains in all of our plans.

Configure

Go to your PropelAuth project and click Frontend Integration in the sidebar. You will see:

  • Port - The port your app runs on locally. The default for React is 3000. After entering 3000, your test environment will allow requests from http://localhost:3000.

  • Login Redirect Path - After a user logs in, they will be redirected here. For example, / will redirect them to http://localhost:3000/.

  • Logout Redirect Path - After a user logs out, they will be redirected here.
  • Auth URL - This is where your authentication pages are hosted, and you will need this for the setup step.

Installation

In your React app, install the @propelauth/react library.

$ npm install --save @propelauth/react
$ yarn add @propelauth/react

Set up AuthProvider

AuthProvider is the provider of a React context that manages the current user's access token and metadata. You cannot use the other hooks without it. AuthProvider manages authentication information and all other components fetches from it.

It is recommended to put the AuthProvider context at the top level of your application, so it never unmounts.

import {AuthProvider} from "@propelauth/react";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <AuthProvider authUrl={process.env.REACT_APP_AUTH_URL}> // (1)
        <YourApp/>
    </AuthProvider>,
    document.getElementById("root")
);
  1. The authUrl is the base URL where your authentication pages are hosted. You can find this under the Frontend Integration section for your project.

RequiredAuthProvider

If your entire application requires a user to be logged in, you can instead use RequiredAuthProvider.

import {RequiredAuthProvider, RedirectToLogin} from "@propelauth/react";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <RequiredAuthProvider authUrl={process.env.REACT_APP_AUTH_URL} 
                          displayWhileLoading={<Loading/>} 
                          displayIfLoggedOut={<RedirectToLogin/>}>
        <YourApp/>
    </RequiredAuthProvider>,
    document.getElementById("root")
);

RequiredAuthProvider has two additional props:

  1. displayWhileLoading: A React element to display while the AuthProvider is fetching auth information. Defaults to an empty element
  2. displayIfLoggedOut: A React element to display if the current user is logged out. Defaults to <RedirectToLogin />

Get current user information

There are three options for getting the current user's information:

import {withAuthInfo} from '@propelauth/react';

function MinimalExample(props) {
    // isLoggedIn and user are injected automatically from withAuthInfo below
    if (props.isLoggedIn) {
        return <div>You are logged in as {props.user.email}</div>
    } else {
        return <div>You are not logged in</div>
    }
}

export default withAuthInfo(MinimalExample); // (1)
  1. A React Higher-Order Component that provides common values like isLoggedIn and accessToken. These values are injected into the props of your component.
import {withRequiredAuthInfo} from '@propelauth/react';

function MinimalExample(props) {
    // user is injected automatically from withRequiredAuthInfo below
    return <div>You are logged in as {props.user.email}</div>
}

export default withRequiredAuthInfo(MinimalExample); // (1)
  1. Similar to withAuthInfo, except if the user isn't logged in, they are redirected to the login page (that behavior is configurable).
import {useAuthInfo} from '@propelauth/react';

function MinimalExample() {
    const authInfo = useAuthInfo()

    // Unlike the higher order functions, we need to check the loading case now
    if (authInfo.loading) {
        return <div>Loading...</div>
    } else if (authInfo.isLoggedIn) {
        return <div>You are logged in as {props.user.email}</div>
    } else {
        return <div>You are not logged in</div>
    }
}

export default MinimalExample;

When is an external API call made?

The AuthProvider context manages all external API requests. The functions withAuthInfo, withRequiredAuthInfo, and useAuthInfo only extract information from requests without making their own requests. For this reason, you can (and should) add as many of these functions as you need.

withAuthInfo

withAuthInfo(Component, {
    displayWhileLoading: <div>Loading...</div>, // (1)
})
  1. A React element to display while the AuthProvider is fetching auth information. Defaults to an empty element

The code example above will inject the following props into Component:

Prop Description
accessToken If user is logged in, this string can access your APIs on behalf of the user. Otherwise, null.
isLoggedIn Returns user logged in status
orgHelper An object with useful functions for managing organizations
accessHelper An object with useful functions for accessing role and permissions (RBAC)
user If user is logged in, this contains metadata about them. Otherwise, null

withRequiredAuthInfo

withRequiredAuthInfo(Component, {
    displayWhileLoading: <div>Loading...</div>, // (1)
    displayIfLoggedOut: <div>You are logged out</div> // (2)
})
  1. A React element to display while the AuthProvider is fetching auth information. Defaults to an empty element
  2. A React element to display if the current user is logged out. Defaults to <RedirectToLogin />

This is identical to withAuthInfo, except Component is only rendered if the user is logged in. You are guaranteed that isLoggedIn is true and the accessToken is not null.

useAuthInfo

function Component() {
    const authInfo = useAuthInfo()
    // ...rest of the component
}

A React hook which gets auth information. authInfo contains:

Key Description
loading True if the AuthProvider is still fetching auth information. This will only happen once when the application is first loaded.
accessToken If user is logged in, this string can access your APIs on behalf of the user. Otherwise, null.
isLoggedIn Returns user logged in status
orgHelper An object with useful functions for managing organizations
accessHelper An object with useful functions for accessing role and permissions (RBAC)
user If user is logged in, this contains metadata about them. Otherwise, null

Other utilities

  • useLogoutFunction - Returns a function for logging out the current user.

  • useRedirectFunctions - Returns a set of functions to redirect the user to different pages (e.g. signup, login).

For a complete list of utilities, see the React Library Reference. Alternatively, our guides will walk you through the process of creating an entire application end to end.

Organizations

The orgHelper, provided by withAuthInfo, withRequiredAuthInfo, or useAuthInfo, helps manage the current user's organization information with ease. It's an object which has the following functions (types included):

type OrgHelper = {
    // returns all orgs that the user is a member of
    getOrgs: () => OrgMemberInfo[],
    // returns all org ids that the user is a member of
    getOrgIds: () => string[],
    // returns org information for a given orgId
    getOrg: (orgId: string) => OrgMemberInfo | undefined,
    // returns org information for a given org by name
    getOrgByName: (orgName: string) => OrgMemberInfo | undefined,
}

type OrgMemberInfo = {
    orgId: string,
    orgName: string,
    urlSafeOrgName: string
    // The role of the user within this organization
    userAssignedRole: string
    userPermissions: string[]
}

Roles and Permissions

Your users will have a role in an organization. By default, these roles are Owner, Admin, and Member - but you can configure them. Each role can have permissions associated with them. See roles and permissions for more details.

The accessHelper, provided by withAuthInfo, withRequiredAuthInfo, or useAuthInfo, helps check the current user's role and permission(s) within a specific organization.

type AccessHelper = {
    isRole: (orgId: string, role: string) => boolean
    isAtLeastRole: (orgId: string, role: string) => boolean
    hasPermission: (orgId: string, permission: string) => boolean
    hasAllPermissions: (orgId: string, permissions: string[]) => boolean
}

Active Organization

Since users can be in more than one organization, one common use case is to pick a single organization that your user is currently operating within.

Commonly, developers use localStorage, a path parameter, or subdomain (e.g. https://CUSTOMER.yourproduct.com or https://app.yourproduct.com/CUSTOMER) to indicate which organization the user is currently operating within.

The AuthProvider and RequiredAuthProvider optionally take in a getActiveOrgFn which enables you to select the currently active organization, like so:

// Get the active org from a path parameter grabbed from our router
<AuthProvider authUrl={AUTH_URL} getActiveOrgFn={() => router.query.orgName}>
  • useActiveOrg allows you to fetch the active organization later on. It will also verify that the current user is actually in that organization.
function OrgName() {
    const org = useActiveOrg()
    return <div>{org.orgName}</div>
}

Making an authenticated HTTP request

For authenticated requests on behalf of your user, you must provide an access token. There are many of ways to make HTTP requests in Javascript. You could use the Fetch API, XMLHttpRequest, or a library like axios.

Just like isLoggedIn and user, the access token is available from withAuthInfo. You provide it in the request in the Authorization header, like so:

Authorization: Bearer YOUR_ACCESS_TOKEN

Code sample of the Authorization with the Fetch API:

function whoAmI(accessToken) {
    return fetch("/whoami", {
        method: "GET",
        headers: {
            "Authorization": `Bearer ${accessToken}`,
        }
    })
}

Examples

For detailed examples, please see React Library Reference Examples.

Next Steps

Done with your frontend? Next you can integrate your backend.