npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ra-keycloak

v2.0.0

Published

An auth provider for [react-admin](https://github.com/marmelab/react-admin) which handles authentication via a [Keycloak](https://www.keycloak.org/guides) server.

Downloads

3,060

Readme

ra-keycloak

An auth provider for react-admin which handles authentication via a Keycloak server.

This package provides:

  • A keycloakAuthProvider for react-admin
  • A helper httpClient which adds headers needed by Keycloak in all requests.
  • A <LoginPage> component

This package uses keycloak-js to handle the Keycloak authentication.

Installation

yarn add ra-keycloak
# or
npm install --save ra-keycloak

Usage

// in src/index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import { App } from './App';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
const router = createBrowserRouter([{ path: '*', element: <App /> }]);

root.render(
    <React.StrictMode>
        <RouterProvider router={router} />
    </React.StrictMode>
);

// in src/App.tsx
import * as React from 'react';
import { Admin, Resource } from 'react-admin';
import simpleRestProvider from 'ra-data-simple-rest';
import Keycloak, {
    KeycloakConfig,
    KeycloakTokenParsed,
    KeycloakInitOptions,
} from 'keycloak-js';
import { keycloakAuthProvider, httpClient, LoginPage } from 'ra-keycloak';
import posts from './posts';
import users from './users';

const config: KeycloakConfig = {
    url: '$KEYCLOAK_URL',
    realm: '$KEYCLOAK_REALM',
    clientId: '$KEYCLOAK_CLIENT_ID',
};

// here you can set options for the keycloak client
const initOptions: KeycloakInitOptions = {
    // Optional: makes Keycloak check that a user session already exists when it initializes
    // and immediately consider the user as authenticated if one exists.
    onLoad: 'check-sso',
    // Optional: makes Keycloak check that a user session already exists when it initializes and redirect them to the Keycloak login page if not.
    // It's not necessary with react-admin as it already has a process for that (authProvider.checkAuth)
    // onLoad: 'login-required',
    // Required when using react-router HashRouter (or createHashRouter)
    // responseMode: 'query'
};

// here you can implement the permission mapping logic for react-admin
const getPermissions = (decoded: KeycloakTokenParsed) => {
    const roles = decoded?.realm_access?.roles;
    if (!roles) {
        return false;
    }
    if (roles.includes('admin')) return 'admin';
    if (roles.includes('user')) return 'user';
    return false;
};

const keycloakClient = new Keycloak(config);
const authProvider = keycloakAuthProvider(keycloakClient, {
    initOptions,
    onPermissions: getPermissions,
});
const dataProvider = simpleRestProvider(
    '$API_URL',
    httpClient(keycloakClient)
);

export const App = () => {
    return (
        <Admin
            authProvider={authProvider}
            dataProvider={dataProvider}
            // Optional when using login-required init option on keycloak
            loginPage={LoginPage}
        >
            {permissions => (
                <>
                    <Resource name="posts" {...posts} />
                    {permissions === 'admin' ? (
                        <Resource name="users" {...users} />
                    ) : null}
                </>
            )}
        </Admin>
    );
};

keycloakAuthProvider Parameters

A function that returns an authProvider. It requires a Keycloak client as its first parameter.

// in src/dataProvider.ts
import { keycloakAuthProvider } from 'ra-keycloak';
import { keycloakClient } from './keycloakClient';

export const authProvider = keycloakAuthProvider(
    keycloakClient,
    {
        initOptions: { onLoad: 'check-sso' },
    }
);

It also accept a second parameter with the following options:

| Option | Required | Type | Description | | authenticationTimeout | | Number | The time to wait in milliseconds for Keycloak to detect authenticated users. Defaults to 2 seconds. | | initOptions | | Object | The options to pass to the Keycloak init function (See https://www.keycloak.org/securing-apps/javascript-adapter#_methods) | | loginRedirectUri | | String | The URI to which to redirect users after login | | logoutRedirectUri | | String | The URI to which to redirect users after logout | | onPermissions | | Function | A function used to transform the permissions fetched from Keycloak into a permissions object in the form of what your react-admin app expects |

Tip: This function will take care of initializing the Keycloak client if not already done.

httpClient

An Http client you can pass to many React-Admin data providers that will add the Keycloak authentication token to the requests headers. It requires a Keycloak client as its first parameter.

// in src/dataProvider.ts
import { httpClient } from 'ra-keycloak';
import simpleRestProvider from 'ra-data-simple-rest';
import { keycloakClient } from './keycloakClient';

export const dataProvider = simpleRestProvider(
    '$API_URL',
    httpClient(keycloakClient)
);

<LoginPage>

A custom React-Admin login page that call the Keycloak login method and automatically set the redirect URI to the /auth-callback route.

// in src/Admin.tsx
import * as React from 'react';
import { Admin } from 'react-admin';
import { LoginPage } from 'ra-keycloak';

export const App = () => {
    return (
        <Admin
            authProvider={authProvider}
            dataProvider={dataProvider}
            // Make sure you use the LoginPage provided by ra-keycloak if you didn't set the onLoad keycloak init option to 'login-required'
            loginPage={LoginPage}
        >
            {/* ... */}
        </Admin>
    );
};

Using ra-keycloak with the HashRouter

If for some reason you can't use createBrowserRouter nor BrowserRouter, you'll have to set the responseMode Keycloak init option to "query" and the keycloakAuthProvider.loginRedirectUri to /#/auth-callback. If your application does not have routes accessible to anonymous users, you should also set the keycloakAuthProvider.logoutRedirectUri to /#/login:

const keycloakClient = new Keycloak({
    url: '$KEYCLOAK_URL',
    realm: '$KEYCLOAK_REALM',
    clientId: '$KEYCLOAK_CLIENT_ID',
});
const authProvider = keycloakAuthProvider(keycloakClient, {
    initOptions: {
        responseMode: 'query',
    },
    loginRedirectUri: `/#/auth-callback`,
    logoutRedirectUri: `/#/login`,
    onPermissions: getPermissions,
});

This is because Keycloak passes its parameters for authentication in the URL hash fragment by default and it's not compatible with createHashRouter nor <HashRouter>.

Demo

You can find a working demo, along with the source code, in this project's repository: https://github.com/marmelab/ra-keycloak

License

This auth provider is licensed under the MIT License and sponsored by marmelab.