Integrating Keycloak in React & Next.js applications

2022-01-09

Keycloak is an Open Source Identity and Access Management solution for modern Applications and Services.

In this post, we will see how to integrate Keycloak into a React & Next.js Application.

Integrating in React application

Let's go ahead and install the keycloak javascript adapter and the react library for Keycloak.

Bash

npm install --save keycloak-js npm install --save @react-keycloak/web

or

Bash

yarn add keycloak-js yarn add @react-keycloak/web

Configure your Keycloak instance as needed by creating a keycloak.js file in your project's src folder with the following content:

Javascript

import Keycloak from 'keycloak-js'; const keycloakConfig = { url: 'http://localhost:8080/auth', realm: 'Demo-Realm', clientId: 'web-app', }; const keycloak = new Keycloak(keycloakConfig); export default keycloak;

💡 Hint

You can intialize Keyclock through a ./keycloak.json file by leaving the constructor value empty.

Javascript

const keycloak = new Keycloak();

Then Wrap your App inside KeycloakProvider and pass the keycloak instance as prop

React (JS)

import React from 'react'; import { KeycloakProvider } from '@react-keycloak/web'; import keycloak from './keycloak'; // If you are using other providers (such as react-redux) it is recommended to place them inside KeycloakProvider. const App = () => { return ( <KeycloakProvider keycloak={keycloak}> <div className="App">{/* place your router or application here */}</div> </KeycloakProvider> ); };

Integrating in SSR rendered Next.js application

Let's go ahead and install the keycloak javascript adapter and the react library for Keycloak.

Bash

npm install --save keycloak-js npm install --save @react-keycloak/ssr

or

Bash

yarn add keycloak-js yarn add @react-keycloak/ssr

Create the _app.tsx file under pages folder and wrap your App inside SSRKeycloakProvider component and pass keycloakConfig and a TokenPersistor.

Note: @react-keycloak/ssr provides a default TokenPersistor which works with cookies (exported as ServerPersistors.SSRCookies).

The following examples will be based on that.

React (TS)

import cookie from 'cookie'; import * as React from 'react'; import type { IncomingMessage } from 'http'; import type { AppProps, AppContext } from 'next/app'; import { SSRKeycloakProvider, SSRCookies } from '@react-keycloak/ssr'; const keycloakCfg = { realm: '', url: '', clientId: '', }; interface InitialProps { cookies: unknown; } function MyApp({ Component, pageProps, cookies }: AppProps & InitialProps) { return ( <SSRKeycloakProvider keycloakConfig={keycloakCfg} persistor={SSRCookies(cookies)}> <Component {...pageProps} /> </SSRKeycloakProvider> ); } function parseCookies(req: IncomingMessage) { return cookie.parse(req.headers.cookie || ''); } MyApp.getInitialProps = async (context: AppContext) => { // Extract cookies from AppContext return { cookies: context.ctx.req ? parseCookies(context.ctx.req) : {}, }; }; export default MyApp;

Integrating in Static Generated Next.js application

Let's go ahead and install the keycloak javascript adapter and the react library for Keycloak.

Bash

npm install --save keycloak-js npm install --save @react-keycloak/web

or

Bash

yarn add keycloak-js yarn add @react-keycloak/web

Create the _app.tsx file under pages folder and wrap your App inside KeycloakProvider component and pass keycloakConfig and a TokenPersistor.

Note: @react-keycloak/ssr provides a default TokenPersistor which works with cookies (exported as ServerPersistors.SSRCookies).

The following examples will be based on that.

React (TS)

import dynamic from 'next/dynamic'; import { ReactKeycloakProvider } from '@react-keycloak/web'; import LoadingScreen from 'components/LoadingScreen'; const App = ({ Component, pageProps }: AppProps): JSX.Element => { const Keycloak = typeof window !== 'undefined' ? require('keycloak-js') : null; const keycloak = Keycloak(); // will load instance configuration from keycloak.json const keycloakInitOptions = { onLoad: 'login-required' }; return ( <ReactKeycloakProvider authClient={keycloak} initOptions={keycloakInitOptions} LoadingComponent={<LoadingScreen />}> <Component {...pageProps} /> </ReactKeycloakProvider> ); }; // we have disabled SSR rendering here export default dynamic(() => Promise.resolve(App), { ssr: false, });

In the above example we have used a LoadingScreen component that will be rendered to the user till the keycloak adapter is initialized.

React (TS)

const keycloakInitOptions = { onLoad: 'login-required' };

This Initialization option makes Keycloak login immediately.

Conclusion

TODO.log