# Instructions

[![NPM Version](https://img.shields.io/npm/v/@carisls/keycloak-client.svg?style=flat)](https://www.npmjs.org/package/@carisls/keycloak-client)
[![NPM Downloads](https://img.shields.io/npm/dm/@carisls/keycloak-client.svg?style=flat)](https://npmcharts.com/compare/@carisls/keycloak-client?minimal=true)
[![Install Size](https://packagephobia.now.sh/badge?p=%40carisls%2Fkeycloak-client)](https://packagephobia.now.sh/result?p=%40carisls%2Fkeycloak-client)
[![Pipeline](https://gitlab.carisls.com/caris-eng/npm-packages/sentry-browser/badges/main/pipeline.svg)](https://gitlab.carisls.com/caris-eng/npm-packages/sentry-browser/badges/main/pipeline.svg)

An integration client for Keycloak for Caris applications.

## Installation
```sh
npm i @carisls/keycloak-client
```

## Middleware

Adding of basic piece to handle user injection and redirections to retrieve user.
```javascript
const keycloakClient = require('@carisls/keycloak-client');
app.use(keycloakClient.router({
  clientId: 'my-client'
  ssoUrl: process.env.SSO_URL,
  encPassword: process.env.ENC_PASSWORD
}));
```

Option | API Router | Description
--- | --- | ---
`ssoUrl` | ANY | Url to use as SSO server base url
`clientId` | ANY | Client Id
`clientSecret` | ANY | Client Secret (if enabled)
`api` | N/A | If API Router we need to set this setting to `true` to prevent any redirections
`standard` | N/A | Whether to use implicit (default) or a standard flow
`useCachedSession` | N/A | Whether to use token caching (in case of large tokens)
`publicKey` | ANY | Overriding a default public certificate (provided by SSO Server)
`publicKeyCache` | ANY | Time in seconds when a fetched publicKey should expire
`encPassword` | ANY | Setting encryption password for session cookie
`encPasswordSalt` | ANY | Setting encryption password salt for session cookie
`encIterationCount` | ANY | Setting encryption password number of hash iterations for session cookie
`paths.login` | `false` | Overriding a default `/login` path to initiate login
`paths.sso` | `false` | Overriding a default `/sso` path to receive user token
`paths.logout` | `false` | Overriding a default `/logout` path to initiate logout
`paths.afterLogin` | `false` | Overrides a default `/` path where to send user after a successful login
`paths.afterLogout` | `false` | Overrides a default `/` path where to send user after a successful logout
`expOffset` | `false` | When x-session cookie will expire (in seconds). Negative is earlier, positive later. Default is 0

**NOTE**: You can include publicKey option or not. If not, client will get it
by following OpenID standard (`.well-known`).

**NOTE**: If it is API, we do not have "sending user to login" so we need to
pass `api: true` to `options`.

## Authorization

Adding middleware to authorize requests.
```javascript
const authorize = keycloakClient.authorize;
app.use(authorize('my-app-role', [
  '/403.html',
  '/assets'
]));
```

Middleware `authorize` has three parameters:

No | Parameter Name | Required | Default | Description
---|---|---|---|---
1 | `roles` | `false` | `null` | Needed roles to pass or `null` for all authenticated (one role string or array of strings)
2 | `exceptions` | `false` | `[]` | What paths to exclude. Matches exact url and from the start (`/peter` will match both `/peter` and `/peterson` and `/peter/some-file.txt`)
3 | `redirectToLogin` | `false` | `true` | If not set as `false` it will redirect user to `/login?ReturnUrl={encodedUrl}`. If set to `false` it will throw `401`

## Client Enpoints

**Base Url for a realm**:

`https://{domain}/auth/realms/{realm}`

**Paths**:

- POST `/protocol/openid-connect/token` (ValidateCredentials)

---

**Base Url for a realm admin**:

`https://{domain}/auth/admin/realms/{realm}`

**Paths**:

- GET `/users?email=something@carisls.com` (FindAUserByEmail)
- DELETE `/users/{user.id}` (DeleteUser)
- POST `/users` (CreateUser)
- PUT `/users/{user.id}/reset-password` (UpdateUser)

---

**Base Url for the master realm**:

`https://{domain}/auth/realms/master`

**Paths**:

- POST `/protocol/openid-connect/token` (GetAdminToken)
