@ovotech/keycloak-auth
TypeScript icon, indicating that this package has built-in type declarations

2.0.5 • Public • Published

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

/@ovotech/keycloak-auth/

    Package Sidebar

    Install

    npm i @ovotech/keycloak-auth

    Weekly Downloads

    497

    Version

    2.0.5

    License

    Apache-2.0

    Unpacked Size

    30.9 kB

    Total Files

    26

    Last publish

    Collaborators

    • ovox
    • oep-accounts-bot
    • ovo.backstage.admins
    • bookings-team
    • orion-bot
    • bizval-bot
    • oeptariffs
    • props
    • metering-reads-health-bot
    • ovotech-identity
    • paceteamkaluza
    • trading-and-dispatch
    • retail-payg-tech
    • accrecovo
    • ovo.trading.tech
    • qe-team
    • ovotech-smart-thermostat
    • rise-team
    • engagement-insights
    • myovo-self-serve-service-account
    • mars-rover
    • ape-team
    • kaluza-devex
    • ohs-aurora
    • kaluza-rnr
    • ipa-bot
    • kawbot
    • data.discovery.ovo
    • ovotech-sg
    • ovotech-qs
    • ovoenergyapps
    • homemoves
    • ovo-oot-bot
    • cp-ui-tooling
    • ovo-bit-tech
    • sir_hiss