@cloudflare/workers-oauth-provider 0.0.0-6ab489d

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,550 @@
1
+ import { WorkerEntrypoint } from 'cloudflare:workers';
2
+
3
+ /**
4
+ * Aliases for either type of Handler that makes .fetch required
5
+ */
6
+ type ExportedHandlerWithFetch = ExportedHandler & Pick<Required<ExportedHandler>, 'fetch'>;
7
+ type WorkerEntrypointWithFetch = WorkerEntrypoint & Pick<Required<WorkerEntrypoint>, 'fetch'>;
8
+ /**
9
+ * Configuration options for the OAuth Provider
10
+ */
11
+ /**
12
+ * Result of a token exchange callback function.
13
+ * Allows updating the props stored in both the access token and the grant.
14
+ */
15
+ interface TokenExchangeCallbackResult {
16
+ /**
17
+ * New props to be stored specifically with the access token.
18
+ * If not provided but newProps is, the access token will use newProps.
19
+ * If neither is provided, the original props will be used.
20
+ */
21
+ accessTokenProps?: any;
22
+ /**
23
+ * New props to replace the props stored in the grant itself.
24
+ * These props will be used for all future token refreshes.
25
+ * If accessTokenProps is not provided, these props will also be used for the current access token.
26
+ * If not provided, the original props will be used.
27
+ */
28
+ newProps?: any;
29
+ /**
30
+ * Override the default access token TTL (time-to-live) for this specific token.
31
+ * This is especially useful when the application is also an OAuth client to another service
32
+ * and wants to match its access token TTL to the upstream access token TTL.
33
+ * Value should be in seconds.
34
+ */
35
+ accessTokenTTL?: number;
36
+ }
37
+ /**
38
+ * Options for token exchange callback functions
39
+ */
40
+ interface TokenExchangeCallbackOptions {
41
+ /**
42
+ * The type of grant being processed.
43
+ * 'authorization_code' for initial code exchange,
44
+ * 'refresh_token' for refresh token exchange.
45
+ */
46
+ grantType: 'authorization_code' | 'refresh_token';
47
+ /**
48
+ * Client that received this grant
49
+ */
50
+ clientId: string;
51
+ /**
52
+ * User who authorized this grant
53
+ */
54
+ userId: string;
55
+ /**
56
+ * List of scopes that were granted
57
+ */
58
+ scope: string[];
59
+ /**
60
+ * Application-specific properties currently associated with this grant
61
+ */
62
+ props: any;
63
+ }
64
+ interface OAuthProviderOptions {
65
+ /**
66
+ * URL(s) for API routes. Requests with URLs starting with any of these prefixes
67
+ * will be treated as API requests and require a valid access token.
68
+ * Can be a single route or an array of routes. Each route can be a full URL or just a path.
69
+ *
70
+ * Used with `apiHandler` for the single-handler configuration. This is incompatible with
71
+ * the `apiHandlers` property. You must use either `apiRoute` + `apiHandler` OR `apiHandlers`, not both.
72
+ */
73
+ apiRoute?: string | string[];
74
+ /**
75
+ * Handler for API requests that have a valid access token.
76
+ * This handler will receive the authenticated user properties in ctx.props.
77
+ * Can be either an ExportedHandler object with a fetch method or a class extending WorkerEntrypoint.
78
+ *
79
+ * Used with `apiRoute` for the single-handler configuration. This is incompatible with
80
+ * the `apiHandlers` property. You must use either `apiRoute` + `apiHandler` OR `apiHandlers`, not both.
81
+ */
82
+ apiHandler?: ExportedHandlerWithFetch | (new (ctx: ExecutionContext, env: any) => WorkerEntrypointWithFetch);
83
+ /**
84
+ * Map of API routes to their corresponding handlers for the multi-handler configuration.
85
+ * The keys are the API routes (strings only, not arrays), and the values are the handlers.
86
+ * Each route can be a full URL or just a path, and each handler can be either an ExportedHandler
87
+ * object with a fetch method or a class extending WorkerEntrypoint.
88
+ *
89
+ * This is incompatible with the `apiRoute` and `apiHandler` properties. You must use either
90
+ * `apiRoute` + `apiHandler` (single-handler configuration) OR `apiHandlers` (multi-handler
91
+ * configuration), not both.
92
+ */
93
+ apiHandlers?: Record<string, ExportedHandlerWithFetch | (new (ctx: ExecutionContext, env: any) => WorkerEntrypointWithFetch)>;
94
+ /**
95
+ * Handler for all non-API requests or API requests without a valid token.
96
+ * Can be either an ExportedHandler object with a fetch method or a class extending WorkerEntrypoint.
97
+ */
98
+ defaultHandler: ExportedHandler | (new (ctx: ExecutionContext, env: any) => WorkerEntrypointWithFetch);
99
+ /**
100
+ * URL of the OAuth authorization endpoint where users can grant permissions.
101
+ * This URL is used in OAuth metadata and is not handled by the provider itself.
102
+ */
103
+ authorizeEndpoint: string;
104
+ /**
105
+ * URL of the token endpoint which the provider will implement.
106
+ * This endpoint handles token issuance, refresh, and revocation.
107
+ */
108
+ tokenEndpoint: string;
109
+ /**
110
+ * Optional URL for the client registration endpoint.
111
+ * If provided, the provider will implement dynamic client registration.
112
+ */
113
+ clientRegistrationEndpoint?: string;
114
+ /**
115
+ * Time-to-live for access tokens in seconds.
116
+ * Defaults to 1 hour (3600 seconds) if not specified.
117
+ */
118
+ accessTokenTTL?: number;
119
+ /**
120
+ * List of scopes supported by this OAuth provider.
121
+ * If not provided, the 'scopes_supported' field will be omitted from the OAuth metadata.
122
+ */
123
+ scopesSupported?: string[];
124
+ /**
125
+ * Controls whether the OAuth implicit flow is allowed.
126
+ * This flow is discouraged in OAuth 2.1 due to security concerns.
127
+ * Defaults to false.
128
+ */
129
+ allowImplicitFlow?: boolean;
130
+ /**
131
+ * Controls whether public clients (clients without a secret, like SPAs) can register via the
132
+ * dynamic client registration endpoint. When true, only confidential clients can register.
133
+ * Note: Creating public clients via the OAuthHelpers.createClient() method is always allowed.
134
+ * Defaults to false.
135
+ */
136
+ disallowPublicClientRegistration?: boolean;
137
+ /**
138
+ * Optional callback function that is called during token exchange.
139
+ * This allows updating the props stored in both the access token and the grant.
140
+ * For example, if the application itself is also a client to some other OAuth API,
141
+ * it may want to perform the equivalent upstream token exchange, and store the result in the props.
142
+ *
143
+ * The callback can return new props values that will be stored with the token or grant.
144
+ * If the callback returns nothing or undefined for a props field, the original props will be used.
145
+ */
146
+ tokenExchangeCallback?: (options: TokenExchangeCallbackOptions) => Promise<TokenExchangeCallbackResult | void> | TokenExchangeCallbackResult | void;
147
+ /**
148
+ * Optional callback function that is called whenever the OAuthProvider returns an error response
149
+ * This allows the client to emit notifications or perform other actions when an error occurs.
150
+ *
151
+ * If the function returns a Response, that will be used in place of the OAuthProvider's default one.
152
+ */
153
+ onError?: (error: {
154
+ code: string;
155
+ description: string;
156
+ status: number;
157
+ headers: Record<string, string>;
158
+ }) => Response | void;
159
+ }
160
+ /**
161
+ * Helper methods for OAuth operations provided to handler functions
162
+ */
163
+ interface OAuthHelpers {
164
+ /**
165
+ * Parses an OAuth authorization request from the HTTP request
166
+ * @param request - The HTTP request containing OAuth parameters
167
+ * @returns The parsed authorization request parameters
168
+ */
169
+ parseAuthRequest(request: Request): Promise<AuthRequest>;
170
+ /**
171
+ * Looks up a client by its client ID
172
+ * @param clientId - The client ID to look up
173
+ * @returns A Promise resolving to the client info, or null if not found
174
+ */
175
+ lookupClient(clientId: string): Promise<ClientInfo | null>;
176
+ /**
177
+ * Completes an authorization request by creating a grant and authorization code
178
+ * @param options - Options specifying the grant details
179
+ * @returns A Promise resolving to an object containing the redirect URL
180
+ */
181
+ completeAuthorization(options: CompleteAuthorizationOptions): Promise<{
182
+ redirectTo: string;
183
+ }>;
184
+ /**
185
+ * Creates a new OAuth client
186
+ * @param clientInfo - Partial client information to create the client with
187
+ * @returns A Promise resolving to the created client info
188
+ */
189
+ createClient(clientInfo: Partial<ClientInfo>): Promise<ClientInfo>;
190
+ /**
191
+ * Lists all registered OAuth clients with pagination support
192
+ * @param options - Optional pagination parameters (limit and cursor)
193
+ * @returns A Promise resolving to the list result with items and optional cursor
194
+ */
195
+ listClients(options?: ListOptions): Promise<ListResult<ClientInfo>>;
196
+ /**
197
+ * Updates an existing OAuth client
198
+ * @param clientId - The ID of the client to update
199
+ * @param updates - Partial client information with fields to update
200
+ * @returns A Promise resolving to the updated client info, or null if not found
201
+ */
202
+ updateClient(clientId: string, updates: Partial<ClientInfo>): Promise<ClientInfo | null>;
203
+ /**
204
+ * Deletes an OAuth client
205
+ * @param clientId - The ID of the client to delete
206
+ * @returns A Promise resolving when the deletion is confirmed.
207
+ */
208
+ deleteClient(clientId: string): Promise<void>;
209
+ /**
210
+ * Lists all authorization grants for a specific user with pagination support
211
+ * Returns a summary of each grant without sensitive information
212
+ * @param userId - The ID of the user whose grants to list
213
+ * @param options - Optional pagination parameters (limit and cursor)
214
+ * @returns A Promise resolving to the list result with grant summaries and optional cursor
215
+ */
216
+ listUserGrants(userId: string, options?: ListOptions): Promise<ListResult<GrantSummary>>;
217
+ /**
218
+ * Revokes an authorization grant
219
+ * @param grantId - The ID of the grant to revoke
220
+ * @param userId - The ID of the user who owns the grant
221
+ * @returns A Promise resolving when the revocation is confirmed.
222
+ */
223
+ revokeGrant(grantId: string, userId: string): Promise<void>;
224
+ }
225
+ /**
226
+ * Parsed OAuth authorization request parameters
227
+ */
228
+ interface AuthRequest {
229
+ /**
230
+ * OAuth response type (e.g., "code" for authorization code flow)
231
+ */
232
+ responseType: string;
233
+ /**
234
+ * Client identifier for the OAuth client
235
+ */
236
+ clientId: string;
237
+ /**
238
+ * URL to redirect to after authorization
239
+ */
240
+ redirectUri: string;
241
+ /**
242
+ * Array of requested permission scopes
243
+ */
244
+ scope: string[];
245
+ /**
246
+ * Client state value to be returned in the redirect
247
+ */
248
+ state: string;
249
+ /**
250
+ * PKCE code challenge (RFC 7636)
251
+ */
252
+ codeChallenge?: string;
253
+ /**
254
+ * PKCE code challenge method (plain or S256)
255
+ */
256
+ codeChallengeMethod?: string;
257
+ }
258
+ /**
259
+ * OAuth client registration information
260
+ */
261
+ interface ClientInfo {
262
+ /**
263
+ * Unique identifier for the client
264
+ */
265
+ clientId: string;
266
+ /**
267
+ * Secret used to authenticate the client (stored as a hash)
268
+ * Only present for confidential clients; undefined for public clients.
269
+ */
270
+ clientSecret?: string;
271
+ /**
272
+ * List of allowed redirect URIs for the client
273
+ */
274
+ redirectUris: string[];
275
+ /**
276
+ * Human-readable name of the client application
277
+ */
278
+ clientName?: string;
279
+ /**
280
+ * URL to the client's logo
281
+ */
282
+ logoUri?: string;
283
+ /**
284
+ * URL to the client's homepage
285
+ */
286
+ clientUri?: string;
287
+ /**
288
+ * URL to the client's privacy policy
289
+ */
290
+ policyUri?: string;
291
+ /**
292
+ * URL to the client's terms of service
293
+ */
294
+ tosUri?: string;
295
+ /**
296
+ * URL to the client's JSON Web Key Set for validating signatures
297
+ */
298
+ jwksUri?: string;
299
+ /**
300
+ * List of email addresses for contacting the client developers
301
+ */
302
+ contacts?: string[];
303
+ /**
304
+ * List of grant types the client supports
305
+ */
306
+ grantTypes?: string[];
307
+ /**
308
+ * List of response types the client supports
309
+ */
310
+ responseTypes?: string[];
311
+ /**
312
+ * Unix timestamp when the client was registered
313
+ */
314
+ registrationDate?: number;
315
+ /**
316
+ * The authentication method used by the client at the token endpoint.
317
+ * Values include:
318
+ * - 'client_secret_basic': Uses HTTP Basic Auth with client ID and secret (default for confidential clients)
319
+ * - 'client_secret_post': Uses POST parameters for client authentication
320
+ * - 'none': Used for public clients that can't securely store secrets (SPAs, mobile apps, etc.)
321
+ *
322
+ * Public clients use 'none', while confidential clients use either 'client_secret_basic' or 'client_secret_post'.
323
+ */
324
+ tokenEndpointAuthMethod: string;
325
+ }
326
+ /**
327
+ * Options for completing an authorization request
328
+ */
329
+ interface CompleteAuthorizationOptions {
330
+ /**
331
+ * The original parsed authorization request
332
+ */
333
+ request: AuthRequest;
334
+ /**
335
+ * Identifier for the user granting the authorization
336
+ */
337
+ userId: string;
338
+ /**
339
+ * Application-specific metadata to associate with this grant
340
+ */
341
+ metadata: any;
342
+ /**
343
+ * List of scopes that were actually granted (may differ from requested scopes)
344
+ */
345
+ scope: string[];
346
+ /**
347
+ * Application-specific properties to include with API requests
348
+ * authorized by this grant
349
+ */
350
+ props: any;
351
+ }
352
+ /**
353
+ * Authorization grant record
354
+ */
355
+ interface Grant {
356
+ /**
357
+ * Unique identifier for the grant
358
+ */
359
+ id: string;
360
+ /**
361
+ * Client that received this grant
362
+ */
363
+ clientId: string;
364
+ /**
365
+ * User who authorized this grant
366
+ */
367
+ userId: string;
368
+ /**
369
+ * List of scopes that were granted
370
+ */
371
+ scope: string[];
372
+ /**
373
+ * Application-specific metadata associated with this grant
374
+ */
375
+ metadata: any;
376
+ /**
377
+ * Encrypted application-specific properties
378
+ */
379
+ encryptedProps: string;
380
+ /**
381
+ * Unix timestamp when the grant was created
382
+ */
383
+ createdAt: number;
384
+ /**
385
+ * The hash of the current refresh token associated with this grant
386
+ */
387
+ refreshTokenId?: string;
388
+ /**
389
+ * Wrapped encryption key for the current refresh token
390
+ */
391
+ refreshTokenWrappedKey?: string;
392
+ /**
393
+ * The hash of the previous refresh token associated with this grant
394
+ * This token is still valid until the new token is first used
395
+ */
396
+ previousRefreshTokenId?: string;
397
+ /**
398
+ * Wrapped encryption key for the previous refresh token
399
+ */
400
+ previousRefreshTokenWrappedKey?: string;
401
+ /**
402
+ * The hash of the authorization code associated with this grant
403
+ * Only present during the authorization code exchange process
404
+ */
405
+ authCodeId?: string;
406
+ /**
407
+ * Wrapped encryption key for the authorization code
408
+ * Only present during the authorization code exchange process
409
+ */
410
+ authCodeWrappedKey?: string;
411
+ /**
412
+ * PKCE code challenge for this authorization
413
+ * Only present during the authorization code exchange process
414
+ */
415
+ codeChallenge?: string;
416
+ /**
417
+ * PKCE code challenge method (plain or S256)
418
+ * Only present during the authorization code exchange process
419
+ */
420
+ codeChallengeMethod?: string;
421
+ }
422
+ /**
423
+ * Token record stored in KV
424
+ * Note: The actual token format is "{userId}:{grantId}:{random-secret}"
425
+ * but we still only store the hash of the full token string.
426
+ * This contains only access tokens; refresh tokens are stored within the grant records.
427
+ */
428
+ interface Token {
429
+ /**
430
+ * Unique identifier for the token (hash of the actual token)
431
+ */
432
+ id: string;
433
+ /**
434
+ * Identifier of the grant this token is associated with
435
+ */
436
+ grantId: string;
437
+ /**
438
+ * User ID associated with this token
439
+ */
440
+ userId: string;
441
+ /**
442
+ * Unix timestamp when the token was created
443
+ */
444
+ createdAt: number;
445
+ /**
446
+ * Unix timestamp when the token expires
447
+ */
448
+ expiresAt: number;
449
+ /**
450
+ * The encryption key for props, wrapped with this token
451
+ */
452
+ wrappedEncryptionKey: string;
453
+ /**
454
+ * Denormalized grant information for faster access
455
+ */
456
+ grant: {
457
+ /**
458
+ * Client that received this grant
459
+ */
460
+ clientId: string;
461
+ /**
462
+ * List of scopes that were granted
463
+ */
464
+ scope: string[];
465
+ /**
466
+ * Encrypted application-specific properties
467
+ */
468
+ encryptedProps: string;
469
+ };
470
+ }
471
+ /**
472
+ * Options for listing operations that support pagination
473
+ */
474
+ interface ListOptions {
475
+ /**
476
+ * Maximum number of items to return (max 1000)
477
+ */
478
+ limit?: number;
479
+ /**
480
+ * Cursor for pagination (from a previous listing operation)
481
+ */
482
+ cursor?: string;
483
+ }
484
+ /**
485
+ * Result of a listing operation with pagination support
486
+ */
487
+ interface ListResult<T> {
488
+ /**
489
+ * The list of items
490
+ */
491
+ items: T[];
492
+ /**
493
+ * Cursor to get the next page of results, if there are more results
494
+ */
495
+ cursor?: string;
496
+ }
497
+ /**
498
+ * Public representation of a grant, with sensitive data removed
499
+ * Used for list operations where the complete grant data isn't needed
500
+ */
501
+ interface GrantSummary {
502
+ /**
503
+ * Unique identifier for the grant
504
+ */
505
+ id: string;
506
+ /**
507
+ * Client that received this grant
508
+ */
509
+ clientId: string;
510
+ /**
511
+ * User who authorized this grant
512
+ */
513
+ userId: string;
514
+ /**
515
+ * List of scopes that were granted
516
+ */
517
+ scope: string[];
518
+ /**
519
+ * Application-specific metadata associated with this grant
520
+ */
521
+ metadata: any;
522
+ /**
523
+ * Unix timestamp when the grant was created
524
+ */
525
+ createdAt: number;
526
+ }
527
+ /**
528
+ * OAuth 2.0 Provider implementation for Cloudflare Workers
529
+ * Implements authorization code flow with support for refresh tokens
530
+ * and dynamic client registration.
531
+ */
532
+ declare class OAuthProvider {
533
+ #private;
534
+ /**
535
+ * Creates a new OAuth provider instance
536
+ * @param options - Configuration options for the provider
537
+ */
538
+ constructor(options: OAuthProviderOptions);
539
+ /**
540
+ * Main fetch handler for the Worker
541
+ * Routes requests to the appropriate handler based on the URL
542
+ * @param request - The HTTP request
543
+ * @param env - Cloudflare Worker environment variables
544
+ * @param ctx - Cloudflare Worker execution context
545
+ * @returns A Promise resolving to an HTTP Response
546
+ */
547
+ fetch(request: Request, env: any, ctx: ExecutionContext): Promise<Response>;
548
+ }
549
+
550
+ export { type AuthRequest, type ClientInfo, type CompleteAuthorizationOptions, type Grant, type GrantSummary, type ListOptions, type ListResult, type OAuthHelpers, OAuthProvider, type OAuthProviderOptions, type Token, type TokenExchangeCallbackOptions, type TokenExchangeCallbackResult, OAuthProvider as default };