@julr/sesame 0.5.0 → 0.6.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.
Files changed (74) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +405 -62
  3. package/build/authorize_controller-BiycO4be.js +251 -0
  4. package/build/chunk-DF48asd8.js +9 -0
  5. package/build/{client_info_controller-BucHGx4u.js → client_info_controller-AcOG8lWu.js} +11 -3
  6. package/build/commands/sesame_client.d.ts +20 -0
  7. package/build/commands/sesame_key.d.ts +12 -0
  8. package/build/commands/sesame_purge.d.ts +0 -2
  9. package/build/commands/sesame_purge.js +15 -3
  10. package/build/configure-DkDkIlt8.js +27 -0
  11. package/build/configure.js +2 -24
  12. package/build/consent_controller-Dsdhv6-f.js +108 -0
  13. package/build/id_token_service-CpTzOUDe.js +54 -0
  14. package/build/index.d.ts +1 -1
  15. package/build/index.js +30 -10
  16. package/build/{introspect_controller-un95fs4y.js → introspect_controller-DvOp9scr.js} +21 -7
  17. package/build/issue_authorization_code-B9ERu1uO.js +40 -0
  18. package/build/jwks_controller-keo4kBZc.js +26 -0
  19. package/build/{main-B3M6ihoS.js → main-DGBJhq3E.js} +34 -4
  20. package/build/metadata_controller-BVsTo0Gp.js +158 -0
  21. package/build/{oauth_access_token-bsoM5KeU.js → oauth_access_token-Cz_5gNBx.js} +12 -1
  22. package/build/oauth_client-BSanvSql.js +63 -0
  23. package/build/oauth_error-C7UhDb2q.js +189 -0
  24. package/build/providers/sesame_provider.js +14 -3
  25. package/build/{register_controller-Dch4ecyD.js → register_controller-gbq7p8a5.js} +46 -7
  26. package/build/{revoke_controller-DnPmzYMd.js → revoke_controller-z_ghrEB7.js} +21 -8
  27. package/build/services/main.js +7 -3
  28. package/build/sesame_manager-B1Jgq1v2.js +6 -0
  29. package/build/sesame_manager-DYUSZ0NC.js +693 -0
  30. package/build/src/actions/authorize.d.ts +46 -0
  31. package/build/src/actions/exchange_authorization_code.d.ts +34 -0
  32. package/build/src/actions/exchange_client_credentials.d.ts +28 -0
  33. package/build/src/actions/exchange_refresh_token.d.ts +59 -0
  34. package/build/src/actions/issue_authorization_code.d.ts +26 -0
  35. package/build/src/controllers/authorize_controller.d.ts +13 -12
  36. package/build/src/controllers/consent_controller.d.ts +5 -0
  37. package/build/src/controllers/jwks_controller.d.ts +14 -0
  38. package/build/src/controllers/metadata_controller.d.ts +9 -2
  39. package/build/src/controllers/token_controller.d.ts +8 -5
  40. package/build/src/controllers/userinfo_controller.d.ts +14 -0
  41. package/build/src/guard/main.js +5 -5
  42. package/build/src/middleware/any_scope_middleware.js +11 -1
  43. package/build/src/middleware/scope_middleware.js +11 -1
  44. package/build/src/models/oauth_authorization_code.d.ts +1 -0
  45. package/build/src/models/oauth_pending_authorization_request.d.ts +1 -0
  46. package/build/src/oauth_error.d.ts +1 -1
  47. package/build/src/routes.d.ts +3 -1
  48. package/build/src/services/id_token_service.d.ts +30 -0
  49. package/build/src/services/key_service.d.ts +20 -0
  50. package/build/src/sesame_manager.d.ts +54 -3
  51. package/build/src/types.d.ts +124 -3
  52. package/build/stubs/main.ts +5 -0
  53. package/build/stubs/migrations/create_oauth_authorization_codes_table.stub +1 -0
  54. package/build/stubs/migrations/create_oauth_pending_authorization_requests_table.stub +1 -0
  55. package/build/stubs/migrations/create_oauth_refresh_tokens_table.stub +1 -1
  56. package/build/token_controller-DyI7oy-U.js +481 -0
  57. package/build/token_service-DwnfAR9F.js +59 -0
  58. package/build/userinfo_controller-RLk8cN_o.js +40 -0
  59. package/build/vite.config.d.ts +2 -0
  60. package/package.json +26 -41
  61. package/build/authorize_controller-BGzxPvYU.js +0 -138
  62. package/build/client_service-C3rfXGk_.js +0 -65
  63. package/build/consent_controller-BHoB9mip.js +0 -85
  64. package/build/decorate-BKZEjPRg.js +0 -15
  65. package/build/metadata_controller-CJeZG93_.js +0 -81
  66. package/build/oauth_client-BIoY5jBR.js +0 -24
  67. package/build/oauth_error-CnJ3L8tf.js +0 -94
  68. package/build/sesame_manager-BQIW2mqt.js +0 -4
  69. package/build/sesame_manager-C-eEFFHM.js +0 -167
  70. package/build/src/grants/authorization_code_grant.d.ts +0 -27
  71. package/build/src/grants/client_credentials_grant.d.ts +0 -23
  72. package/build/src/grants/refresh_token_grant.d.ts +0 -27
  73. package/build/token_controller-hGDAYuBS.js +0 -194
  74. package/build/token_service-fhoA4slP.js +0 -31
