@getcirrus/oauth-provider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,591 @@
1
+ import { JWK } from "jose";
2
+ import { OAuthClientMetadata, OAuthParResponse, OAuthTokenResponse } from "@atproto/oauth-types";
3
+
4
+ //#region src/storage.d.ts
5
+
6
+ /**
7
+ * OAuth storage interface and types
8
+ * Defines the storage abstraction for auth codes, tokens, clients, etc.
9
+ */
10
+ /**
11
+ * Data stored with an authorization code
12
+ */
13
+ interface AuthCodeData {
14
+ /** Client DID that requested the code */
15
+ clientId: string;
16
+ /** Redirect URI used in the authorization request */
17
+ redirectUri: string;
18
+ /** PKCE code challenge */
19
+ codeChallenge: string;
20
+ /** PKCE challenge method (always S256 for AT Protocol) */
21
+ codeChallengeMethod: "S256";
22
+ /** Authorized scope */
23
+ scope: string;
24
+ /** User DID that authorized the request */
25
+ sub: string;
26
+ /** Expiration timestamp (Unix ms) */
27
+ expiresAt: number;
28
+ }
29
+ /**
30
+ * Data stored with access and refresh tokens
31
+ */
32
+ interface TokenData {
33
+ /** Opaque access token */
34
+ accessToken: string;
35
+ /** Opaque refresh token */
36
+ refreshToken: string;
37
+ /** Client DID that received the token */
38
+ clientId: string;
39
+ /** User DID the token is for */
40
+ sub: string;
41
+ /** Authorized scope */
42
+ scope: string;
43
+ /** DPoP key thumbprint (for token binding) */
44
+ dpopJkt?: string;
45
+ /** Issuance timestamp (Unix ms) */
46
+ issuedAt: number;
47
+ /** Expiration timestamp (Unix ms) */
48
+ expiresAt: number;
49
+ /** Whether the token has been revoked */
50
+ revoked?: boolean;
51
+ }
52
+ /**
53
+ * OAuth client metadata (discovered from DID document)
54
+ */
55
+ interface ClientMetadata {
56
+ /** Client DID */
57
+ clientId: string;
58
+ /** Human-readable client name */
59
+ clientName: string;
60
+ /** Allowed redirect URIs */
61
+ redirectUris: string[];
62
+ /** Client logo URI (optional) */
63
+ logoUri?: string;
64
+ /** Client homepage URI (optional) */
65
+ clientUri?: string;
66
+ /** When the metadata was cached (Unix ms) */
67
+ cachedAt?: number;
68
+ }
69
+ /**
70
+ * Data stored for Pushed Authorization Requests (PAR)
71
+ */
72
+ interface PARData {
73
+ /** Client DID that pushed the request */
74
+ clientId: string;
75
+ /** All OAuth parameters from the push request */
76
+ params: Record<string, string>;
77
+ /** Expiration timestamp (Unix ms) */
78
+ expiresAt: number;
79
+ }
80
+ /**
81
+ * Storage interface for OAuth data
82
+ * Implementations should handle TTL-based expiration
83
+ */
84
+ interface OAuthStorage {
85
+ /**
86
+ * Save an authorization code
87
+ * @param code The authorization code
88
+ * @param data Associated data
89
+ */
90
+ saveAuthCode(code: string, data: AuthCodeData): Promise<void>;
91
+ /**
92
+ * Get authorization code data
93
+ * @param code The authorization code
94
+ * @returns The data or null if not found/expired
95
+ */
96
+ getAuthCode(code: string): Promise<AuthCodeData | null>;
97
+ /**
98
+ * Delete an authorization code (after use)
99
+ * @param code The authorization code
100
+ */
101
+ deleteAuthCode(code: string): Promise<void>;
102
+ /**
103
+ * Save token data
104
+ * @param data The token data
105
+ */
106
+ saveTokens(data: TokenData): Promise<void>;
107
+ /**
108
+ * Get token data by access token
109
+ * @param accessToken The access token
110
+ * @returns The data or null if not found/expired/revoked
111
+ */
112
+ getTokenByAccess(accessToken: string): Promise<TokenData | null>;
113
+ /**
114
+ * Get token data by refresh token
115
+ * @param refreshToken The refresh token
116
+ * @returns The data or null if not found/expired/revoked
117
+ */
118
+ getTokenByRefresh(refreshToken: string): Promise<TokenData | null>;
119
+ /**
120
+ * Revoke a token by access token
121
+ * @param accessToken The access token to revoke
122
+ */
123
+ revokeToken(accessToken: string): Promise<void>;
124
+ /**
125
+ * Revoke all tokens for a user (for logout)
126
+ * @param sub The user DID
127
+ */
128
+ revokeAllTokens?(sub: string): Promise<void>;
129
+ /**
130
+ * Save client metadata (cached from DID document)
131
+ * @param clientId The client DID
132
+ * @param metadata The client metadata
133
+ */
134
+ saveClient(clientId: string, metadata: ClientMetadata): Promise<void>;
135
+ /**
136
+ * Get cached client metadata
137
+ * @param clientId The client DID
138
+ * @returns The metadata or null if not cached
139
+ */
140
+ getClient(clientId: string): Promise<ClientMetadata | null>;
141
+ /**
142
+ * Save PAR request data
143
+ * @param requestUri The unique request URI
144
+ * @param data The PAR data
145
+ */
146
+ savePAR(requestUri: string, data: PARData): Promise<void>;
147
+ /**
148
+ * Get PAR request data
149
+ * @param requestUri The request URI
150
+ * @returns The data or null if not found/expired
151
+ */
152
+ getPAR(requestUri: string): Promise<PARData | null>;
153
+ /**
154
+ * Delete PAR request (after use - one-time use)
155
+ * @param requestUri The request URI
156
+ */
157
+ deletePAR(requestUri: string): Promise<void>;
158
+ /**
159
+ * Check if a nonce has been used and save it if not
160
+ * Used for DPoP replay prevention
161
+ * @param nonce The nonce to check
162
+ * @returns true if the nonce is new (valid), false if already used
163
+ */
164
+ checkAndSaveNonce(nonce: string): Promise<boolean>;
165
+ }
166
+ /**
167
+ * In-memory storage implementation for testing
168
+ */
169
+ declare class InMemoryOAuthStorage implements OAuthStorage {
170
+ private authCodes;
171
+ private tokens;
172
+ private refreshTokenIndex;
173
+ private clients;
174
+ private parRequests;
175
+ private nonces;
176
+ saveAuthCode(code: string, data: AuthCodeData): Promise<void>;
177
+ getAuthCode(code: string): Promise<AuthCodeData | null>;
178
+ deleteAuthCode(code: string): Promise<void>;
179
+ saveTokens(data: TokenData): Promise<void>;
180
+ getTokenByAccess(accessToken: string): Promise<TokenData | null>;
181
+ getTokenByRefresh(refreshToken: string): Promise<TokenData | null>;
182
+ revokeToken(accessToken: string): Promise<void>;
183
+ revokeAllTokens(sub: string): Promise<void>;
184
+ saveClient(clientId: string, metadata: ClientMetadata): Promise<void>;
185
+ getClient(clientId: string): Promise<ClientMetadata | null>;
186
+ savePAR(requestUri: string, data: PARData): Promise<void>;
187
+ getPAR(requestUri: string): Promise<PARData | null>;
188
+ deletePAR(requestUri: string): Promise<void>;
189
+ checkAndSaveNonce(nonce: string): Promise<boolean>;
190
+ /** Clear all stored data (for testing) */
191
+ clear(): void;
192
+ }
193
+ //#endregion
194
+ //#region src/client-resolver.d.ts
195
+ /**
196
+ * Client resolution error
197
+ */
198
+ declare class ClientResolutionError extends Error {
199
+ readonly code: string;
200
+ constructor(message: string, code: string);
201
+ }
202
+ /**
203
+ * Options for client resolution
204
+ */
205
+ interface ClientResolverOptions {
206
+ /** Storage for caching client metadata */
207
+ storage?: OAuthStorage;
208
+ /** Cache TTL in milliseconds (default: 1 hour) */
209
+ cacheTtl?: number;
210
+ /** Fetch function for making HTTP requests (for testing) */
211
+ fetch?: typeof globalThis.fetch;
212
+ }
213
+ /**
214
+ * Resolve client metadata from a DID
215
+ */
216
+ declare class ClientResolver {
217
+ private storage?;
218
+ private cacheTtl;
219
+ private fetchFn;
220
+ constructor(options?: ClientResolverOptions);
221
+ /**
222
+ * Resolve client metadata from a client ID (URL or DID)
223
+ * @param clientId The client ID (HTTPS URL or DID)
224
+ * @returns The client metadata
225
+ * @throws ClientResolutionError if resolution fails
226
+ */
227
+ resolveClient(clientId: string): Promise<ClientMetadata>;
228
+ /**
229
+ * Validate that a redirect URI is allowed for a client
230
+ * @param clientId The client DID
231
+ * @param redirectUri The redirect URI to validate
232
+ * @returns true if the redirect URI is allowed
233
+ */
234
+ validateRedirectUri(clientId: string, redirectUri: string): Promise<boolean>;
235
+ }
236
+ /**
237
+ * Create a client resolver with optional caching
238
+ */
239
+ declare function createClientResolver(options?: ClientResolverOptions): ClientResolver;
240
+ //#endregion
241
+ //#region src/provider.d.ts
242
+ /**
243
+ * OAuth provider configuration
244
+ */
245
+ interface OAuthProviderConfig {
246
+ /** OAuth storage implementation */
247
+ storage: OAuthStorage;
248
+ /** The OAuth issuer URL (e.g., https://your-pds.com) */
249
+ issuer: string;
250
+ /** Whether DPoP is required for all tokens (default: true for AT Protocol) */
251
+ dpopRequired?: boolean;
252
+ /** Whether PAR is enabled (default: true) */
253
+ enablePAR?: boolean;
254
+ /** Client resolver for DID-based discovery */
255
+ clientResolver?: ClientResolver;
256
+ /** Callback to verify user credentials */
257
+ verifyUser?: (password: string) => Promise<{
258
+ sub: string;
259
+ handle: string;
260
+ } | null>;
261
+ /** Get the current user (if already authenticated) */
262
+ getCurrentUser?: () => Promise<{
263
+ sub: string;
264
+ handle: string;
265
+ } | null>;
266
+ }
267
+ /**
268
+ * Error thrown when request body parsing fails
269
+ */
270
+ declare class RequestBodyError extends Error {
271
+ constructor(message: string);
272
+ }
273
+ /**
274
+ * Parse request body from JSON or form-urlencoded
275
+ * @throws RequestBodyError if content type is unsupported or parsing fails
276
+ */
277
+ declare function parseRequestBody(request: Request): Promise<Record<string, string>>;
278
+ /**
279
+ * AT Protocol OAuth 2.1 Provider
280
+ */
281
+ declare class ATProtoOAuthProvider {
282
+ private storage;
283
+ private issuer;
284
+ private dpopRequired;
285
+ private enablePAR;
286
+ private parHandler;
287
+ private clientResolver;
288
+ private verifyUser?;
289
+ private getCurrentUser?;
290
+ constructor(config: OAuthProviderConfig);
291
+ /**
292
+ * Handle authorization request (GET/POST /oauth/authorize)
293
+ */
294
+ handleAuthorize(request: Request): Promise<Response>;
295
+ /**
296
+ * Handle authorization form POST
297
+ */
298
+ private handleAuthorizePost;
299
+ /**
300
+ * Handle token request (POST /oauth/token)
301
+ */
302
+ handleToken(request: Request): Promise<Response>;
303
+ /**
304
+ * Handle authorization code grant
305
+ */
306
+ private handleAuthorizationCodeGrant;
307
+ /**
308
+ * Handle refresh token grant
309
+ */
310
+ private handleRefreshTokenGrant;
311
+ /**
312
+ * Handle PAR request (POST /oauth/par)
313
+ */
314
+ handlePAR(request: Request): Promise<Response>;
315
+ /**
316
+ * Handle metadata request (GET /.well-known/oauth-authorization-server)
317
+ */
318
+ handleMetadata(): Response;
319
+ /**
320
+ * Verify an access token from a request
321
+ * @param request The HTTP request
322
+ * @param requiredScope Optional scope to require
323
+ * @returns Token data if valid
324
+ */
325
+ verifyAccessToken(request: Request, requiredScope?: string): Promise<TokenData | null>;
326
+ /**
327
+ * Render an error page
328
+ */
329
+ private renderError;
330
+ }
331
+ //#endregion
332
+ //#region src/pkce.d.ts
333
+ /**
334
+ * PKCE (Proof Key for Code Exchange) verification
335
+ * Implements RFC 7636 with S256 challenge method
336
+ */
337
+ /**
338
+ * Verify a PKCE code challenge against a verifier
339
+ * @param verifier The code verifier from the token request
340
+ * @param challenge The code challenge from the authorization request
341
+ * @param method The challenge method (only S256 supported for AT Protocol)
342
+ * @returns true if the verifier matches the challenge
343
+ */
344
+ declare function verifyPkceChallenge(verifier: string, challenge: string, method: "S256"): Promise<boolean>;
345
+ //#endregion
346
+ //#region src/dpop.d.ts
347
+ /**
348
+ * Verified DPoP proof data
349
+ */
350
+ interface DpopProof {
351
+ /** HTTP method from the proof */
352
+ htm: string;
353
+ /** HTTP URI from the proof (without query/fragment) */
354
+ htu: string;
355
+ /** Unique proof identifier (for replay prevention) */
356
+ jti: string;
357
+ /** Access token hash (if present) */
358
+ ath?: string;
359
+ /** Key thumbprint (JWK thumbprint of the proof key) */
360
+ jkt: string;
361
+ /** The public JWK from the proof */
362
+ jwk: JWK;
363
+ }
364
+ /**
365
+ * DPoP verification options
366
+ */
367
+ interface DpopVerifyOptions {
368
+ /** Access token to verify ath claim against (optional) */
369
+ accessToken?: string;
370
+ /** Allowed signature algorithms (default: ['ES256']) */
371
+ allowedAlgorithms?: string[];
372
+ /** Expected nonce value (optional, for nonce binding) */
373
+ expectedNonce?: string;
374
+ /** Max token age in seconds (default: 60) */
375
+ maxTokenAge?: number;
376
+ }
377
+ /**
378
+ * DPoP verification error
379
+ */
380
+ declare class DpopError extends Error {
381
+ readonly code: string;
382
+ constructor(message: string, code: string, options?: ErrorOptions);
383
+ }
384
+ /**
385
+ * Verify a DPoP proof from a request
386
+ * Uses jose library for JWT verification
387
+ * @param request The HTTP request containing the DPoP header
388
+ * @param options Verification options
389
+ * @returns The verified proof data
390
+ * @throws DpopError if verification fails
391
+ */
392
+ declare function verifyDpopProof(request: Request, options?: DpopVerifyOptions): Promise<DpopProof>;
393
+ /**
394
+ * Generate a random DPoP nonce
395
+ * @returns A base64url-encoded random nonce (16 bytes)
396
+ */
397
+ declare function generateDpopNonce(): string;
398
+ //#endregion
399
+ //#region src/par.d.ts
400
+ /**
401
+ * OAuth error response
402
+ */
403
+ interface OAuthErrorResponse {
404
+ error: string;
405
+ error_description?: string;
406
+ }
407
+ /**
408
+ * Handler for Pushed Authorization Requests (PAR)
409
+ */
410
+ declare class PARHandler {
411
+ private storage;
412
+ private issuer;
413
+ private expiresIn;
414
+ /**
415
+ * Create a PAR handler
416
+ * @param storage OAuth storage implementation
417
+ * @param issuer The OAuth issuer URL
418
+ * @param expiresIn PAR expiration time in seconds (default: 90)
419
+ */
420
+ constructor(storage: OAuthStorage, issuer: string, expiresIn?: number);
421
+ /**
422
+ * Handle a PAR push request
423
+ * POST /oauth/par
424
+ * @param request The HTTP request
425
+ * @returns Response with request_uri or error
426
+ */
427
+ handlePushRequest(request: Request): Promise<Response>;
428
+ /**
429
+ * Retrieve and consume PAR parameters
430
+ * Called during authorization request handling
431
+ * @param requestUri The request URI from the authorization request
432
+ * @param clientId The client_id from the authorization request (for verification)
433
+ * @returns The stored parameters or null if not found/expired
434
+ */
435
+ retrieveParams(requestUri: string, clientId: string): Promise<Record<string, string> | null>;
436
+ /**
437
+ * Check if a request_uri is valid format
438
+ */
439
+ static isRequestUri(value: string): boolean;
440
+ /**
441
+ * Create an OAuth error response
442
+ */
443
+ private errorResponse;
444
+ }
445
+ //#endregion
446
+ //#region src/tokens.d.ts
447
+ /** Default access token TTL: 1 hour */
448
+ declare const ACCESS_TOKEN_TTL: number;
449
+ /** Default refresh token TTL: 90 days */
450
+ declare const REFRESH_TOKEN_TTL: number;
451
+ /** Authorization code TTL: 5 minutes */
452
+ declare const AUTH_CODE_TTL: number;
453
+ /**
454
+ * Generate a cryptographically random token
455
+ * @param bytes Number of random bytes (default: 32)
456
+ * @returns Base64URL-encoded token
457
+ */
458
+ declare function generateRandomToken(bytes?: number): string;
459
+ /**
460
+ * Generate an authorization code
461
+ * @returns A random authorization code
462
+ */
463
+ declare function generateAuthCode(): string;
464
+ /**
465
+ * Token generation result
466
+ */
467
+ interface GeneratedTokens {
468
+ /** Opaque access token */
469
+ accessToken: string;
470
+ /** Opaque refresh token */
471
+ refreshToken: string;
472
+ /** Access token type (Bearer or DPoP) */
473
+ tokenType: "Bearer" | "DPoP";
474
+ /** Access token expiration in seconds */
475
+ expiresIn: number;
476
+ /** Scope granted */
477
+ scope: string;
478
+ /** Subject (user DID) */
479
+ sub: string;
480
+ }
481
+ /**
482
+ * Options for token generation
483
+ */
484
+ interface GenerateTokensOptions {
485
+ /** User DID */
486
+ sub: string;
487
+ /** Client DID */
488
+ clientId: string;
489
+ /** Scope granted */
490
+ scope: string;
491
+ /** DPoP key thumbprint (if using DPoP) */
492
+ dpopJkt?: string;
493
+ /** Custom access token TTL in ms (default: 1 hour) */
494
+ accessTokenTtl?: number;
495
+ /** Custom refresh token TTL in ms (default: 90 days) */
496
+ refreshTokenTtl?: number;
497
+ }
498
+ /**
499
+ * Generate access and refresh tokens
500
+ * Tokens are opaque - their meaning comes from the database entry
501
+ * @param options Token generation options
502
+ * @returns Generated tokens and metadata
503
+ */
504
+ declare function generateTokens(options: GenerateTokensOptions): {
505
+ tokens: GeneratedTokens;
506
+ tokenData: TokenData;
507
+ };
508
+ /**
509
+ * Refresh tokens - generates new access token, optionally rotates refresh token
510
+ * @param existingData The existing token data
511
+ * @param rotateRefreshToken Whether to generate a new refresh token
512
+ * @param accessTokenTtl Custom access token TTL in ms
513
+ * @returns Updated tokens and token data
514
+ */
515
+ declare function refreshTokens(existingData: TokenData, rotateRefreshToken?: boolean, accessTokenTtl?: number): {
516
+ tokens: GeneratedTokens;
517
+ tokenData: TokenData;
518
+ };
519
+ /**
520
+ * Build token response for OAuth token endpoint
521
+ * @param tokens The generated tokens
522
+ * @returns JSON-serializable token response
523
+ */
524
+ declare function buildTokenResponse(tokens: GeneratedTokens): OAuthTokenResponse;
525
+ /**
526
+ * Extract access token from Authorization header
527
+ * Supports both Bearer and DPoP token types
528
+ * @param request The HTTP request
529
+ * @returns The access token and type, or null if not found
530
+ */
531
+ declare function extractAccessToken(request: Request): {
532
+ token: string;
533
+ type: "Bearer" | "DPoP";
534
+ } | null;
535
+ /**
536
+ * Validate that a token is not expired or revoked
537
+ * @param tokenData The token data from storage
538
+ * @returns true if the token is valid
539
+ */
540
+ declare function isTokenValid(tokenData: TokenData): boolean;
541
+ //#endregion
542
+ //#region src/ui.d.ts
543
+ /**
544
+ * Content Security Policy for the consent UI
545
+ *
546
+ * - default-src 'none': Deny all by default
547
+ * - style-src 'unsafe-inline': Allow inline styles (our CSS is inline)
548
+ * - img-src https: data:: Allow images from HTTPS URLs (client logos) and data URIs
549
+ * - form-action 'self': Form can only POST to same origin
550
+ * - frame-ancestors 'none': Prevent clickjacking by disallowing framing
551
+ * - base-uri 'none': Prevent base tag injection
552
+ */
553
+ declare const CONSENT_UI_CSP = "default-src 'none'; style-src 'unsafe-inline'; img-src https: data:; form-action 'self'; frame-ancestors 'none'; base-uri 'none'";
554
+ /**
555
+ * Options for rendering the consent UI
556
+ */
557
+ interface ConsentUIOptions {
558
+ /** The OAuth client metadata */
559
+ client: ClientMetadata;
560
+ /** The requested scope */
561
+ scope: string;
562
+ /** URL to POST the consent form to */
563
+ authorizeUrl: string;
564
+ /** State parameter to include in the form */
565
+ state: string;
566
+ /** OAuth parameters to include as hidden fields */
567
+ oauthParams: Record<string, string>;
568
+ /** User's handle (for display) */
569
+ userHandle?: string;
570
+ /** Whether to show a login form instead of consent */
571
+ showLogin?: boolean;
572
+ /** Error message to display */
573
+ error?: string;
574
+ }
575
+ /**
576
+ * Render the consent UI HTML
577
+ * @param options Consent UI options
578
+ * @returns HTML string
579
+ */
580
+ declare function renderConsentUI(options: ConsentUIOptions): string;
581
+ /**
582
+ * Render an error page
583
+ * @param error Error code
584
+ * @param description Error description
585
+ * @param redirectUri Optional redirect URI for the error
586
+ * @returns HTML string
587
+ */
588
+ declare function renderErrorPage(error: string, description: string, redirectUri?: string): string;
589
+ //#endregion
590
+ export { ACCESS_TOKEN_TTL, ATProtoOAuthProvider, AUTH_CODE_TTL, type AuthCodeData, CONSENT_UI_CSP, type ClientMetadata, ClientResolutionError, ClientResolver, type ClientResolverOptions, type ConsentUIOptions, DpopError, type DpopProof, type DpopVerifyOptions, type GenerateTokensOptions, type GeneratedTokens, InMemoryOAuthStorage, type OAuthClientMetadata, type OAuthErrorResponse, type OAuthParResponse, type OAuthProviderConfig, type OAuthStorage, type PARData, PARHandler, REFRESH_TOKEN_TTL, RequestBodyError, type TokenData, buildTokenResponse, createClientResolver, extractAccessToken, generateAuthCode, generateDpopNonce, generateRandomToken, generateTokens, isTokenValid, parseRequestBody, refreshTokens, renderConsentUI, renderErrorPage, verifyDpopProof, verifyPkceChallenge };
591
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/storage.ts","../src/client-resolver.ts","../src/provider.ts","../src/pkce.ts","../src/dpop.ts","../src/par.ts","../src/tokens.ts","../src/ui.ts"],"sourcesContent":[],"mappings":"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"}