@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
@@ -0,0 +1,46 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ export interface AuthorizeInput {
3
+ clientId: string;
4
+ responseType: string;
5
+ redirectUri: string;
6
+ scope?: string;
7
+ state?: string;
8
+ codeChallenge?: string;
9
+ codeChallengeMethod?: string;
10
+ nonce?: string;
11
+ userId?: string;
12
+ }
13
+ export type AuthorizeResult = {
14
+ type: 'redirect_error';
15
+ error: string;
16
+ description: string;
17
+ } | {
18
+ type: 'login_required';
19
+ } | {
20
+ type: 'consent_required';
21
+ authToken: string;
22
+ scopes: string[];
23
+ } | {
24
+ type: 'authorized';
25
+ code: string;
26
+ };
27
+ /**
28
+ * Handles the OAuth 2.0 authorization request business logic.
29
+ *
30
+ * Validates the client, scopes, and PKCE parameters, checks
31
+ * existing consent, and either issues an authorization code
32
+ * or signals that login/consent is required.
33
+ *
34
+ * Errors before redirect_uri validation are thrown as exceptions.
35
+ * Errors after are returned as `redirect_error` results so the
36
+ * controller can redirect back to the client per spec.
37
+ */
38
+ export declare class AuthorizeAction {
39
+ #private;
40
+ /**
41
+ * Process an authorization request. Returns a discriminated
42
+ * union that the controller interprets as the appropriate
43
+ * HTTP redirect.
44
+ */
45
+ execute(manager: SesameManager, input: AuthorizeInput): Promise<AuthorizeResult>;
46
+ }
@@ -0,0 +1,34 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ import type { OAuthClient } from '../models/oauth_client.ts';
3
+ export interface ExchangeAuthorizationCodeInput {
4
+ client: OAuthClient;
5
+ code: string;
6
+ redirectUri: string;
7
+ codeVerifier: string;
8
+ }
9
+ /**
10
+ * Handle the Authorization Code Grant (RFC 6749 §4.1.3).
11
+ *
12
+ * Exchanges an authorization code for an access token and
13
+ * optionally a refresh token and id_token. Verifies PKCE,
14
+ * validates scopes, and atomically consumes the code to
15
+ * prevent replay.
16
+ *
17
+ * @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
18
+ * @see https://datatracker.ietf.org/doc/html/rfc7636#section-4.6
19
+ */
20
+ export declare class ExchangeAuthorizationCodeAction {
21
+ #private;
22
+ /**
23
+ * Exchange an authorization code for tokens. The code is
24
+ * consumed atomically inside a transaction.
25
+ */
26
+ execute(manager: SesameManager, input: ExchangeAuthorizationCodeInput): Promise<{
27
+ id_token?: string | undefined;
28
+ refresh_token?: string | undefined;
29
+ access_token: string;
30
+ token_type: "Bearer";
31
+ expires_in: number;
32
+ scope: string;
33
+ }>;
34
+ }
@@ -0,0 +1,28 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ import type { OAuthClient } from '../models/oauth_client.ts';
3
+ export interface ExchangeClientCredentialsInput {
4
+ client: OAuthClient;
5
+ scope?: string;
6
+ }
7
+ /**
8
+ * Handle the Client Credentials Grant (RFC 6749 §4.4).
9
+ *
10
+ * Issues an access token directly to a confidential client
11
+ * for machine-to-machine communication. No refresh token
12
+ * is issued. User-centric OIDC scopes are rejected.
13
+ *
14
+ * @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.4
15
+ */
16
+ export declare class ExchangeClientCredentialsAction {
17
+ #private;
18
+ /**
19
+ * Validate the client, resolve scopes, and issue an
20
+ * access token for M2M usage.
21
+ */
22
+ execute(manager: SesameManager, input: ExchangeClientCredentialsInput): Promise<{
23
+ access_token: string;
24
+ token_type: "Bearer";
25
+ expires_in: number;
26
+ scope: string;
27
+ }>;
28
+ }
@@ -0,0 +1,59 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ import type { OAuthClient } from '../models/oauth_client.ts';
3
+ export interface ExchangeRefreshTokenInput {
4
+ client: OAuthClient;
5
+ refreshToken: string;
6
+ scope?: string;
7
+ }
8
+ /**
9
+ * Handle the Refresh Token Grant (RFC 6749 §6).
10
+ *
11
+ * Exchanges a refresh token for a new access token and a new
12
+ * refresh token (rotation). The old refresh token is revoked
13
+ * immediately after use.
14
+ *
15
+ * ## Replay detection
16
+ *
17
+ * If a revoked refresh token is presented **outside** the grace
18
+ * period, all tokens for that client+user pair are nuked to
19
+ * mitigate stolen-token reuse (RFC 6819 §5.2.2.3, RFC 9700 §4.14.2).
20
+ *
21
+ * ## Grace period (rotation reuse window)
22
+ *
23
+ * OAuth 2.1 requires that rotated refresh tokens be single-use.
24
+ * However, that requirement conflicts with the realities of
25
+ * distributed systems: if the server rotates the token but the
26
+ * client never receives (or persists) the new token — due to a
27
+ * network failure, a concurrent refresh from another process, or
28
+ * a retry after timeout — the client loses its grant permanently.
29
+ *
30
+ * To handle this, we allow a recently-rotated refresh token to be
31
+ * reused within a short configurable window (`refreshTokenRotationGracePeriod`,
32
+ * defaults to 120 s). During that window the old token issues fresh
33
+ * tokens without triggering replay-attack revocation.
34
+ *
35
+ * This is the same approach used by Auth0 ("reuse interval") and
36
+ * Cloudflare workers-oauth-provider ("previous token"). It provides
37
+ * most of the security benefits of strict rotation while remaining
38
+ * reliable for real-world clients (MCP SDK, multi-process CLIs, etc.).
39
+ *
40
+ * @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
41
+ * @see https://datatracker.ietf.org/doc/html/rfc6819#section-5.2.2.3
42
+ * @see https://datatracker.ietf.org/doc/html/rfc9700#section-4.14.2
43
+ */
44
+ export declare class ExchangeRefreshTokenAction {
45
+ #private;
46
+ /**
47
+ * Rotate the refresh token, issue a new access token,
48
+ * and optionally reissue an id_token if openid scope
49
+ * is present.
50
+ */
51
+ execute(manager: SesameManager, input: ExchangeRefreshTokenInput): Promise<{
52
+ id_token?: string | undefined;
53
+ access_token: string;
54
+ token_type: "Bearer";
55
+ expires_in: number;
56
+ scope: string;
57
+ refresh_token: string;
58
+ }>;
59
+ }
@@ -0,0 +1,26 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ import type { OAuthClient } from '../models/oauth_client.ts';
3
+ export interface AuthorizationCodeInput {
4
+ client: OAuthClient;
5
+ userId: string;
6
+ scopes: string[];
7
+ redirectUri: string;
8
+ codeChallenge?: string;
9
+ codeChallengeMethod?: string;
10
+ nonce?: string;
11
+ }
12
+ /**
13
+ * Create and persist an authorization code in the database.
14
+ * Returns the raw (unhashed) code to be sent to the client.
15
+ *
16
+ * Shared between the authorize and consent flows to avoid
17
+ * duplicating the code-issuance logic.
18
+ */
19
+ export declare class IssueAuthorizationCodeAction {
20
+ /**
21
+ * Generate an opaque authorization code, store its SHA-256
22
+ * hash in the database, and return the raw value for the
23
+ * client redirect.
24
+ */
25
+ execute(manager: SesameManager, input: AuthorizationCodeInput): Promise<string>;
26
+ }
@@ -2,17 +2,10 @@ import type { HttpContext } from '@adonisjs/core/http';
2
2
  /**
3
3
  * Handles the OAuth 2.0 Authorization Endpoint (RFC 6749 §3.1).
4
4
  *
5
- * Implements the authorization code flow with PKCE support (RFC 7636).
6
- * Validates the client, requested scopes, and PKCE parameters, then
7
- * either redirects the user to the login/consent page or directly
8
- * issues an authorization code if consent was already granted.
9
- *
10
- * The `iss` response parameter is included per RFC 9207 to prevent
11
- * mix-up attacks.
5
+ * Validates HTTP parameters, delegates business logic to
6
+ * AuthorizeAction, and interprets the result as redirects.
12
7
  *
13
8
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-3.1
14
- * @see https://datatracker.ietf.org/doc/html/rfc7636
15
- * @see https://datatracker.ietf.org/doc/html/rfc9207
16
9
  */