@@ -1,4 +1,6 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
+ import type { JWK } from 'jose';
3
+ import type { OAuthUserProviderContract } from './guard/types.ts';
2
4
  /**
3
5
  * Augment this interface via module augmentation to enable
4
6
  * type-safe scope names across the application.
@@ -30,14 +32,63 @@ export type InferScopes<T extends {
30
32
  * Standard OAuth/OIDC scopes that are always valid regardless
31
33
  * of server or client scope configuration.
32
34
  *
35
+ * These scopes are:
36
+ * - Accepted during scope validation (client and server level)
37
+ * - Advertised in `scopes_supported` of all metadata endpoints
38
+ * (protected resource, OIDC discovery) so MCP clients know
39
+ * they can request them
40
+ *
33
41
  * - `offline_access`: signals that the client needs a refresh token
34
- * (OIDC Core §11, OAuth 2.1). Without this built-in treatment,
35
- * MCP clients that don't explicitly configure scopes would never
36
- * receive a refresh token and would expire after the access token TTL.
42
+ * (OIDC Core §11). Note: Sesame issues refresh tokens by default
43
+ * when the `refresh_token` grant is enabled, regardless of whether
44
+ * the client requests this scope (per RFC 6749 §5.1). This scope
45
+ * is still advertised for clients that check metadata before
46
+ * building their authorization request.
37
47
  *
38
48
  * @see https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
49
+ * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
39
50
  */
40
51
  export declare const BUILTIN_SCOPES: Set<string>;
52
+ /**
53
+ * OIDC-recognized scopes that are accepted by server-level validation
54
+ * without needing to be declared in the config `scopes` map.
55
+ *
56
+ * Unlike `BUILTIN_SCOPES`, these still require explicit client authorization
57
+ * via `ClientService.validateClientScopes()`.
58
+ */
59
+ export declare const OIDC_SCOPES: Set<string>;
60
+ /**
61
+ * Protocol-managed claims that must never be overridden by `getOidcClaims()`.
62
+ */
63
+ export declare const RESERVED_OIDC_CLAIMS: Set<string>;
64
+ /**
65
+ * Interface for User models that provide OIDC claims.
66
+ * Implement this on your User model to include custom claims
67
+ * in id_tokens and /userinfo responses.
68
+ *
69
+ * If not implemented, only protocol-level claims (sub, iss, aud, exp, iat)
70
+ * are included.
71
+ */
72
+ export interface OidcSubject {
73
+ getOidcClaims(scopes: Scope[]): Record<string, unknown> | Promise<Record<string, unknown>>;
74
+ }
75
+ /**
76
+ * Collect OIDC claims based on the granted scopes.
77
+ *
78
+ * Maps each scope to its corresponding claims object and merges
79
+ * only the claims for scopes present in the granted set.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * getOidcClaims(scopes: Scope[]) {
84
+ * return collectOidcClaims(scopes, {
85
+ * profile: { name: this.fullName },
86
+ * email: { email: this.email },
87
+ * })
88
+ * }
89
+ * ```
90
+ */
91
+ export declare function collectOidcClaims(scopes: Scope[], claimsMap: Partial<Record<Scope, Record<string, unknown>>>): Record<string, unknown>;
41
92
  /**
42
93
  * Supported OAuth 2.1 grant types.
43
94
  *
@@ -50,6 +101,39 @@ export declare const BUILTIN_SCOPES: Set<string>;
50
101
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
51
102
  */
52
103
  export type GrantType = 'authorization_code' | 'refresh_token' | 'client_credentials';
104
+ /**
105
+ * Options for creating an OAuth client programmatically.
106
+ */
107
+ export interface CreateClientOptions {
108
+ name: string;
109
+ redirectUris: string[];
110
+ scopes?: string[];
111
+ grantTypes?: GrantType[];
112
+ isPublic?: boolean;
113
+ requirePkce?: boolean;
114
+ userId?: string;
115
+ metadata?: Record<string, any>;
116
+ }
117
+ /**
118
+ * Options for updating an existing OAuth client.
119
+ */
120
+ export interface UpdateClientOptions {
121
+ name?: string;
122
+ redirectUris?: string[];
123
+ scopes?: string[];
124
+ grantTypes?: GrantType[];
125
+ isDisabled?: boolean;
126
+ requirePkce?: boolean;
127
+ metadata?: Record<string, any>;
128
+ }
129
+ /**
130
+ * Result returned when creating a client.
131
+ * Includes the raw secret (only available at creation time).
132
+ */
133
+ export interface CreateClientResult {
134
+ client: import('./models/oauth_client.ts').OAuthClient;
135
+ clientSecret: string | null;
136
+ }
53
137
  /**
54
138
  * User-facing configuration interface for Sésame.
55
139
  *
@@ -91,6 +175,18 @@ export interface SesameConfig {
91
175
  * Defaults to '30d'.
92
176
  */
