@cloudflare/workers-oauth-provider 0.0.1

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