17
10
  export default class AuthorizeController {
18
11
  #private;
@@ -24,30 +17,38 @@ export default class AuthorizeController {
24
17
  state: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine").VineString>;
25
18
  code_challenge: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine").VineString>;
26
19
  code_challenge_method: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine").VineString>;
20
+ nonce: import("@vinejs/vine/schema/base/literal").OptionalModifier<import("@vinejs/vine").VineString>;
27
21
  }, {
22
+ nonce?: string | null | undefined;
28
23
  scope?: string | null | undefined;
29
24
  state?: string | null | undefined;
30
25
  code_challenge?: string | null | undefined;
31
26
  code_challenge_method?: string | null | undefined;
32
- redirect_uri: string;
33
27
  client_id: string;
28
+ redirect_uri: string;
34
29
  response_type: string;
35
30
  }, {
31
+ nonce?: string | undefined;
36
32
  scope?: string | undefined;
37
33
  state?: string | undefined;
38
34
  code_challenge?: string | undefined;
39
35
  code_challenge_method?: string | undefined;
40
- redirect_uri: string;
41
36
  client_id: string;
37
+ redirect_uri: string;
42
38
  response_type: string;
43
39
  }, {
40
+ nonce?: string | undefined;
44
41
  scope?: string | undefined;
45
42
  state?: string | undefined;
46
43
  code_challenge?: string | undefined;
47
44
  code_challenge_method?: string | undefined;
48
- redirect_uri: string;
49
45
  client_id: string;
46
+ redirect_uri: string;
50
47
  response_type: string;
51
48
  }>, Record<string, any> | undefined>;
49
+ /**
50
+ * Validate the authorization request query params, run the
51
+ * authorize action, and redirect based on the result.
52
+ */
52
53
  handle(ctx: HttpContext): Promise<void>;
53
54
  }
