Fork of https://github.com/react-keycloak/react-keycloak.git with updated packages for Keycloak >=17. SSR bindings for Keycloak javascript adapter
npm install @react-keycloak-fork/ssrkeycloak-js 9.0.2 or later
shell
yarn add @react-keycloak-fork/ssr
`
or
`shell
npm install --save @react-keycloak-fork/ssr
`
Getting Started
This module has been created to support NextJS and Razzle, other SSR frameworks might be working as well.
$3
Follow the guide related to your SSR Framework and note that SSRKeycloakProvider also accepts all the properties of KeycloakProvider.
#### NextJS
Requires NextJS 9 or later
Create the _app.tsx file under pages folder and wrap your App inside SSRKeycloakProvider component and pass keycloakConfig and a TokenPersistor.
Note: @react-keycloak-fork/ssr provides a default TokenPersistor which works with cookies (exported as ServerPersistors.SSRCookies).
The following examples will be based on that.
`tsx
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-fork/ssr'
const keycloakCfg = {
realm: '',
url: '',
clientId: '',
}
interface InitialProps {
cookies: unknown
}
function MyApp({ Component, pageProps, cookies }: AppProps & InitialProps) {
return (
keycloakConfig={keycloakCfg}
persistor={SSRCookies(cookies)}
>
)
}
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
`
#### Razzle
Requires Razzle 3 or later
> N.B: This setup requires you to install cookie-parser middleware.
Edit your app server.js as follow
`js
...
import { ExpressCookies, SSRKeycloakProvider } from '@react-keycloak-fork/ssr'
// Create a function to retrieve Keycloak configuration parameters -- 'see examples/razzle-app'
import { getKeycloakConfig } from './utils'
const assets = require(process.env.RAZZLE_ASSETS_MANIFEST)
const server = express()
server
.disable('x-powered-by')
.use(express.static(process.env.RAZZLE_PUBLIC_DIR))
.use(cookieParser()) // 1. Add cookieParser Express middleware
.get('/*', (req, res) => {
const context = {}
// 2. Create an instance of ExpressCookies passing the current request
const cookiePersistor = ExpressCookies(req)
// 3. Wrap the App inside SSRKeycloakProvider
const markup = renderToString(
keycloakConfig={getKeycloakConfig()}
persistor={cookiePersistor}
>
)
...
})
...
`
Edit your client.js as follow
`js
import { Cookies, SSRKeycloakProvider } from '@react-keycloak-fork/ssr'
// Create a function to retrieve Keycloak configuration parameters -- 'see examples/razzle-app'
import { getKeycloakConfig } from './utils'
// 1. Create an instance of Cookies
const cookiePersistor = new Cookies()
// 2. Wrap the App inside SSRKeycloakProvider
hydrate(
keycloakConfig={getKeycloakConfig()}
persistor={cookiePersistor}
>
,
document.getElementById('root')
)
...
`
$3
When a component requires access to Keycloak, you can use the useKeycloak Hook.
`js
import { useKeycloak } from '@react-keycloak-fork/ssr'
export default () => {
const { keycloak, initialized } = useKeycloak()
// Here you can access the current keycloak instance methods and variables...
return (
{User is ${
!keycloak.authenticated ? 'NOT ' : ''
}authenticated}
{!!keycloak.authenticated && (
)}
)
}
`
Examples
See inside examples/nextjs-app and examples/razzle-app folders of @react-keycloak-fork/react-keycloak-examples repository for sample implementations.
Guides and Articles
- Migration guide for @react-keycloak-fork/ssr v2.x to v3.x can be found here MIGRATION.md.
Other Resources
$3
Whilst @react-keycloak-fork/ssr can help you secure the Frontend part of a NextJS app if you also want to secure NextJS-exposed APIs you can follow the sample in this issue.
Thanks to @webdeb for reporting the issue and helping develop a solution.
$3
If you need to access keycloak instance from non-React files (such as sagas, utils, providers ...), you can retrieve the instance using the exported getKeycloakInstance() method.
The instance will be initialized by react-keycloak but you'll need to be carefull when using the instance, expecially server-side, and avoid setting/overriding any props, you can however freely access the exposed methods (such as refreshToken, login, etc...).
Note: This approach is NOT recommended on the server-side because can lead to token leakage issues (see this issue for more details).
Thanks to @webdeb for requesting this feature and helping develop and test the solution.
Alternatives
If you need to connect using a more generic OIDC client instead of keycloak.js`, consider using one of the following libraries: