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

@ovotech/keycloak-auth

v2.0.5

Published

Keycloak Auth

Downloads

3,059

Readme

Keycloak Auth

Retrieve access tokens for keycloak oauth. Respect access token and refresh token expiry.

Usage

import { authenticate } from '@ovotech/keycloak-auth';

const tokens1 = await authenticate({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
});

// { accessToken: '...', refreshToken: '...', accessTokenExpires: 1553010721, refreshTokenExpires: 1553068047 }
console.log(tokens1);

// ... some time passes

const tokens2 = await authenticate({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
  previous: auth,
});

After the initial call, doing another authenticate with a previous argument would either - return the same response, if the authToken is still valid, use the refreshToken to generate a new authToken, if it has expired, or if refreshToken has expired as well, generate a new auth + refresh token.

By default it would give you a leeway of 10 seconds for the expiry checks, so auth and refresh tokens are expired 10 seconds earlier. You can configure this with the margin argument

const auth1 = await authenticate({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
  // consider tokens expired 15 seconds earlier
  margin: 15,
});

Usage with a class

If you want to encapsulate the state of the tokens inside of a class, you can use the KeycloakAuth class:

import { KeycloakAuth } from '@ovotech/keycloak-auth';

const auth = new KeycloakAuth({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
});

const tokens1 = await auth.authenticate();

// ... sometime passes

const tokens2 = await auth.authenticate();

Usage with axios

You can use the axios interceptor to add a bearer auth token to the requests automatically.

import axios from 'axios';
import { keycloakAxios } from '@ovotech/keycloak-auth';

const api = axios.create({ baseURL: 'http://service.example.com' });
const auth = keycloakAxios({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
});

api.interceptors.request.use(auth);

// Would be called with Authorization: Bearer <authToken>
const response = await api.get('/test');

Error handling

If there is an api error, you'll get an KeycloackAuthError

import { authenticate, KeycloackAuthError } from '@ovotech/keycloak-auth';

try {
  const tokens1 = await authenticate({
    serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
    clientId: '...',
    clientSecret: '...',
  });
} catch (error) {
  if (error instanceof KeycloackAuthError) {
    console.log(error.message, error.code);
  }
}

Low level usage

You can also call the login and refresh functions directly, to get the raw server responses.

import { login, refresh } from '@ovotech/keycloak-auth';

const tokens1 = await login({
  serverUrl:  'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
});

const tokens2 = await refresh({
  serverUrl:  'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
  refreshToken: tokens1.refresh_token,
});

Decoding a request

You can also call the decodeAccessToken function to decode a given access token, this can be used to protect a server

const token = await authenticate({
  serverUrl: 'http://keycloak-server.example.com/auth/realms/<my-realm>/protocol/openid-connect/token',
  clientId: '...',
  clientSecret: '...',
});

const res = await decodeAccessToken(
  token.accessToken,
  {
    issuer: '...',
    jwksUri: '...',
  },
);

Running the tests

Then you can run the tests with:

yarn test

Coding style (linting, etc) tests

Style is maintained with prettier and tslint

yarn lint

Deployment

Deployment is performed by lerna automatically on merge / push to master, but you'll need to bump the package version numbers yourself. Only updated packages with newer versions will be pushed to the npm registry.

Contributing

Have a bug? File an issue with a simple example that reproduces this so we can take a look & confirm.

Want to make a change? Submit a PR, explain why it's useful, and make sure you've updated the docs (this file) and the tests (see test folder).

License

This project is licensed under Apache 2 - see the LICENSE file for details