Integrating Keycloak in React & Next.js applications
January 09, 2022
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
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 hereexport 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