@@ -23,5 +23,10 @@ export default class ConsentController {
23
23
  }, {
24
24
  auth_token: string;
25
25
  }>, Record<string, any> | undefined>;
26
+ /**
27
+ * Validate the consent submission, consume the pending
28
+ * request, and redirect back to the client with either
29
+ * an authorization code or an access_denied error.
30
+ */
26
31
  handle(ctx: HttpContext): Promise<void>;
27
32
  }
@@ -0,0 +1,14 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ /**
3
+ * Serves the JSON Web Key Set (JWKS) containing public keys
4
+ * used to verify ID token signatures.
5
+ *
6
+ * @see https://datatracker.ietf.org/doc/html/rfc7517
7
+ */
8
+ export default class JwksController {
9
+ handle(ctx: HttpContext): Promise<{
10
+ keys: import("jose").JWK[];
11
+ } | {
12
+ error: string;
13
+ }>;
14
+ }
@@ -1,5 +1,5 @@
1
1
  import type { HttpContext } from '@adonisjs/core/http';
2
- import type { AuthServerMetadata, ResourceServerMetadata } from '../types.ts';
2
+ import { type AuthServerMetadata, type ResourceServerMetadata } from '../types.ts';
3
3
  /**
4
4
  * Serves OAuth 2.0 discovery metadata documents.
5
5
  *
@@ -34,15 +34,21 @@ export default class MetadataController {
34
34
  * @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
35
35
  */
