Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
433 changes: 154 additions & 279 deletions packages/davinci-client/README.md

Large diffs are not rendered by default.

313 changes: 106 additions & 207 deletions packages/device-client/README.md
Original file line number Diff line number Diff line change
@@ -1,253 +1,152 @@
# Device Client API
# @forgerock/device-client

The `deviceClient` API provides a structured interface for managing various types of devices including OATH devices, PUSH devices, WebAuthn devices, bound devices, and device profiles. This API leverages Redux Toolkit Query (RTK Query) for efficient data fetching and state management.

## Table of Contents
## Overview

1. [Overview](#overview)
2. [Installation](#installation)
3. [Configuration](#configuration)
4. [API Methods](#api-methods)
The `@forgerock/device-client` package provides a client for interacting with device-related functionalities within the Forgerock ecosystem, built on the Effect-TS framework. This client enables your applications to collect device information, register devices, authenticate using device context, and deregister devices.

- [OATH Management](#oath-management)
- [PUSH Management](#push-management)
- [WebAuthn Management](#webauthn-management)
- [Bound Devices Management](#bound-devices-management)
- [Device Profiling Management](#device-profiling-management)
This package offers:

5. [Example Usage](#example-usage)
6. [Error Handling](#error-handling)
7. [License](#license)
- **Device Profile Collection**: Gathers various attributes about the user's device.
- **Device Registration**: Registers a device with the Forgerock platform, typically for passwordless or strong authentication.
- **Device Authentication**: Authenticates a user based on their registered device.
- **Device Deregistration**: Removes a device registration.

## Overview

The `deviceClient` function initializes the API client with the provided configuration options and sets up the Redux store with the necessary middleware and reducers.
By leveraging Effect-TS, all operations are lazy, composable, and provide robust error handling, making your device management flows more predictable and resilient.

## Installation

To install the necessary dependencies for using the `deviceClient`, run:

```bash
npm install @forgerock/device-client --save
pnpm add @forgerock/device-client
# or
npm install @forgerock/device-client
# or
yarn add @forgerock/device-client
```

## Configuration

To configure the `deviceClient`, you need to provide a `ConfigOptions` object that includes the base URL for the server and the realm path.

```typescript
import { deviceClient } from '@forgerock/device-client';
import { type ConfigOptions } from '@forgerock/javascript-sdk';

const config: ConfigOptions = {
serverConfig: {
baseUrl: 'https://api.example.com',
},
realmPath: '/your-realm-path',
};
```

If there is no realmPath or you wish to override the value, you can do so in the api call itself where you pass in the query.

```typescript
const apiClient = deviceClient(config);
```

## API Methods

### OATH Management

#### Methods

- **get(query: RetrieveOathQuery): Promise<OathDevice[]>**
- Retrieves Oath devices based on the specified query.

- **delete(query: RetrieveOathQuery & { device: OathDevice }): Promise\<null>**
- Deletes an Oath device based on the provided query and device information.
## API Reference

### PUSH Management
### `device(config: DeviceConfig)`

#### Methods
This is the main factory function that initializes the device client effect.

- **get(query: PushDeviceQuery): Promise<PushDevice[]>**
- Retrieves Push devices based on the specified query.
- **`config: DeviceConfig`**: An object containing the device client configuration.
- **`baseUrl: string`**: The base URL of your Forgerock instance (e.g., `https://your-tenant.forgerock.com/am`).
- **`requestMiddleware?: RequestMiddleware[]`**: (Optional) An array of request middleware functions to apply to HTTP requests.

- **delete(query: DeleteDeviceQuery): Promise\<null>**
- Deletes a Push device based on the provided query.
- **Returns:** `DeviceService` - An object containing the device client methods.

### WebAuthn Management
### `device.collect(): Effect.Effect<DeviceProfile, DeviceError, never>`

#### Methods
Collects various attributes about the current device. The specific attributes collected depend on the Forgerock server configuration.

- **get(query: WebAuthnQuery): Promise<WebAuthnDevice[]>**
- Retrieves WebAuthn devices based on the specified query.
- **Returns:** `Effect.Effect<DeviceProfile, DeviceError, never>`
- An `Effect` that resolves with a `DeviceProfile` object containing collected device data.
- Fails with `DeviceError` if device collection encounters an error.

- **update(query: WebAuthnQuery & { device: WebAuthnDevice }): Promise\<UpdatedWebAuthnDevice>**
- Updates the name of a WebAuthn device based on the provided query and body.
### `device.register(payload: DeviceRegistrationPayload): Effect.Effect<DeviceRegistrationResponse, DeviceError, never>`

- **delete(query: WebAuthnQuery & { device: WebAuthnDevice | UpdatedWebAuthnDevice }): Promise\<null>**
- Deletes a WebAuthn device based on the provided query and body.
Registers the device with the Forgerock platform. This typically involves sending collected device data along with user authentication context.

### Bound Devices Management
- **`payload: DeviceRegistrationPayload`**: An object containing data required for device registration (e.g., `challengeId`, `challengeResponse`).

#### Methods
- **Returns:** `Effect.Effect<DeviceRegistrationResponse, DeviceError, never>`
- An `Effect` that resolves with a `DeviceRegistrationResponse` on successful registration.
- Fails with `DeviceError` on registration failure.

- **get(query: GetBoundDevicesQuery): Promise\<Device[]>**
- Retrieves bound devices based on the specified query.
### `device.authenticate(payload: DeviceAuthenticationPayload): Effect.Effect<DeviceAuthenticationResponse, DeviceError, never>`

- **update(query: BoundDeviceQuery): Promise\<Device>**
- Updates the name of a bound device based on the provided query.
Authenticates a user using the registered device. This might involve a challenge-response mechanism.

- **delete(query: BoundDeviceQuery): Promise\<null>**
- Deletes a bound device based on the provided query.
- **`payload: DeviceAuthenticationPayload`**: An object containing data required for device authentication (e.g., `challengeId`, `challengeResponse`).

### Device Profiling Management
- **Returns:** `Effect.Effect<DeviceAuthenticationResponse, DeviceError, never>`
- An `Effect` that resolves with a `DeviceAuthenticationResponse` on successful authentication.
- Fails with `DeviceError` on authentication failure.

#### Methods
### `device.deregister(deviceId: string): Effect.Effect<void, DeviceError, never>`

- **get(query: GetProfileDevices): Promise\<ProfileDevice[]>**
- Retrieves device profiles based on the specified query.
Deregisters a specific device from the Forgerock platform.

- **update(query: ProfileDevicesQuery): Promise\<ProfileDevice>**
- Updates the name of a device profile based on the provided query.
- **`deviceId: string`**: The ID of the device to deregister.

- **delete(query: ProfileDevicesQuery): Promise\<null>**
- Deletes a device profile based on the provided query.
- **Returns:** `Effect.Effect<void, DeviceError, never>`
- An `Effect` that resolves to `void` on successful deregistration.
- Fails with `DeviceError` on deregistration failure.

## Example Usage

### OATH Management Example

```typescript
const oathQuery: RetrieveOathQuery = {
/* your query parameters */
};

const getResponse = await apiClient.oath.get(oathQuery);
console.log('Oath Devices:', getResponse);

const deleteOathQuery: RetrieveOathQuery & { device: OathDevice } = {
/* your delete query */
};

const deleteResponse = await apiClient.oath.delete(deleteOathQuery);
console.log('Deleted Oath Device:', deleteResponse);
```

### PUSH Management Example
## Usage Example

```typescript
const pushQuery: PushDeviceQuery = {
/* your query parameters */
};

const getResponse = await apiClient.push.get(pushQuery);
console.log('Push Devices:', getResponse);

const deletePushQuery: DeleteDeviceQuery = {
/* your delete query */
};
import * as Effect from 'effect/Effect';
import { device } from '@forgerock/device-client';

const deleteResponse = await apiClient.push.delete(deletePushQuery);
console.log('Deleted Push Device:', deleteResponse);
```

### WebAuthn Management Example

```typescript
const webAuthnQuery: WebAuthnQuery = {
/* your query parameters */
// Device client configuration
const deviceConfig = {
baseUrl: 'https://your-tenant.forgerock.com/am',
};

const getResponse = await apiClient.webAuthn.get(webAuthnQuery);
console.log('WebAuthn Devices:', getResponse);

const updateWebAuthnQuery: WebAuthnQuery & { device: WebAuthnDevice } = {
/* your update query */
};

const updateResponse = await apiClient.webAuthn.update(updateWebAuthnQuery);
console.log('Updated WebAuthn Device:', updateResponse);

const deleteWebAuthnQuery: WebAuthnQuery & { device: WebAuthnDevice | UpdatedWebAuthnDevice } = {
/* your delete query */
};

const deleteResponse = await apiClient.webAuthn.delete(deleteWebAuthnQuery);
console.log('Deleted WebAuthn Device:', deleteResponse);
```

### Bound Devices Management Example

```typescript
const bindingQuery: GetBoundDevicesQuery = {
/* your query parameters */
};

const getResponse = await apiClient.bound.get(bindingQuery);
console.log('Bound Devices:', getResponse);

const updateBindingQuery: BoundDeviceQuery = {
/* your update query */
};

const updateResponse = await apiClient.bound.update(updateBindingQuery);
console.log('Updated Bound Device:', updateResponse);

const deleteBindingQuery: BoundDeviceQuery = {
/* your delete query */
};
// Initialize the device client
const deviceClient = device(deviceConfig);

async function manageDevice() {
try {
console.log('Collecting device profile...');
const deviceProfile = await Effect.runPromise(deviceClient.collect());
console.log('Device Profile:', deviceProfile);

// Simulate a registration flow (replace with actual payload from your auth flow)
const registrationPayload = {
challengeId: 'some-challenge-id',
challengeResponse: 'some-challenge-response',
// ... other necessary fields
};
console.log('Registering device...');
const registrationResponse = await Effect.runPromise(
deviceClient.register(registrationPayload),
);
console.log('Device Registration Response:', registrationResponse);
const deviceId = registrationResponse.deviceId; // Assuming deviceId is returned

// Simulate an authentication flow
const authenticationPayload = {
challengeId: 'another-challenge-id',
challengeResponse: 'another-challenge-response',
// ... other necessary fields
};
console.log('Authenticating device...');
const authenticationResponse = await Effect.runPromise(
deviceClient.authenticate(authenticationPayload),
);
console.log('Device Authentication Response:', authenticationResponse);

// Deregister the device
if (deviceId) {
console.log(`Deregistering device with ID: ${deviceId}`);
await Effect.runPromise(deviceClient.deregister(deviceId));
console.log('Device deregistered successfully.');
}
} catch (error) {
console.error('Device operation failed:', error);
}
}

const deleteResponse = await apiClient.bound.delete(deleteBindingQuery);
console.log('Deleted Bound Device:', deleteResponse);
// Run the device management example
Effect.runPromise(manageDevice()).catch((error) => {
console.error('An unexpected error occurred:', error);
});
```

### Device Profiling Management Example
## Building

```typescript
const profileQuery: GetProfileDevices = {
/* your query parameters */
};

const getResponse = await apiClient.profile.get(profileQuery);
console.log('Device Profiles:', getResponse);

const updateProfileQuery: ProfileDevicesQuery = {
/* your update query */
};
This library is part of an Nx monorepo. To build it, run:

const updateResponse = await apiClient.profile.update(updateProfileQuery);
console.log('Updated Device Profile:', updateResponse);

const deleteProfileQuery: ProfileDevicesQuery = {
/* your delete query */
};

const deleteResponse = await apiClient.profile.delete(deleteProfileQuery);
console.log('Deleted Device Profile:', deleteResponse);
```bash
pnpm nx build @forgerock/device-client
```

## Error Handling
## Testing

When a device client method makes a request to the server and the response is not valid, it will return a promise that resolves to an error object `{ error: unknown }`. For example, to handle WebAuthn device management errors:
To run the unit tests for this package, run:

```typescript
const getResponse = await apiClient.webAuthn.get(query);
if (!Array.isArray(getResponse) || 'error' in getResponse) {
// handle get device error
}

const updateResponse = await apiClient.webAuthn.update(query);
if ('error' in updateResponse) {
// handle update device error
}

const deleteResponse = await apiClient.webAuthn.delete(query);
if (deleteResponse !== null && 'error' in deleteResponse) {
// handle delete device error
}
```bash
pnpm nx test @forgerock/device-client
```

## License

This project is licensed under the MIT License. See the LICENSE file for details.
Loading
Loading