npm package: @schematize/client-credentials
Description: Schematize Client Credentials Auth Library
Author: Benjamin Bytheway
Latest version: 0.6.3

# @schematize/client-credentials

A secure OAuth 2.0 Client Credentials flow implementation for server-to-server authentication.  This library provides a complete solution for implementing OAuth 2.0 client credentials grant type, designed primarily for backend services and server-side applications where user interaction is not required.

## Features

- **OAuth 2.0 Client Credentials Flow**: Complete implementation of the client credentials grant type
- **Automatic Token Management**: Handles token acquisition, storage, and expiration
- **Cross-Platform Support**: Works in both Node.js and browser environments (with security warnings)
- **Automatic Token Refresh**: Manages token expiration and re-authorization
- **Request Deduplication**: Prevents multiple simultaneous authorization requests
- **Error Handling**: Comprehensive error management and reporting
- **Security Warnings**: Built-in warnings for browser usage to prevent credential exposure

## Dependencies

- `@schematize/refs`: Reference utilities for cross-platform compatibility
- `@schematize/metamodel`: Instance management and utilities

## Installation

```bash
npm install @schematize/client-credentials
```

## Usage

```javascript
import ClientCredentials from '@schematize/client-credentials';

const auth = ClientCredentials({
  endpoints: {
    token: 'https://auth.example.com/token'
  },
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  scope: 'api:read api:write'
});

// Authorize and get access token
await auth.authorize();

// Use the access token for API calls
const response = await fetch('https://api.example.com/data', {
  headers: auth.headers
});
```

## API Reference

### ClientCredentials(config)

Creates a new client credentials flow instance with the specified configuration.

#### Parameters

- `config` (Object): Configuration object containing:
  - `endpoints` (Object): Required endpoint URLs
    - `token` (String): Token endpoint URL (required)
  - `clientId` (String): OAuth client identifier (required)
  - `clientSecret` (String): OAuth client secret (required)
  - `scope` (String): Space-separated list of scopes (optional)

#### Returns

- `Object`: Client credentials instance with methods and properties

#### Usage

```javascript
const auth = ClientCredentials({
  endpoints: {
    token: 'https://auth.example.com/token'
  },
  clientId: '4mfnfh3n264rovj1u1cyoed4',
  clientSecret: 'your-secret-key',
  scope: 'api:read api:write'
});
```

#### Features

- **Browser Warning**: Displays warning when used in browser environments
- **Configuration Validation**: Validates required parameters and endpoints
- **Cross-Platform**: Works in both Node.js and browser environments
- **Security Focused**: Designed for server-to-server authentication

### auth.initialize()

Initializes the client credentials flow.  Currently a placeholder for future functionality.

#### Returns

- `Promise<void>`: Promise that resolves when initialization is complete

#### Usage

```javascript
await auth.initialize();
```

#### Features

- **Future Ready**: Prepared for automatic authorization and token management
- **Async Support**: Returns a promise for consistent API

### auth.authorize(options)

Obtains an access token using the client credentials flow.

#### Parameters

- `options` (Object): Optional configuration object (currently unused)

#### Returns

- `Promise<Object>`: Promise that resolves to the auth instance

#### Usage

```javascript
// Basic authorization
await auth.authorize();

// Check if already authorized before calling
if (!auth.authorized) {
  await auth.authorize();
}
```

#### Features

- **Automatic Expiration Handling**: Checks token expiration with 20-second buffer
- **Request Deduplication**: Prevents multiple simultaneous authorization requests
- **Token Storage**: Stores access token and expiration time
- **Header Generation**: Automatically creates Authorization headers
- **Error Management**: Handles and reports authorization errors

### auth.signout(options)

Clears all stored authorization data and resets the authentication state.

#### Parameters

- `options` (Object): Optional configuration object (currently unused)

#### Returns

- `Promise<void>`: Promise that resolves when sign-out is complete

#### Usage

```javascript
await auth.signout();
```

#### Features

- **Complete Cleanup**: Removes all stored tokens and authorization data
- **State Reset**: Resets all authentication state properties
- **Memory Management**: Clears authorization state from memory

### auth.getUserInfo()

Not supported for client credentials flow.

#### Returns

- `Promise<never>`: Always throws an error

#### Usage

```javascript
// This will throw an error
try {
  await auth.getUserInfo();
} catch (error) {
  console.log('getUserInfo not supported for client credentials');
}
```

#### Features

- **Explicit Error**: Throws clear error indicating unsupported operation
- **API Consistency**: Maintains consistent API with other auth flows

## Properties

### auth.authorized

- **Type**: `Boolean`
- **Description**: Indicates whether the client is currently authorized
- **Usage**: Check authorization status before making API calls

### auth.accessToken

- **Type**: `String`
- **Description**: The current access token for API authentication
- **Usage**: Include in Authorization header for API requests

### auth.headers

- **Type**: `Object`
- **Description**: Pre-configured headers object with Authorization header
- **Usage**: Use directly in fetch requests or API calls in connection with the OAuth 2.0 Bearer Token specification

### auth.expires

- **Type**: `Number`
- **Description**: Timestamp when the current access token expires
- **Usage**: Check token expiration for automatic refresh

### auth.userInfo

- **Type**: `undefined`
- **Description**: Not available for client credentials flow
- **Usage**: Not applicable for server-to-server authentication

### auth.error

- **Type**: `String`
- **Description**: Error code from authorization server
- **Usage**: Handle authorization errors and display user-friendly messages

### auth.errorDescription

- **Type**: `String`
- **Description**: Human-readable error description
- **Usage**: Display detailed error information

### auth.errorUri

- **Type**: `String`
- **Description**: URI with additional error information
- **Usage**: Link to detailed error documentation

### auth.authorizing

- **Type**: `Promise|undefined`
- **Description**: Promise for ongoing authorization request
- **Usage**: Internal property for request deduplication

## Security Considerations

### Browser Usage Warning

The library displays a warning when used in browser environments:

```javascript
console.warn(
  'auth.clientCredentials: You should NEVER use this in a browser environment.' + 
  'You will expose your clientSecret to anyone who can inspect this code allowing anyone access.'
);
```

### Best Practices

- **Server-Side Only**: Use only in server-side applications
- **Secure Storage**: Store client secrets securely in environment variables
- **Token Management**: Let the library handle token expiration and refresh
- **HTTPS Only**: Always use HTTPS for token endpoint communication

### Token Security

- **Automatic Expiration**: Tokens are automatically checked for expiration
- **Buffer Time**: 20-second buffer prevents token expiration during requests
- **Memory Storage**: Tokens stored in memory, not persistent storage
- **Header Generation**: Automatic Bearer token header generation

## Error Handling

The library provides comprehensive error handling for various scenarios:

```javascript
try {
  await auth.authorize();
} catch (error) {
  if (auth.error) {
    console.error('Authorization failed:', auth.error);
    console.error('Description:', auth.errorDescription);
    console.error('URI:', auth.errorUri);
  } else {
    console.error('Unexpected error:', error.message);
  }
}
```

## Cross-Platform Support

### Node.js Environment

```javascript
// Works seamlessly in Node.js
const auth = ClientCredentials({
  endpoints: { token: 'https://auth.example.com/token' },
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret'
});
```

### Browser Environment

```javascript
// Displays warning but still functions
// YOU SHOULD NEVER USE THIS IN production or any public facing web app or website
const auth = ClientCredentials({
  endpoints: { token: 'https://auth.example.com/token' },
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret'
});
```

## License

MIT

## Author

Benjamin Bytheway