npm package: @ministryofjustice/hmpps-auth-clients
Description: Clients for authenticating and verifying tokens using the HMPPS Authentication estate
Author: hmpps-developers
Latest version: 1.0.2

# hmpps-auth-clients

This package provides reusable clients for interacting with [HMPPS Auth](https://github.com/ministryofjustice/hmpps-auth) and the HMPPS Token Verification API. It abstracts the logic for:

- Acquiring tokens for system or user-based authentication
- Verifying the validity of tokens
- Storing and retrieving tokens from various backends (e.g., Redis, in-memory)

## Features

- **AuthenticationClient**: Manages retrieval of tokens from HMPPS Auth (supports both system and impersonation tokens).
- **VerificationClient**: Validates tokens against the HMPPS Token Verification API.
- **RedisTokenStore**: Persists tokens in Redis for distributed deployments.
- **InMemoryTokenStore**: Keeps tokens in memory for local development or testing purposes.

## Status

**This library is currently: ready to adopt.**

 Teams are encouraged to use this library. Please provide feedback via slack to the #typescript channel.

## Installation

```bash
npm install @ministryofjustice/hmpps-auth-clients
```

## Usage

### AuthenticationClient

An example of using AuthenticationClient to retrieve a system token or a user token from HMPPS Auth:

```
import AuthenticationClient from 'hmpps-auth-clients/dist/AuthenticationClient'
import ConsoleLogger from 'bunyan' // Example logger; you can use your own

const authClient = new AuthenticationClient(
  {
    systemClientId: 'your-system-client-id',
    systemClientSecret: 'your-system-client-secret',
    ...ApiConfig
  },
  logger,
)

// Get a system (anonymous) token
const systemToken = await authClient.getToken()

// Optionally, perform a system action on behalf of a user
const userToken = await authClient.getToken('some-user')
```

### VerificationClient

Use VerificationClient to verify tokens against the HMPPS Token Verification API:

```
import VerificationClient from 'hmpps-auth-clients/dist/VerificationClient'
import ConsoleLogger from 'bunyan'

const verificationClient = new VerificationClient(
  {
    enabled: true,
    ...ApiConfig
  },
  logger,
)

// If your request object has a user and token, you can verify it:
const isTokenValid = await verificationClient.verifyToken({
  user: { username: 'some-user', token: 'jwt-token-here' },
})
```

### RedisTokenStore

Using RedisTokenStore to persist tokens in Redis (useful for distributed or scalable environments):

```
import { createClient } from 'redis'
import RedisTokenStore from 'hmpps-auth-clients/dist/tokenStores/RedisTokenStore'

// Create and connect a Redis client
const redisClient = createClient()
await redisClient.connect()

// Create the token store instance
const redisTokenStore = new RedisTokenStore(redisClient)

// Store and retrieve a token
await redisTokenStore.setToken('some-key', 'my-token', 3600) // 1 hour expiry
const token = await redisTokenStore.getToken('some-key') // 'my-token'
```

The default prefix for values set in Redis using the RedisTokenStore is `systemToken:`, therefore the following code
will set the value in Redis with the key `systemToken:A_USER_GEN`:
```
// token = system token generated from HMPPS Auth
// key = DPS username, eg: A_USER_GEN

const redisTokenStore = new RedisTokenStore(redisClient)
await redisTokenStore.setToken(key, token, 3600)
```
Typical use cases for this are for storing system client tokens (the client-credentials tokens) generated by HMPPS Auth
but with the DPS username set as the subject.

Sometimes other client-credentials tokens are generated with the DPS username set as the subject, but these tokens are
not the UI's main system client ID & secret. For example, HMPPS Auth generates and issues the client-credentials token
for calling the Curious API. A separate client is created by the HAAR team that carries just the role(s) necessary to
call Curious. This client has its own client ID and secret. A separate RedisTokenStore can be created with a specific
prefix for this purpose:

```
// token = Curious token generated from HMPPS Auth
// key = DPS username, eg: A_USER_GEN

const redisTokenStore = new RedisTokenStore(redisClient, 'curiousToken:)
await redisTokenStore.setToken(key, token, 3600)
```

### InMemoryTokenStore

Using InMemoryTokenStore to store tokens in memory (suitable for local development):

```
import InMemoryTokenStore from 'hmpps-auth-clients/dist/tokenStores/InMemoryTokenStore'

const inMemoryStore = new InMemoryTokenStore()

await inMemoryStore.setToken('some-key', 'my-token', 3600)
const token = await inMemoryStore.getToken('some-key') // 'my-token'
```

## Developing this package

This module uses rollup, to build:

`npm run lint-fix && npm run build && npm run test`

## Testing changes to this library

- `cd` to this directory and then link this library: `npm link`
- Utilise the in-development library within a project by using: `npm link @ministryofjustice/hmpps-auth-clients`