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

react-and-keycloak

v0.1.0

Published

Keycloak + React Router - Clean & Simple.

Downloads

14

Readme

react-and-keycloak

A simple interface to use React Router and Keycloak together.

It is a thin wrapper around @react-keycloak/web that makes everything nice and easy to use. I also ported over and simplified the logic from react-router-keycloak which

Usage

In index.jsx

import React from 'react';
import KeycloakProvider from 'react-and-keycloak';
import Routes from './routes';


const kcParams = {
  url: 'https://auth.mydomain.com',
  realm: 'master', // optional
  // a public client cuz you dont wanna put a clientSecret on a public webpage
  clientId: 'myclient',
};

const App = ({}) => {
    return (
        <KeycloakProvider {...kcParams} onEvent={console.log} onTokens={console.log}>
            <Routes />
        </KeycloakProvider>
    )
}

And then in routes.jsx

import { useKeycloak } from '@react-keycloak/web';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { PrivateRoute, LoginRoute, LogoutRoute } from 'react-and-keycloak';

function Routes() {
  const { initialized, keycloak } = useKeycloak();

if (!initialized) {
    return <div>Loadinggggg...</div>
  }

  const token = keycloak && keycloak.token;
  return (
      <main>          
          <Router>
              <Route exact path="/" render={() => 
                  <div>
                      A public home page <p>Token: {token}</p>
                  </div>} />
              <LoginRoute redirectTo="/token" />
              <LogoutRoute redirectTo="/" />
              <PrivateRoute path="/private" render={() => 
                  <div>
                      A private page <p>Token: {token}</p>
                      <Link to="/private2">other</Link>
                  </div>} />
              <PrivateRoute path="/private2" render={() => 
                  <div>
                      Another private page <p>Token: {token}</p>
                      <Link to="/private">other</Link>
                  </div>} />
          </Router>
      </main>
  )
}

API Reference

KeycloakProvider

This is responsible for holding the Keycloak JS object and providing it to the child elements. This goes at the top of the DOM hierarchy.

// defaults
<KeycloakProvider {...{
    // connection parameters for keycloak
    url,  // the keycloak base url
    clientId,  // the keycloak client id
    realm='master',  // the keycloak realm

    loginPath='/login',  // the login route to redirect to
    logoutPath='/logout', // TODO: how to connect these to login routes
    onTokens,  // callback function when tokens are refreshed. receives ({ token, refreshToken, idToken })
    // keycloak api reference: https://www.keycloak.org/docs/latest/securing_apps/#javascript-adapter-reference
    initOptions, // keycloak .init() arguments
    keycloakOptions, // keycloak() arguments
    offline=false,  // use an offline refresh token (basically refresh token won't expire, but it's higher risk)
    appendPath=null,  // set to false if you don't want to append /auth to your url (you probably do tho)
    children,  // children components that can access the keycloak object
    ...props
}} />

For keycloak options: docs For init options: docs

Example

The simplest configuration you could provide:

<KeycloakProvider url='auth.myproject.com' clientId='myapp'>
    <App />
</KeycloakProvider>

PrivateRoute

This let's you create a react router route that is only accessible when you're logged in.

If you aren't, it will redirect you to the Keycloak login page.

<PrivateRoute {...{
    render,  // the route render function
    ...routeProps,  // the rest of the route props
}}>
Example
<Router>
    <PrivateRoute path="/private" render={() => 
        <div>I am a dark secret</div>} />
</Router>

LoginRoute

<LoginRoute {...{
    path,  // the url for the login page - make sure it matches with `KeycloakProvider`'s `loginPath`
    redirectTo,  // the url to redirect to when you're done
    ...routeProps,  // the rest of the route props
}}>
Example
<Router>
    <LoginRoute redirectTo="/" />
</Router>

LogoutRoute

<LogoutRoute {...{
    path,  // the url for the logout page - make sure it matches with `KeycloakProvider`'s `logoutPath`
    redirectTo,  // the url to redirect to when you're done
    ...routeProps,  // the rest of the route props
}}>
Example
<Router>
    <LogoutRoute redirectTo="/" />
</Router>

Protect

This is a slightly more general version of PrivateRoute that will only render its children

<Protect {...{
    children,  // a function that returns the protected children
    unprotected  // an optional function that returns content to render for unauthenticated users
}} />
Example
<Protect>() => (<div>You're only gonna see this if you're logged in !!!</div>)</Protect>

And if you want to display a message for unauthenticated users:

<Protect unprotected={() => <div>Ma says not to talk to strangers !!</div>}>
    () => (<div>Oh hey friend !!</div>)
</Protect>

Other Routes

See keycloak docs.

NOTE: The path parameters here are set to their defaults and are optional. They are included here for clarity.

<Router>
    <LoginRoute />
    <LogoutRoute />
    <RegisterUrl path='/register' /> {/* Redirects to Keycloak's register url */}
    <ManageAccountUrl path='/account' /> {/* Redirects to Keycloak's account url */}
</Router>

Utilities

useToken

const { 
    token, // the token string
    data // the token payload
} = useToken(
    period=null, // the interval to check the token - by default it's 1 (second), for key='refresh' it's 10(s).
    key=null // the kind of token to get. can be null, 'refresh', or 'id'
);
Example

To get your token as a string (token) and it's contents as an object (data) use this:

import { useToken } from 'react-and-keycloak';

const App = () => {
    const { token, data } = useToken();
    return (<div>
        <p>Your token, dear: {token}</p>
        <p>anddd the data: {JSON.stringify(data)}</p>
    </div>);
}

If, for some reason, you want the refresh token, you can do useToken(null, 'refresh') or useToken(null, 'id') for the id token.

It will periodically check if there's a new token and will refresh when a new one is available.

If you want to

By default, it will check refresh tokens every 10 seconds and the others every 1 second.

timeLeft

// given the token payload, return the time left in seconds until expiration
const seconds = timeLeft(data);

To get the time left in your token, do this:

import { useToken, timeLeft } from 'react-and-keycloak';

const App = () => {
    const { token, data } = useToken();
    // this will only update when you get a new token.
    return <div>You have {timeLeft(data)} seconds left in your token.</div>
}

useTock

// re-render every x seconds. returns the current time
// by default, it uses 1 second
const tock = useTock(1);

If you want to refresh your elements on your own every second, you can do:

import { useTock, useToken, timeLeft } from 'react-and-keycloak';

const App = () => {
    useTock(1);  // will refresh every 1 second
    const { token, data } = useToken();
    // now timeleft will update every second
    return <div>You have {timeLeft(data)} seconds left in your token.</div>
}

or alternatively:

import { useTock, useToken, timeLeft } from 'react-and-keycloak';

const App = () => {
    const { token, data } = useToken();
    return <TimeLeftDisplay data={data} />
}

const TimeLeftDisplay = ({ data }) => {
    const tock = useTock(1); // now tock is only refreshing what it needs to
    return <div>You have {timeLeft(data)} seconds left in your token.</div>
}