# @edirect/oidc-client

OpenID Connect client for eDirect applications. Supports three OAuth2 grant types — `password`, `client_credentials`, and `sso` — with a uniform API for acquiring and refreshing tokens.

## Features

- Three grant types: `password`, `client_credentials`, `sso`
- Uniform `getAccessToken()` and `getRefreshToken()` API across all grant types
- OIDC provider discovery via configurable `baseUrl` and `oidcPath`
- Token set parsing utilities

## Installation

```sh
pnpm add @edirect/oidc-client
# or
npm install @edirect/oidc-client
```

## Usage

### Password Grant (username + password)

Used when the application authenticates on behalf of a user:

```ts
import OidcClient from '@edirect/oidc-client';

const client = await OidcClient({
  grantType: 'password',
  baseUrl: process.env.OIDC_PROVIDER_URL, // e.g., 'https://keycloak.example.com'
  oidcPath: process.env.OIDC_PROVIDER_PATH, // e.g., '/realms/my-realm'
  clientId: process.env.OIDC_CLIENT_ID,
  clientSecret: process.env.OIDC_CLIENT_SECRET,
});

// Acquire access token
const tokenSet = await client.getAccessToken({
  username: process.env.OIDC_USERNAME,
  password: process.env.OIDC_PASSWORD,
});

console.log(tokenSet.access_token);
console.log(tokenSet.expires_in);

// Refresh token (not available for client_credentials)
const refreshed = await client.getRefreshToken(tokenSet);
```

### Client Credentials Grant (service-to-service)

Used for machine-to-machine authentication:

```ts
import OidcClient from '@edirect/oidc-client';

const client = await OidcClient({
  grantType: 'client_credentials',
  baseUrl: process.env.OIDC_PROVIDER_URL,
  oidcPath: process.env.OIDC_PROVIDER_PATH,
  clientId: process.env.OIDC_CLIENT_ID,
  clientSecret: process.env.OIDC_CLIENT_SECRET,
});

// No login data required for client_credentials
const tokenSet = await client.getAccessToken();
console.log(tokenSet.access_token);

// Note: getRefreshToken is not applicable to client_credentials
```

### SSO Grant

Used for SSO-based authentication flows:

```ts
const client = await OidcClient({
  grantType: 'sso',
  baseUrl: process.env.OIDC_PROVIDER_URL,
  oidcPath: process.env.OIDC_PROVIDER_PATH,
  clientId: process.env.OIDC_CLIENT_ID,
  clientSecret: process.env.OIDC_CLIENT_SECRET,
  redirectUri: process.env.OIDC_CALLBACK_URL,
});

const tokenSet = await client.getAccessToken({ code: authorizationCode });
```

## API

### `OidcClient(params: Connect): Promise<OidcConnect>`

Factory function that initializes the OIDC client for the specified grant type.

| Parameter      | Type                                          | Description                                |
| -------------- | --------------------------------------------- | ------------------------------------------ |
| `grantType`    | `'password' \| 'client_credentials' \| 'sso'` | OAuth2 grant type                          |
| `baseUrl`      | `string`                                      | OIDC provider base URL                     |
| `oidcPath`     | `string`                                      | OIDC realm path (e.g., `/realms/my-realm`) |
| `clientId`     | `string`                                      | Client ID registered in the OIDC provider  |
| `clientSecret` | `string`                                      | Client secret                              |
| `redirectUri`  | `string`                                      | Callback URL (for `sso` grant)             |

### Client Methods

| Method            | Signature                           | Description                                                  |
| ----------------- | ----------------------------------- | ------------------------------------------------------------ |
| `getAccessToken`  | `(loginData?) => Promise<TokenSet>` | Acquire an access token                                      |
| `getRefreshToken` | `(tokenSet) => Promise<TokenSet>`   | Refresh an existing token set (not for `client_credentials`) |

### `TokenSet`

```ts
interface TokenSet {
  access_token: string;
  token_type: string;
  expires_in: number;
  refresh_token?: string; // not present for client_credentials
  refresh_expires_in?: number;
  id_token?: string;
  session_state?: string;
  scope?: string;
}
```

## Environment Variables

| Variable             | Description                                                   |
| -------------------- | ------------------------------------------------------------- |
| `OIDC_PROVIDER_URL`  | OIDC provider base URL (e.g., `https://keycloak.example.com`) |
| `OIDC_PROVIDER_PATH` | OIDC realm path (e.g., `/realms/my-realm`)                    |
| `OIDC_CLIENT_ID`     | Client ID                                                     |
| `OIDC_CLIENT_SECRET` | Client secret                                                 |
| `OIDC_USERNAME`      | Username (for `password` grant)                               |
| `OIDC_PASSWORD`      | Password (for `password` grant)                               |
| `OIDC_CALLBACK_URL`  | Redirect URI (for `sso` grant)                                |