36
36
  oidc(ctx: HttpContext): Promise<{
37
+ error: string;
38
+ } | {
39
+ userinfo_endpoint: string;
40
+ jwks_uri: string;
37
41
  subject_types_supported: string[];
42
+ id_token_signing_alg_values_supported: string[];
38
43
  scopes_supported: string[];
44
+ claims_supported: string[];
45
+ response_types_supported: string[];
39
46
  issuer: string;
40
47
  authorization_endpoint: string;
41
48
  token_endpoint: string;
42
49
  registration_endpoint?: string;
43
50
  introspection_endpoint?: string;
44
51
  revocation_endpoint?: string;
45
- response_types_supported: string[];
46
52
  response_modes_supported: string[];
47
53
  grant_types_supported: string[];
48
54
  token_endpoint_auth_methods_supported: string[];
@@ -50,6 +56,7 @@ export default class MetadataController {
50
56
  revocation_endpoint_auth_methods_supported?: string[];
51
57
  code_challenge_methods_supported: string[];
52
58
  authorization_response_iss_parameter_supported: boolean;
59
+ error?: undefined;
53
60
  }>;
54
61
  /**
55
62
  * OAuth 2.0 Protected Resource Metadata (RFC 9728).
@@ -2,15 +2,14 @@ import type { HttpContext } from '@adonisjs/core/http';
2
2
  /**
3
3
  * Handles the OAuth 2.0 Token Endpoint (RFC 6749 §3.2).
4
4
  *
5
- * Dispatches to the appropriate grant handler based on the
6
- * `grant_type` parameter. Sets `Cache-Control: no-store` and
7
- * `Pragma: no-cache` headers on all token responses as required
8
- * by the spec.
5
+ * Authenticates the client, extracts grant-specific params,
6
+ * and dispatches to the appropriate action. Sets required
7
+ * cache headers on all token responses.
9
8
  *
10
9
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-3.2
11
- * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
12
10
  */
13
11
  export default class TokenController {
12
+ #private;
14
13
  static validator: import("@vinejs/vine").VineValidator<import("@vinejs/vine").VineObject<{
15
14
  grant_type: import("@vinejs/vine").VineString;
16
15
  }, {
@@ -20,5 +19,9 @@ export default class TokenController {
20
19
  }, {
21
20
  grant_type: string;
22
21
  }>, Record<string, any> | undefined>;
22
+ /**
23
+ * Validate the grant type, authenticate the client,
24
+ * and dispatch to the appropriate grant action.
25
+ */
23
26
  handle(ctx: HttpContext): Promise<any>;
24
27
  }
@@ -0,0 +1,14 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ /**
3
+ * OpenID Connect UserInfo endpoint (OIDC Core §5.3).
4
+ *
5
+ * Returns claims about the authenticated user based on the
6
+ * access token's scopes. Supports both GET and POST.
7
+ *
8
+ * @see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
9
+ */
10
+ export default class UserinfoController {
11
+ handle(ctx: HttpContext): Promise<{
12
+ sub: string | null;
13
+ }>;
14
+ }
@@ -1,6 +1,6 @@
1
- import "../../decorate-BKZEjPRg.js";
2
- import "../../oauth_access_token-bsoM5KeU.js";
3
- import "../../oauth_client-BIoY5jBR.js";
4
- import "../../token_service-fhoA4slP.js";
5
- import { i as OAuthGuard, n as oauthUserProvider, r as OAuthLucidUserProvider, t as oauthGuard } from "../../main-B3M6ihoS.js";
1
+ import "../../chunk-DF48asd8.js";
2
+ import "../../oauth_client-BSanvSql.js";
3
+ import "../../oauth_access_token-Cz_5gNBx.js";
4
+ import "../../token_service-DwnfAR9F.js";
5
+ import { i as OAuthGuard, n as oauthUserProvider, r as OAuthLucidUserProvider, t as oauthGuard } from "../../main-DGBJhq3E.js";
6
6
  export { OAuthGuard, OAuthLucidUserProvider, oauthGuard, oauthUserProvider };
@@ -1,4 +1,13 @@
1
- import { n as E_INSUFFICIENT_SCOPE } from "../../oauth_error-CnJ3L8tf.js";
1
+ import "../../chunk-DF48asd8.js";
2
+ import { n as E_INSUFFICIENT_SCOPE } from "../../oauth_error-C7UhDb2q.js";
3
+ //#region src/middleware/any_scope_middleware.ts
4
+ /**
5
+ * Any-scope middleware requires ANY of the listed scopes on the
6
+ * authenticated OAuth token. Throws 403 if none match.
7
+ *
8
+ * @example
9
+ * router.get('/data', [DataController]).use(middleware.anyScope({ scopes: ['read', 'read-all'] }))
10
+ */
2
11
  var AnyScopeMiddleware = class {
3
12
  async handle(ctx, next, options) {
4
13
  const guard = ctx.auth.use("oauth");
@@ -15,4 +24,5 @@ var AnyScopeMiddleware = class {
15
24
  await guard.authenticate();
16
25
  }
17
26
  };
27
+ //#endregion
18
28
  export { AnyScopeMiddleware as default };
@@ -1,4 +1,13 @@
1
- import { n as E_INSUFFICIENT_SCOPE } from "../../oauth_error-CnJ3L8tf.js";
1
+ import "../../chunk-DF48asd8.js";
2
+ import { n as E_INSUFFICIENT_SCOPE } from "../../oauth_error-C7UhDb2q.js";
3
+ //#region src/middleware/scope_middleware.ts
4
+ /**
5
+ * Scope middleware requires ALL listed scopes on the authenticated
6
+ * OAuth token. Throws 403 if any scope is missing.
7
+ *
8
+ * @example
9
+ * router.get('/admin', [AdminController]).use(middleware.scopes({ scopes: ['admin', 'manage'] }))
10
+ */
2
11
  var ScopeMiddleware = class {
3
12
  async handle(ctx, next, options) {
4
13
  const guard = ctx.auth.use("oauth");
@@ -15,4 +24,5 @@ var ScopeMiddleware = class {
15
24
  await guard.authenticate();
16
25
  }
17
26
  };
27
+ //#endregion
18
28
  export { ScopeMiddleware as default };
@@ -24,6 +24,7 @@ export declare class OAuthAuthorizationCode extends BaseModel {
24
24
  redirectUri: string;
25
25
  codeChallenge: string | null;
26
26
  codeChallengeMethod: string | null;
27
+ nonce: string | null;
27
28
  expiresAt: DateTime;
28
29
  createdAt: DateTime;
29
30
  updatedAt: DateTime;
@@ -24,6 +24,7 @@ export declare class OAuthPendingAuthorizationRequest extends BaseModel {
24
24
  state: string | null;
25
25
  codeChallenge: string | null;
26
26
  codeChallengeMethod: string | null;
27
+ nonce: string | null;
27
28
  expiresAt: DateTime;
28
29
  createdAt: DateTime;
29
30
  }
@@ -171,8 +171,8 @@ export declare const E_INVALID_TOKEN: {
171
171
  code?: string;
172
172
  status?: number;
173
173
  }): {
174
- get oauthCode(): string;
175
174
  handle(error: /*elided*/ any, ctx: HttpContext): void;
175
+ get oauthCode(): string;
176
176
  name: string;
177
177
  help?: string;
178
178
  code?: string;
@@ -26,4 +26,6 @@ export declare function registerOAuthRoutes(router: Router): void;
26
26
  * - `GET /.well-known/openid-configuration` — OpenID Connect discovery
27
27
  * - `GET /.well-known/oauth-protected-resource` — Protected resource metadata (RFC 9728)
28
28
  */
29
- export declare function registerWellKnownRoutes(router: Router): void;
29
+ export declare function registerWellKnownRoutes(router: Router, options?: {
30
+ jwksPath?: string;
31
+ }): void;
@@ -0,0 +1,30 @@
1
+ import type { SesameManager } from '../sesame_manager.ts';
2
+ /**
3
+ * Builds and signs OIDC `id_token` JWTs.
4
+ */
5
+ export declare class IdTokenService {
6
+ #private;
7
+ constructor(manager: SesameManager);
8
+ /**
9
+ * Compute `at_hash` — left half of SHA-256 hash of the access token, base64url-encoded.
10
+ * @see OIDC Core §3.1.3.6
11
+ */
12
+ static computeAtHash(accessToken: string): string;
13
+ /**
14
+ * Filter out reserved claims that the server owns.
15
+ */
16
+ static filterReservedClaims(claims: Record<string, unknown>): Record<string, unknown>;
17
+ /**
18
+ * Resolve user OIDC claims by calling `getOidcClaims` if present,
19
+ * then filtering out reserved protocol claims.
20
+ */
21
+ static resolveUserClaims(user: unknown, scopes: string[]): Promise<Record<string, unknown>>;
22
+ sign(options: {
23
+ sub: string;
24
+ clientId: string;
25
+ scopes: string[];
26
+ accessToken: string;
27
+ user: unknown;
28
+ nonce?: string;
29
+ }): Promise<string>;
30
+ }
@@ -0,0 +1,20 @@
1
+ import { type JWK } from 'jose';
2
+ /**
3
+ * Manages the RSA key pair used to sign ID tokens.
4
+ * Accepts a JWK from config, caches the imported private key
5
+ * and public JWK for JWKS export.
6
+ */
7
+ export declare class KeyService {
8
+ #private;
9
+ constructor(jwk: JWK);
10
+ /**
11
+ * Compute a `kid` from public key components (SHA-256, base64url).
12
+ * Same approach as node-oidc-provider.
13
+ */
14
+ static computeKid(jwk: JWK): string;
15
+ sign(payload: Record<string, unknown>): Promise<string>;
16
+ getPublicJwks(): {
17
+ keys: JWK[];
18
+ };
19
+ get kid(): string;
20
+ }
@@ -1,5 +1,7 @@
1
1
  import type { Router } from '@adonisjs/core/http';
2
- import { type ResolvedSesameConfig, type Scope } from './types.ts';
2
+ import { type CreateClientOptions, type CreateClientResult, type ResolvedSesameConfig, type Scope, type UpdateClientOptions } from './types.ts';
3
+ import { KeyService } from './services/key_service.ts';
4
+ import { OAuthClient } from './models/oauth_client.ts';
3
5
  export interface PurgeResult {
4
6
  accessTokens: number;
5
7
  refreshTokens: number;
@@ -16,12 +18,23 @@ export declare class SesameManager {
16
18
  #private;
17
19
  constructor(config: ResolvedSesameConfig, router: Router);
18
20
  get config(): ResolvedSesameConfig;
21
+ get keyService(): KeyService;
22
+ get isOidcEnabled(): boolean;
23
+ /**
24
+ * Load a user by ID using the configured user provider.
25
+ * Returns the original user model instance, or null if not found.
26
+ */
27
+ findUserById(userId: string): Promise<unknown | null>;
19
28
  /**
20
29
  * Check if a scope is registered in the server configuration.
21
30
  *
22
31
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3
23
32
  */
24
33
  hasScope(scope: Scope): boolean;
34
+ /**
35
+ * Check if the requested scope list uses any OIDC-specific scopes.
36
+ */
37
+ usesOidcScopes(scopes: Scope[]): boolean;
25
38
  /**
26
39
  * Return the list of scopes that are not registered in the
27
40
  * server configuration. When no scopes are configured, all
@@ -58,6 +71,36 @@ export declare class SesameManager {
58
71
  expiredOnly?: boolean;
59
72
  retentionHours?: number;
60
73
  }): Promise<PurgeResult>;
74
+ /**
75
+ * Create a new OAuth client programmatically.
76
+ * Returns the client and the raw secret (only available at creation time).
77
+ */
78
+ createClient(options: CreateClientOptions): Promise<CreateClientResult>;
79
+ /**
80
+ * Find a client by its public client_id.
81
+ */
82
+ findClient(clientId: string): Promise<OAuthClient | null>;
83
+ /**
84
+ * List all clients, optionally filtered by userId.
85
+ */
86
+ listClients(options?: {
87
+ userId?: string;
88
+ }): Promise<OAuthClient[]>;
89
+ /**
90
+ * Update an existing client by its public client_id.
91
+ * Returns the updated client, or null if not found.
92
+ */
93
+ updateClient(clientId: string, options: UpdateClientOptions): Promise<OAuthClient | null>;
94
+ /**
95
+ * Delete a client and all its associated tokens, codes, and consents.
96
+ * Returns true if the client was found and deleted.
97
+ */
98
+ deleteClient(clientId: string): Promise<boolean>;
99
+ /**
100
+ * Rotate the secret of a confidential client.
101
+ * Returns the new raw secret, or null if the client is public or not found.
102
+ */
103
+ rotateClientSecret(clientId: string): Promise<string | null>;
61
104
  /**
62
105
  * Register OAuth 2.1 endpoint routes (token, authorize, consent, etc.).
63
106
  *
@@ -77,12 +120,20 @@ export declare class SesameManager {
77
120
  */
78
121
  registerRoutes(): void;
79
122
  /**
80
- * Register well-known discovery routes at the root level.
123
+ * Register discovery routes at the root level.
81
124
  *
82
125
  * Must be called outside any prefix group so endpoints
83
126
  * remain at `/.well-known/...`.
84
127
  */
85
- registerWellKnownRoutes(): void;
128
+ registerDiscoveryRoutes(options?: {
129
+ jwksPath?: string;
130
+ }): void;
131
+ /**
132
+ * @deprecated Use `registerDiscoveryRoutes()` instead.
133
+ */
134
+ registerWellKnownRoutes(options?: {
135
+ jwksPath?: string;
136
+ }): void;
86
137
  /**
87
138
  * Register a `/.well-known/oauth-protected-resource` endpoint
88
139
  * for a specific resource path (RFC 9728). Useful for MCP