93
177
  refreshTokenTtl?: string;
178
+ /**
179
+ * Grace period (in seconds) during which a recently-rotated
180
+ * refresh token is still accepted instead of triggering
181
+ * replay-attack detection. Handles race conditions in
182
+ * multi-process clients (e.g. MCP SDK).
183
+ *
184
+ * Set to `0` to disable (strict rotation, no grace period).
185
+ * Defaults to `120` (2 minutes).
186
+ *
187
+ * @see https://auth0.com/docs/secure/tokens/refresh-tokens/configure-refresh-token-rotation
188
+ */
189
+ refreshTokenRotationGracePeriod?: number;
94
190
  /**
95
191
  * Access token TTL for the client_credentials grant (M2M).
96
192
  * Defaults to `accessTokenTtl`.
@@ -133,6 +229,27 @@ export interface SesameConfig {
133
229
  * Defaults to `false`.
134
230
  */
135
231
  allowPublicRegistration?: boolean;
232
+ /**
233
+ * JWK (JSON Web Key) for signing ID tokens.
234
+ * Must be an RSA private key in JWK format.
235
+ * Required together with `oidcProvider` when OIDC scopes (openid) are used.
236
+ * Passed via env var, parsed at boot, lives in memory.
237
+ */
238
+ jwk?: JWK;
239
+ /**
240
+ * User provider used by OIDC flows to resolve the subject for
241
+ * `id_token` emission and `/userinfo`.
242
+ *
243
+ * This is independent from `@adonisjs/auth` guards. The provider is
244
+ * configured once for the authorization server and must be stable for
245
+ * the issuer. Required together with `jwk` to enable OIDC.
246
+ */
247
+ oidcProvider?: OAuthUserProviderContract<unknown>;
248
+ /**
249
+ * ID token TTL as a string duration (e.g. '1h', '10m').
250
+ * Defaults to '1h'.
251
+ */
252
+ idTokenTtl?: string;
136
253
  }
137
254
  /**
138
255
  * Fully resolved configuration with defaults applied.
@@ -146,12 +263,16 @@ export interface ResolvedSesameConfig {
146
263
  accessTokenTtl: string;
147
264
  clientCredentialsAccessTokenTtl: string;
148
265
  refreshTokenTtl: string;
266
+ refreshTokenRotationGracePeriod: number;
149
267
  authorizationCodeTtl: string;
150
268
  authorizationRequestTtl: string;
151
269
  loginPage: string | ((ctx: HttpContext, params: URLSearchParams) => string);
152
270
  consentPage: string | ((ctx: HttpContext, params: URLSearchParams) => string);
153
271
  allowDynamicRegistration: boolean;
154
272
  allowPublicRegistration: boolean;
273
+ jwk?: JWK;
274
+ oidcProvider?: OAuthUserProviderContract<unknown>;
275
+ idTokenTtl: string;
155
276
  }
156
277
  /**
157
278
  * OAuth 2.0 Authorization Server Metadata as defined by RFC 8414.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Path to the root directory where the stubs are stored. We use
3
+ * this path within commands and the configure hook
4
+ */
5
+ export const stubsRoot = import.meta.dirname
@@ -15,6 +15,7 @@ export default class extends BaseSchema {
15
15
  table.text('redirect_uri').notNullable()
16
16
  table.string('code_challenge').nullable()
17
17
  table.string('code_challenge_method').nullable()
18
+ table.string('nonce').nullable()
18
19
  table.timestamp('expires_at').notNullable()
19
20
  table.timestamp('created_at').notNullable()
20
21
  table.timestamp('updated_at').notNullable()
@@ -21,6 +21,7 @@ export default class extends BaseSchema {
21
21
  table.string('state').nullable()
22
22
  table.string('code_challenge').nullable()
23
23
  table.string('code_challenge_method').nullable()
24
+ table.string('nonce').nullable()
24
25
  table.timestamp('expires_at').notNullable()
25
26
  table.timestamp('created_at').notNullable()
26
27
  })
@@ -9,7 +9,7 @@ export default class extends BaseSchema {
9
9
  this.schema.createTable(this.tableName, (table) => {
10
10
  table.uuid('id').primary()
11
11
  table.string('token').notNullable().index()
12
- table.string('access_token_id').notNullable()
12
+ table.uuid('access_token_id').notNullable()
13
13
  table.string('client_id').notNullable().references('client_id').inTable('oauth_clients').onDelete('CASCADE')
14
14
  table.string('user_id').notNullable()
15
15
  table.json('scopes').notNullable()