コンテンツにスキップ

Provider Interfaces

このコンテンツはまだ日本語訳がありません。

@authrim/core uses a provider-based architecture to remain platform-agnostic. Three provider interfaces abstract runtime-specific functionality:

ProviderPurpose
CryptoProviderCryptographic operations (random, hashing, PKCE)
AuthrimStoragePersistent key-value storage
HttpClientHTTP requests

The CryptoProvider interface handles all cryptographic operations required by the OAuth 2.0 / OIDC protocols.

interface CryptoProvider {
randomBytes(length: number): Promise<Uint8Array>;
sha256(data: string): Promise<Uint8Array>;
generateCodeVerifier(): Promise<string>;
generateCodeChallenge(verifier: string): Promise<string>;
}
MethodParametersReturnsDescription
randomByteslength: numberPromise<Uint8Array>Generate cryptographically secure random bytes
sha256data: stringPromise<Uint8Array>Compute SHA-256 hash of a string
generateCodeVerifierPromise<string>Generate a PKCE code verifier (43-128 chars, base64url)
generateCodeChallengeverifier: stringPromise<string>Compute S256 code challenge from a verifier
import type { CryptoProvider } from '@authrim/core';
const webCryptoProvider: CryptoProvider = {
async randomBytes(length) {
return crypto.getRandomValues(new Uint8Array(length));
},
async sha256(data) {
const encoder = new TextEncoder();
const buffer = await crypto.subtle.digest('SHA-256', encoder.encode(data));
return new Uint8Array(buffer);
},
async generateCodeVerifier() {
const bytes = crypto.getRandomValues(new Uint8Array(32));
return base64urlEncode(bytes);
},
async generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const digest = await crypto.subtle.digest('SHA-256', encoder.encode(verifier));
return base64urlEncode(new Uint8Array(digest));
},
};
import { randomBytes, createHash } from 'node:crypto';
import type { CryptoProvider } from '@authrim/core';
const nodeCryptoProvider: CryptoProvider = {
async randomBytes(length) {
return new Uint8Array(randomBytes(length));
},
async sha256(data) {
const hash = createHash('sha256').update(data).digest();
return new Uint8Array(hash);
},
async generateCodeVerifier() {
const bytes = randomBytes(32);
return base64urlEncode(new Uint8Array(bytes));
},
async generateCodeChallenge(verifier) {
const hash = createHash('sha256').update(verifier).digest();
return base64urlEncode(new Uint8Array(hash));
},
};

For DPoP support, the CryptoProvider may optionally implement DPoPCryptoProvider:

interface DPoPCryptoProvider {
generateDPoPKeyPair?(algorithm?: 'ES256' | 'PS256' | 'EdDSA'): Promise<DPoPKeyPair>;
getDPoPKeyPair?(): Promise<DPoPKeyPair | null>;
clearDPoPKeyPair?(): Promise<void>;
}
interface DPoPKeyPair {
algorithm: 'ES256' | 'PS256' | 'EdDSA';
thumbprint: string;
publicKeyJwk: JWK;
sign(data: Uint8Array): Promise<Uint8Array>;
}

Enable token endpoint DPoP with dpop.tokenRequests: true in Configuration. See DPoP for proof generation details.


The AuthrimStorage interface provides persistent key-value storage for tokens, state, and nonce values.

interface AuthrimStorage {
get(key: string): Promise<string | null>;
set(key: string, value: string): Promise<void>;
remove(key: string): Promise<void>;
getAll?(): Promise<Record<string, string>>; // Optional
clear?(): Promise<void>; // Optional
}
MethodParametersReturnsRequiredDescription
getkey: stringPromise<string | null>YesRetrieve a value by key
setkey: string, value: stringPromise<void>YesStore a value
removekey: stringPromise<void>YesDelete a value
getAllPromise<Record<string, string>>NoGet all stored entries
clearPromise<void>NoRemove all entries
import type { AuthrimStorage } from '@authrim/core';
const localStorageProvider: AuthrimStorage = {
async get(key) {
return localStorage.getItem(key);
},
async set(key, value) {
localStorage.setItem(key, value);
},
async remove(key) {
localStorage.removeItem(key);
},
async getAll() {
const result: Record<string, string> = {};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key) result[key] = localStorage.getItem(key) ?? '';
}
return result;
},
async clear() {
localStorage.clear();
},
};

Implementation Example: In-Memory (Testing)

Section titled “Implementation Example: In-Memory (Testing)”
import type { AuthrimStorage } from '@authrim/core';
const memoryStorage: AuthrimStorage = {
_store: new Map<string, string>(),
async get(key) {
return this._store.get(key) ?? null;
},
async set(key, value) {
this._store.set(key, value);
},
async remove(key) {
this._store.delete(key);
},
async getAll() {
return Object.fromEntries(this._store);
},
async clear() {
this._store.clear();
},
};

The SDK derives issuer and client-id storage key segments from SHA-256 hashes. See Configuration for the hashOptions.hashLength setting.


The HttpClient interface handles all HTTP communication with the authorization server.

interface HttpClient {
fetch<T = unknown>(url: string, options?: HttpOptions): Promise<HttpResponse<T>>;
}
interface HttpOptions {
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
headers?: Record<string, string>;
body?: string | FormData | URLSearchParams;
timeout?: number;
signal?: AbortSignal;
}
interface HttpResponse<T = unknown> {
status: number;
statusText: string;
headers: Record<string, string>;
data: T;
ok: boolean;
}
PropertyTypeDefaultDescription
methodstring'GET'HTTP method
headersRecord<string, string>Request headers
bodystring | FormData | URLSearchParamsRequest body
timeoutnumberRequest timeout in milliseconds
signalAbortSignalAbort signal for cancellation
PropertyTypeDescription
statusnumberHTTP status code
statusTextstringHTTP status text
headersRecord<string, string>Response headers
dataTParsed response body
okbooleantrue if status is 2xx
import type { HttpClient } from '@authrim/core';
const fetchHttpClient: HttpClient = {
async fetch<T>(url: string, options?: HttpOptions): Promise<HttpResponse<T>> {
const response = await globalThis.fetch(url, {
method: options?.method ?? 'GET',
headers: options?.headers,
body: options?.body,
signal: options?.signal,
});
const data = await response.json() as T;
const headers: Record<string, string> = {};
response.headers.forEach((value, key) => {
headers[key] = value;
});
return {
status: response.status,
statusText: response.statusText,
headers,
data,
ok: response.ok,
};
},
};

The SDK recognizes standard OAuth error responses:

interface OAuthErrorResponse {
error: string;
error_description?: string;
error_uri?: string;
}

When an HTTP response contains an OAuth error, the SDK converts it into an AuthrimError with the appropriate error code.

When implementing custom providers:

  1. All methods must be async — Even if the underlying operation is synchronous, return a Promise
  2. Error handling — Throw descriptive errors; the SDK wraps them in AuthrimError
  3. Thread safety — Storage implementations should handle concurrent access (especially in multi-tab scenarios)
  4. Cleanup — Implement clear() on storage providers to support full session cleanup on logout