@boopkit/cap-oauth-server 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.
Files changed (124) hide show
  1. package/capability.json +120 -0
  2. package/dist/authorization-code-service.d.ts +105 -0
  3. package/dist/authorization-code-service.d.ts.map +1 -0
  4. package/dist/authorization-code-service.js +142 -0
  5. package/dist/authorization-code-service.js.map +1 -0
  6. package/dist/bearer.d.ts +146 -0
  7. package/dist/bearer.d.ts.map +1 -0
  8. package/dist/bearer.js +150 -0
  9. package/dist/bearer.js.map +1 -0
  10. package/dist/body-field.d.ts +24 -0
  11. package/dist/body-field.d.ts.map +1 -0
  12. package/dist/body-field.js +43 -0
  13. package/dist/body-field.js.map +1 -0
  14. package/dist/client-registry-service.d.ts +120 -0
  15. package/dist/client-registry-service.d.ts.map +1 -0
  16. package/dist/client-registry-service.js +450 -0
  17. package/dist/client-registry-service.js.map +1 -0
  18. package/dist/config.d.ts +82 -0
  19. package/dist/config.d.ts.map +1 -0
  20. package/dist/config.js +157 -0
  21. package/dist/config.js.map +1 -0
  22. package/dist/connections-controller.d.ts +106 -0
  23. package/dist/connections-controller.d.ts.map +1 -0
  24. package/dist/connections-controller.js +161 -0
  25. package/dist/connections-controller.js.map +1 -0
  26. package/dist/consent-controller.d.ts +197 -0
  27. package/dist/consent-controller.d.ts.map +1 -0
  28. package/dist/consent-controller.js +532 -0
  29. package/dist/consent-controller.js.map +1 -0
  30. package/dist/discovery-controller.d.ts +16 -0
  31. package/dist/discovery-controller.d.ts.map +1 -0
  32. package/dist/discovery-controller.js +52 -0
  33. package/dist/discovery-controller.js.map +1 -0
  34. package/dist/discovery.d.ts +95 -0
  35. package/dist/discovery.d.ts.map +1 -0
  36. package/dist/discovery.js +101 -0
  37. package/dist/discovery.js.map +1 -0
  38. package/dist/errors.d.ts +26 -0
  39. package/dist/errors.d.ts.map +1 -0
  40. package/dist/errors.js +41 -0
  41. package/dist/errors.js.map +1 -0
  42. package/dist/express.d.ts +66 -0
  43. package/dist/express.d.ts.map +1 -0
  44. package/dist/express.js +3 -0
  45. package/dist/express.js.map +1 -0
  46. package/dist/grant-service.d.ts +102 -0
  47. package/dist/grant-service.d.ts.map +1 -0
  48. package/dist/grant-service.js +137 -0
  49. package/dist/grant-service.js.map +1 -0
  50. package/dist/index.d.ts +67 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +148 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/metadata-document.d.ts +60 -0
  55. package/dist/metadata-document.d.ts.map +1 -0
  56. package/dist/metadata-document.js +148 -0
  57. package/dist/metadata-document.js.map +1 -0
  58. package/dist/oauth-error.d.ts +45 -0
  59. package/dist/oauth-error.d.ts.map +1 -0
  60. package/dist/oauth-error.js +51 -0
  61. package/dist/oauth-error.js.map +1 -0
  62. package/dist/pkce.d.ts +29 -0
  63. package/dist/pkce.d.ts.map +1 -0
  64. package/dist/pkce.js +65 -0
  65. package/dist/pkce.js.map +1 -0
  66. package/dist/property-array.d.ts +60 -0
  67. package/dist/property-array.d.ts.map +1 -0
  68. package/dist/property-array.js +31 -0
  69. package/dist/property-array.js.map +1 -0
  70. package/dist/public-id.d.ts +35 -0
  71. package/dist/public-id.d.ts.map +1 -0
  72. package/dist/public-id.js +76 -0
  73. package/dist/public-id.js.map +1 -0
  74. package/dist/rate-limit.d.ts +56 -0
  75. package/dist/rate-limit.d.ts.map +1 -0
  76. package/dist/rate-limit.js +55 -0
  77. package/dist/rate-limit.js.map +1 -0
  78. package/dist/redirect-uri.d.ts +89 -0
  79. package/dist/redirect-uri.d.ts.map +1 -0
  80. package/dist/redirect-uri.js +249 -0
  81. package/dist/redirect-uri.js.map +1 -0
  82. package/dist/registration-controller.d.ts +62 -0
  83. package/dist/registration-controller.d.ts.map +1 -0
  84. package/dist/registration-controller.js +79 -0
  85. package/dist/registration-controller.js.map +1 -0
  86. package/dist/request-client.d.ts +19 -0
  87. package/dist/request-client.d.ts.map +1 -0
  88. package/dist/request-client.js +32 -0
  89. package/dist/request-client.js.map +1 -0
  90. package/dist/revocation-controller.d.ts +28 -0
  91. package/dist/revocation-controller.d.ts.map +1 -0
  92. package/dist/revocation-controller.js +176 -0
  93. package/dist/revocation-controller.js.map +1 -0
  94. package/dist/revocation-service.d.ts +113 -0
  95. package/dist/revocation-service.d.ts.map +1 -0
  96. package/dist/revocation-service.js +121 -0
  97. package/dist/revocation-service.js.map +1 -0
  98. package/dist/token-controller.d.ts +79 -0
  99. package/dist/token-controller.d.ts.map +1 -0
  100. package/dist/token-controller.js +207 -0
  101. package/dist/token-controller.js.map +1 -0
  102. package/dist/token-service.d.ts +175 -0
  103. package/dist/token-service.d.ts.map +1 -0
  104. package/dist/token-service.js +251 -0
  105. package/dist/token-service.js.map +1 -0
  106. package/dist/types.d.ts +130 -0
  107. package/dist/types.d.ts.map +1 -0
  108. package/dist/types.js +13 -0
  109. package/dist/types.js.map +1 -0
  110. package/dist/user-store.d.ts +110 -0
  111. package/dist/user-store.d.ts.map +1 -0
  112. package/dist/user-store.js +40 -0
  113. package/dist/user-store.js.map +1 -0
  114. package/package.json +37 -0
  115. package/scaffold/prisma/schema/oauth-clients.prisma +80 -0
  116. package/scaffold/reference/oauth-server.ref.md +478 -0
  117. package/scaffold/src/middleware/oauth-server.ts +227 -0
  118. package/scaffold/src/scripts/seed-oauth-clients.ts +72 -0
  119. package/scaffold/src/services/oauth-server.service.ts +101 -0
  120. package/scaffold/styles/oauth-server.css +345 -0
  121. package/scaffold/views/oauth-connected-clients.hbs +98 -0
  122. package/scaffold/views/oauth-consent-error.hbs +22 -0
  123. package/scaffold/views/oauth-consent.hbs +138 -0
  124. package/scaffold/views/oauth-disconnect-confirm.hbs +57 -0
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @boopkit/cap-oauth-server — an OAuth 2.1 authorization server and resource
3
+ * server for a boop application.
4
+ *
5
+ * Slice 1 shipped the parts every later slice speaks in terms of: the client
6
+ * registry that knows who is asking, and the discovery documents that tell a
7
+ * client what we are. Slice 2 adds the grant itself — the consent screen, the
8
+ * authorization code, `POST /oauth/token`, and enough of a resource-server
9
+ * guard to make an authenticated call real. Slice 3 makes that guard something
10
+ * a route can defend itself with — `requireOAuth(...scopes)` and its RFC 6750
11
+ * refusals — adds soft revocation, and gives a person the two screens where
12
+ * they see and disconnect what they have connected.
13
+ *
14
+ * **The identity boundary.** Nothing in this package reaches a user, an
15
+ * account, or an identity except through `@boopkit/cap-users`' public surface.
16
+ * The one table it owns is `oauth_clients`, which describes software rather
17
+ * than people. `tests/packages/cap-oauth-server-import-audit.test.ts` enforces
18
+ * that mechanically.
19
+ */
20
+ import './express.js';
21
+ export { classifyRedirectUri, matchRedirectUri, matchesAnyRedirectUri, isLoopbackHost, } from './redirect-uri.js';
22
+ export type { RedirectUriClassification, RedirectUriShape } from './redirect-uri.js';
23
+ export { generateClientPublicId, isValidClientPublicId, CLIENT_PUBLIC_ID_ALPHABET, CLIENT_PUBLIC_ID_LENGTH, } from './public-id.js';
24
+ export { ClientRegistryError, isClientRegistryError } from './errors.js';
25
+ export type { ClientRegistryErrorCode } from './errors.js';
26
+ export { createClientRegistryService, validateRedirectUris, DEFAULT_GRANT_TYPES, DEFAULT_RESPONSE_TYPES, DEFAULT_METADATA_MAX_AGE_MS, DEFAULT_ABANDONED_CLIENT_TTL_MS, DEFAULT_MAX_REGISTERED_CLIENTS, } from './client-registry-service.js';
27
+ export type { ClientRegistryService, ClientRegistryServiceOptions, PruneOptions, } from './client-registry-service.js';
28
+ export { fetchMetadataDocument, isValidMetadataUri, DEFAULT_METADATA_TIMEOUT_MS, DEFAULT_METADATA_MAX_BYTES, DEFAULT_METADATA_MAX_REDIRECTS, } from './metadata-document.js';
29
+ export type { FetchLike, FetchLikeResponse, MetadataFetchOptions, } from './metadata-document.js';
30
+ export { buildAuthorizationServerMetadata, buildProtectedResourceMetadata, CODE_CHALLENGE_METHODS_SUPPORTED, DEVICE_CODE_GRANT_TYPE, DEFAULT_SCOPES_SUPPORTED, DISCOVERY_MAX_AGE_SECONDS, } from './discovery.js';
31
+ export type { DiscoveryConfig, AuthorizationServerMetadata, ProtectedResourceMetadata, } from './discovery.js';
32
+ export { readServerConfig, clampTtlSeconds, OauthServerConfigError, DEFAULT_ACCESS_TOKEN_TTL_SECONDS, DEFAULT_REFRESH_TOKEN_TTL_SECONDS, ACCESS_TOKEN_TTL_BOUNDS, REFRESH_TOKEN_TTL_BOUNDS, } from './config.js';
33
+ export type { ServerConfig, ReadConfigOptions } from './config.js';
34
+ export { createDiscoveryHandlers, createDiscoveryRouter } from './discovery-controller.js';
35
+ export type { DiscoveryHandlers } from './discovery-controller.js';
36
+ export { createRegistrationHandlers, createRegistrationRouter, toRegistrationResponse, } from './registration-controller.js';
37
+ export type { RegistrationHandlerDeps, RegistrationRouterOptions, } from './registration-controller.js';
38
+ export { createRegistrationRateLimiter, DEFAULT_REGISTRATION_RATE_LIMIT, DEFAULT_REGISTRATION_RATE_WINDOW_MS, } from './rate-limit.js';
39
+ export type { RateLimiterOptions, RegistrationRateLimiter } from './rate-limit.js';
40
+ export { CLIENT_MODES } from './types.js';
41
+ export type { ClientMode, ClientStatus, OauthClient, OauthClientDelegate, ClientMetadataInput, ClientIdMetadataDocument, StaticClientInput, } from './types.js';
42
+ export { createTokenService, buildIdentityKey, AUTHORIZATION_CODE_TTL_SECONDS, OAUTH_CODE_DOMAIN, OAUTH_ACCESS_DOMAIN, OAUTH_REFRESH_DOMAIN, } from './token-service.js';
43
+ export type { TokenService, TokenServiceOptions, OAuthTokenDomain, MintedToken, ResolvedToken, } from './token-service.js';
44
+ export { createGrantService, isGrantActive, OAUTH_GRANTS_PROPERTY, OAUTH_GRANTS_INFO_SCHEMA, } from './grant-service.js';
45
+ export type { GrantService, GrantServiceOptions, GrantsSnapshot, OAuthGrantRecord, ApproveGrantInput, } from './grant-service.js';
46
+ export { createAuthorizationCodeService, OAUTH_CODES_PROPERTY, OAUTH_CODES_INFO_SCHEMA, } from './authorization-code-service.js';
47
+ export type { AuthorizationCodeService, AuthorizationCodeServiceOptions, AuthorizationCodeRecord, IssueCodeInput, RedeemCodeInput, RedeemFailure, RedeemResult, } from './authorization-code-service.js';
48
+ export { CODE_CHALLENGE_METHOD, deriveCodeChallenge, isValidCodeChallenge, isValidCodeVerifier, verifyCodeChallenge, } from './pkce.js';
49
+ export { OAuthError, isOAuthError } from './oauth-error.js';
50
+ export type { OAuthErrorCode } from './oauth-error.js';
51
+ export { isStaleWriteError } from './user-store.js';
52
+ export type { IdentityStore, PropertyStore, PropertyWriteOptions, StoredIdentity, StoredProperty, } from './user-store.js';
53
+ export { readArray, writeArray } from './property-array.js';
54
+ export type { ArraySnapshot } from './property-array.js';
55
+ export { createConsentHandlers, createConsentRouter, monogramFor, provenanceFor, safeLogoUri, scopeDescriptionsFrom, toScopeViews, warnUndescribedScopes, SCOPE_DESCRIPTIONS_LOCAL, } from './consent-controller.js';
56
+ export type { AuthorizationRequest, ConsentCredentials, ConsentHandlers, ConsentHandlerDeps, ConsentRegister, ConsentRegistration, ConsentRouterOptions, ConsentScopeView, ConsentSession, ConsentSignIn, ConsentVariant, ScopeDescriptions, } from './consent-controller.js';
57
+ export { createTokenHandlers, createTokenRouter, parseScopes, OFFLINE_ACCESS_SCOPE, } from './token-controller.js';
58
+ export type { TokenHandlerDeps, TokenRouterOptions, TokenResponse, } from './token-controller.js';
59
+ export { createOAuthBearerMiddleware, createOAuthResourceServer, createOAuthTokenResolver, missingScopes, requireOAuth, DEFAULT_BEARER_CHALLENGE, } from './bearer.js';
60
+ export type { OAuthBearerOptions, OAuthResourceServer, ResolvedOAuthPrincipal, } from './bearer.js';
61
+ export { createRevocationService, REVOKED_BY_CLIENT, REVOKED_BY_USER, REVOKED_CLIENT_WIDE, } from './revocation-service.js';
62
+ export type { RevocationService, RevocationServiceOptions, RevokedGrant, } from './revocation-service.js';
63
+ export { createRevocationHandlers, createRevocationRouter, } from './revocation-controller.js';
64
+ export type { RevocationHandlerDeps, RevocationHandlers, RevocationRouterOptions, } from './revocation-controller.js';
65
+ export { createConnectionsHandlers, createConnectionsRouter, ACCOUNT_COVERAGE_STATEMENT, } from './connections-controller.js';
66
+ export type { ConnectionView, ConnectionsHandlers, ConnectionsHandlerDeps, ConnectionsRouterOptions, } from './connections-controller.js';
67
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ /**
3
+ * @boopkit/cap-oauth-server — an OAuth 2.1 authorization server and resource
4
+ * server for a boop application.
5
+ *
6
+ * Slice 1 shipped the parts every later slice speaks in terms of: the client
7
+ * registry that knows who is asking, and the discovery documents that tell a
8
+ * client what we are. Slice 2 adds the grant itself — the consent screen, the
9
+ * authorization code, `POST /oauth/token`, and enough of a resource-server
10
+ * guard to make an authenticated call real. Slice 3 makes that guard something
11
+ * a route can defend itself with — `requireOAuth(...scopes)` and its RFC 6750
12
+ * refusals — adds soft revocation, and gives a person the two screens where
13
+ * they see and disconnect what they have connected.
14
+ *
15
+ * **The identity boundary.** Nothing in this package reaches a user, an
16
+ * account, or an identity except through `@boopkit/cap-users`' public surface.
17
+ * The one table it owns is `oauth_clients`, which describes software rather
18
+ * than people. `tests/packages/cap-oauth-server-import-audit.test.ts` enforces
19
+ * that mechanically.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.OAUTH_REFRESH_DOMAIN = exports.OAUTH_ACCESS_DOMAIN = exports.OAUTH_CODE_DOMAIN = exports.AUTHORIZATION_CODE_TTL_SECONDS = exports.buildIdentityKey = exports.createTokenService = exports.CLIENT_MODES = exports.DEFAULT_REGISTRATION_RATE_WINDOW_MS = exports.DEFAULT_REGISTRATION_RATE_LIMIT = exports.createRegistrationRateLimiter = exports.toRegistrationResponse = exports.createRegistrationRouter = exports.createRegistrationHandlers = exports.createDiscoveryRouter = exports.createDiscoveryHandlers = exports.REFRESH_TOKEN_TTL_BOUNDS = exports.ACCESS_TOKEN_TTL_BOUNDS = exports.DEFAULT_REFRESH_TOKEN_TTL_SECONDS = exports.DEFAULT_ACCESS_TOKEN_TTL_SECONDS = exports.OauthServerConfigError = exports.clampTtlSeconds = exports.readServerConfig = exports.DISCOVERY_MAX_AGE_SECONDS = exports.DEFAULT_SCOPES_SUPPORTED = exports.DEVICE_CODE_GRANT_TYPE = exports.CODE_CHALLENGE_METHODS_SUPPORTED = exports.buildProtectedResourceMetadata = exports.buildAuthorizationServerMetadata = exports.DEFAULT_METADATA_MAX_REDIRECTS = exports.DEFAULT_METADATA_MAX_BYTES = exports.DEFAULT_METADATA_TIMEOUT_MS = exports.isValidMetadataUri = exports.fetchMetadataDocument = exports.DEFAULT_MAX_REGISTERED_CLIENTS = exports.DEFAULT_ABANDONED_CLIENT_TTL_MS = exports.DEFAULT_METADATA_MAX_AGE_MS = exports.DEFAULT_RESPONSE_TYPES = exports.DEFAULT_GRANT_TYPES = exports.validateRedirectUris = exports.createClientRegistryService = exports.isClientRegistryError = exports.ClientRegistryError = exports.CLIENT_PUBLIC_ID_LENGTH = exports.CLIENT_PUBLIC_ID_ALPHABET = exports.isValidClientPublicId = exports.generateClientPublicId = exports.isLoopbackHost = exports.matchesAnyRedirectUri = exports.matchRedirectUri = exports.classifyRedirectUri = void 0;
23
+ exports.ACCOUNT_COVERAGE_STATEMENT = exports.createConnectionsRouter = exports.createConnectionsHandlers = exports.createRevocationRouter = exports.createRevocationHandlers = exports.REVOKED_CLIENT_WIDE = exports.REVOKED_BY_USER = exports.REVOKED_BY_CLIENT = exports.createRevocationService = exports.DEFAULT_BEARER_CHALLENGE = exports.requireOAuth = exports.missingScopes = exports.createOAuthTokenResolver = exports.createOAuthResourceServer = exports.createOAuthBearerMiddleware = exports.OFFLINE_ACCESS_SCOPE = exports.parseScopes = exports.createTokenRouter = exports.createTokenHandlers = exports.SCOPE_DESCRIPTIONS_LOCAL = exports.warnUndescribedScopes = exports.toScopeViews = exports.scopeDescriptionsFrom = exports.safeLogoUri = exports.provenanceFor = exports.monogramFor = exports.createConsentRouter = exports.createConsentHandlers = exports.writeArray = exports.readArray = exports.isStaleWriteError = exports.isOAuthError = exports.OAuthError = exports.verifyCodeChallenge = exports.isValidCodeVerifier = exports.isValidCodeChallenge = exports.deriveCodeChallenge = exports.CODE_CHALLENGE_METHOD = exports.OAUTH_CODES_INFO_SCHEMA = exports.OAUTH_CODES_PROPERTY = exports.createAuthorizationCodeService = exports.OAUTH_GRANTS_INFO_SCHEMA = exports.OAUTH_GRANTS_PROPERTY = exports.isGrantActive = exports.createGrantService = void 0;
24
+ // Side-effect import: the Express request augmentation this capability's
25
+ // middleware writes (`req.oauthGrant`) and its consent controller reads
26
+ // (`req.user`). Importing the package is what gives an application those
27
+ // declarations. See `src/express.ts` for why they are re-declarations.
28
+ require("./express.js");
29
+ var redirect_uri_js_1 = require("./redirect-uri.js");
30
+ Object.defineProperty(exports, "classifyRedirectUri", { enumerable: true, get: function () { return redirect_uri_js_1.classifyRedirectUri; } });
31
+ Object.defineProperty(exports, "matchRedirectUri", { enumerable: true, get: function () { return redirect_uri_js_1.matchRedirectUri; } });
32
+ Object.defineProperty(exports, "matchesAnyRedirectUri", { enumerable: true, get: function () { return redirect_uri_js_1.matchesAnyRedirectUri; } });
33
+ Object.defineProperty(exports, "isLoopbackHost", { enumerable: true, get: function () { return redirect_uri_js_1.isLoopbackHost; } });
34
+ var public_id_js_1 = require("./public-id.js");
35
+ Object.defineProperty(exports, "generateClientPublicId", { enumerable: true, get: function () { return public_id_js_1.generateClientPublicId; } });
36
+ Object.defineProperty(exports, "isValidClientPublicId", { enumerable: true, get: function () { return public_id_js_1.isValidClientPublicId; } });
37
+ Object.defineProperty(exports, "CLIENT_PUBLIC_ID_ALPHABET", { enumerable: true, get: function () { return public_id_js_1.CLIENT_PUBLIC_ID_ALPHABET; } });
38
+ Object.defineProperty(exports, "CLIENT_PUBLIC_ID_LENGTH", { enumerable: true, get: function () { return public_id_js_1.CLIENT_PUBLIC_ID_LENGTH; } });
39
+ var errors_js_1 = require("./errors.js");
40
+ Object.defineProperty(exports, "ClientRegistryError", { enumerable: true, get: function () { return errors_js_1.ClientRegistryError; } });
41
+ Object.defineProperty(exports, "isClientRegistryError", { enumerable: true, get: function () { return errors_js_1.isClientRegistryError; } });
42
+ var client_registry_service_js_1 = require("./client-registry-service.js");
43
+ Object.defineProperty(exports, "createClientRegistryService", { enumerable: true, get: function () { return client_registry_service_js_1.createClientRegistryService; } });
44
+ Object.defineProperty(exports, "validateRedirectUris", { enumerable: true, get: function () { return client_registry_service_js_1.validateRedirectUris; } });
45
+ Object.defineProperty(exports, "DEFAULT_GRANT_TYPES", { enumerable: true, get: function () { return client_registry_service_js_1.DEFAULT_GRANT_TYPES; } });
46
+ Object.defineProperty(exports, "DEFAULT_RESPONSE_TYPES", { enumerable: true, get: function () { return client_registry_service_js_1.DEFAULT_RESPONSE_TYPES; } });
47
+ Object.defineProperty(exports, "DEFAULT_METADATA_MAX_AGE_MS", { enumerable: true, get: function () { return client_registry_service_js_1.DEFAULT_METADATA_MAX_AGE_MS; } });
48
+ Object.defineProperty(exports, "DEFAULT_ABANDONED_CLIENT_TTL_MS", { enumerable: true, get: function () { return client_registry_service_js_1.DEFAULT_ABANDONED_CLIENT_TTL_MS; } });
49
+ Object.defineProperty(exports, "DEFAULT_MAX_REGISTERED_CLIENTS", { enumerable: true, get: function () { return client_registry_service_js_1.DEFAULT_MAX_REGISTERED_CLIENTS; } });
50
+ var metadata_document_js_1 = require("./metadata-document.js");
51
+ Object.defineProperty(exports, "fetchMetadataDocument", { enumerable: true, get: function () { return metadata_document_js_1.fetchMetadataDocument; } });
52
+ Object.defineProperty(exports, "isValidMetadataUri", { enumerable: true, get: function () { return metadata_document_js_1.isValidMetadataUri; } });
53
+ Object.defineProperty(exports, "DEFAULT_METADATA_TIMEOUT_MS", { enumerable: true, get: function () { return metadata_document_js_1.DEFAULT_METADATA_TIMEOUT_MS; } });
54
+ Object.defineProperty(exports, "DEFAULT_METADATA_MAX_BYTES", { enumerable: true, get: function () { return metadata_document_js_1.DEFAULT_METADATA_MAX_BYTES; } });
55
+ Object.defineProperty(exports, "DEFAULT_METADATA_MAX_REDIRECTS", { enumerable: true, get: function () { return metadata_document_js_1.DEFAULT_METADATA_MAX_REDIRECTS; } });
56
+ var discovery_js_1 = require("./discovery.js");
57
+ Object.defineProperty(exports, "buildAuthorizationServerMetadata", { enumerable: true, get: function () { return discovery_js_1.buildAuthorizationServerMetadata; } });
58
+ Object.defineProperty(exports, "buildProtectedResourceMetadata", { enumerable: true, get: function () { return discovery_js_1.buildProtectedResourceMetadata; } });
59
+ Object.defineProperty(exports, "CODE_CHALLENGE_METHODS_SUPPORTED", { enumerable: true, get: function () { return discovery_js_1.CODE_CHALLENGE_METHODS_SUPPORTED; } });
60
+ Object.defineProperty(exports, "DEVICE_CODE_GRANT_TYPE", { enumerable: true, get: function () { return discovery_js_1.DEVICE_CODE_GRANT_TYPE; } });
61
+ Object.defineProperty(exports, "DEFAULT_SCOPES_SUPPORTED", { enumerable: true, get: function () { return discovery_js_1.DEFAULT_SCOPES_SUPPORTED; } });
62
+ Object.defineProperty(exports, "DISCOVERY_MAX_AGE_SECONDS", { enumerable: true, get: function () { return discovery_js_1.DISCOVERY_MAX_AGE_SECONDS; } });
63
+ var config_js_1 = require("./config.js");
64
+ Object.defineProperty(exports, "readServerConfig", { enumerable: true, get: function () { return config_js_1.readServerConfig; } });
65
+ Object.defineProperty(exports, "clampTtlSeconds", { enumerable: true, get: function () { return config_js_1.clampTtlSeconds; } });
66
+ Object.defineProperty(exports, "OauthServerConfigError", { enumerable: true, get: function () { return config_js_1.OauthServerConfigError; } });
67
+ Object.defineProperty(exports, "DEFAULT_ACCESS_TOKEN_TTL_SECONDS", { enumerable: true, get: function () { return config_js_1.DEFAULT_ACCESS_TOKEN_TTL_SECONDS; } });
68
+ Object.defineProperty(exports, "DEFAULT_REFRESH_TOKEN_TTL_SECONDS", { enumerable: true, get: function () { return config_js_1.DEFAULT_REFRESH_TOKEN_TTL_SECONDS; } });
69
+ Object.defineProperty(exports, "ACCESS_TOKEN_TTL_BOUNDS", { enumerable: true, get: function () { return config_js_1.ACCESS_TOKEN_TTL_BOUNDS; } });
70
+ Object.defineProperty(exports, "REFRESH_TOKEN_TTL_BOUNDS", { enumerable: true, get: function () { return config_js_1.REFRESH_TOKEN_TTL_BOUNDS; } });
71
+ var discovery_controller_js_1 = require("./discovery-controller.js");
72
+ Object.defineProperty(exports, "createDiscoveryHandlers", { enumerable: true, get: function () { return discovery_controller_js_1.createDiscoveryHandlers; } });
73
+ Object.defineProperty(exports, "createDiscoveryRouter", { enumerable: true, get: function () { return discovery_controller_js_1.createDiscoveryRouter; } });
74
+ var registration_controller_js_1 = require("./registration-controller.js");
75
+ Object.defineProperty(exports, "createRegistrationHandlers", { enumerable: true, get: function () { return registration_controller_js_1.createRegistrationHandlers; } });
76
+ Object.defineProperty(exports, "createRegistrationRouter", { enumerable: true, get: function () { return registration_controller_js_1.createRegistrationRouter; } });
77
+ Object.defineProperty(exports, "toRegistrationResponse", { enumerable: true, get: function () { return registration_controller_js_1.toRegistrationResponse; } });
78
+ var rate_limit_js_1 = require("./rate-limit.js");
79
+ Object.defineProperty(exports, "createRegistrationRateLimiter", { enumerable: true, get: function () { return rate_limit_js_1.createRegistrationRateLimiter; } });
80
+ Object.defineProperty(exports, "DEFAULT_REGISTRATION_RATE_LIMIT", { enumerable: true, get: function () { return rate_limit_js_1.DEFAULT_REGISTRATION_RATE_LIMIT; } });
81
+ Object.defineProperty(exports, "DEFAULT_REGISTRATION_RATE_WINDOW_MS", { enumerable: true, get: function () { return rate_limit_js_1.DEFAULT_REGISTRATION_RATE_WINDOW_MS; } });
82
+ var types_js_1 = require("./types.js");
83
+ Object.defineProperty(exports, "CLIENT_MODES", { enumerable: true, get: function () { return types_js_1.CLIENT_MODES; } });
84
+ var token_service_js_1 = require("./token-service.js");
85
+ Object.defineProperty(exports, "createTokenService", { enumerable: true, get: function () { return token_service_js_1.createTokenService; } });
86
+ Object.defineProperty(exports, "buildIdentityKey", { enumerable: true, get: function () { return token_service_js_1.buildIdentityKey; } });
87
+ Object.defineProperty(exports, "AUTHORIZATION_CODE_TTL_SECONDS", { enumerable: true, get: function () { return token_service_js_1.AUTHORIZATION_CODE_TTL_SECONDS; } });
88
+ Object.defineProperty(exports, "OAUTH_CODE_DOMAIN", { enumerable: true, get: function () { return token_service_js_1.OAUTH_CODE_DOMAIN; } });
89
+ Object.defineProperty(exports, "OAUTH_ACCESS_DOMAIN", { enumerable: true, get: function () { return token_service_js_1.OAUTH_ACCESS_DOMAIN; } });
90
+ Object.defineProperty(exports, "OAUTH_REFRESH_DOMAIN", { enumerable: true, get: function () { return token_service_js_1.OAUTH_REFRESH_DOMAIN; } });
91
+ var grant_service_js_1 = require("./grant-service.js");
92
+ Object.defineProperty(exports, "createGrantService", { enumerable: true, get: function () { return grant_service_js_1.createGrantService; } });
93
+ Object.defineProperty(exports, "isGrantActive", { enumerable: true, get: function () { return grant_service_js_1.isGrantActive; } });
94
+ Object.defineProperty(exports, "OAUTH_GRANTS_PROPERTY", { enumerable: true, get: function () { return grant_service_js_1.OAUTH_GRANTS_PROPERTY; } });
95
+ Object.defineProperty(exports, "OAUTH_GRANTS_INFO_SCHEMA", { enumerable: true, get: function () { return grant_service_js_1.OAUTH_GRANTS_INFO_SCHEMA; } });
96
+ var authorization_code_service_js_1 = require("./authorization-code-service.js");
97
+ Object.defineProperty(exports, "createAuthorizationCodeService", { enumerable: true, get: function () { return authorization_code_service_js_1.createAuthorizationCodeService; } });
98
+ Object.defineProperty(exports, "OAUTH_CODES_PROPERTY", { enumerable: true, get: function () { return authorization_code_service_js_1.OAUTH_CODES_PROPERTY; } });
99
+ Object.defineProperty(exports, "OAUTH_CODES_INFO_SCHEMA", { enumerable: true, get: function () { return authorization_code_service_js_1.OAUTH_CODES_INFO_SCHEMA; } });
100
+ var pkce_js_1 = require("./pkce.js");
101
+ Object.defineProperty(exports, "CODE_CHALLENGE_METHOD", { enumerable: true, get: function () { return pkce_js_1.CODE_CHALLENGE_METHOD; } });
102
+ Object.defineProperty(exports, "deriveCodeChallenge", { enumerable: true, get: function () { return pkce_js_1.deriveCodeChallenge; } });
103
+ Object.defineProperty(exports, "isValidCodeChallenge", { enumerable: true, get: function () { return pkce_js_1.isValidCodeChallenge; } });
104
+ Object.defineProperty(exports, "isValidCodeVerifier", { enumerable: true, get: function () { return pkce_js_1.isValidCodeVerifier; } });
105
+ Object.defineProperty(exports, "verifyCodeChallenge", { enumerable: true, get: function () { return pkce_js_1.verifyCodeChallenge; } });
106
+ var oauth_error_js_1 = require("./oauth-error.js");
107
+ Object.defineProperty(exports, "OAuthError", { enumerable: true, get: function () { return oauth_error_js_1.OAuthError; } });
108
+ Object.defineProperty(exports, "isOAuthError", { enumerable: true, get: function () { return oauth_error_js_1.isOAuthError; } });
109
+ var user_store_js_1 = require("./user-store.js");
110
+ Object.defineProperty(exports, "isStaleWriteError", { enumerable: true, get: function () { return user_store_js_1.isStaleWriteError; } });
111
+ var property_array_js_1 = require("./property-array.js");
112
+ Object.defineProperty(exports, "readArray", { enumerable: true, get: function () { return property_array_js_1.readArray; } });
113
+ Object.defineProperty(exports, "writeArray", { enumerable: true, get: function () { return property_array_js_1.writeArray; } });
114
+ var consent_controller_js_1 = require("./consent-controller.js");
115
+ Object.defineProperty(exports, "createConsentHandlers", { enumerable: true, get: function () { return consent_controller_js_1.createConsentHandlers; } });
116
+ Object.defineProperty(exports, "createConsentRouter", { enumerable: true, get: function () { return consent_controller_js_1.createConsentRouter; } });
117
+ Object.defineProperty(exports, "monogramFor", { enumerable: true, get: function () { return consent_controller_js_1.monogramFor; } });
118
+ Object.defineProperty(exports, "provenanceFor", { enumerable: true, get: function () { return consent_controller_js_1.provenanceFor; } });
119
+ Object.defineProperty(exports, "safeLogoUri", { enumerable: true, get: function () { return consent_controller_js_1.safeLogoUri; } });
120
+ Object.defineProperty(exports, "scopeDescriptionsFrom", { enumerable: true, get: function () { return consent_controller_js_1.scopeDescriptionsFrom; } });
121
+ Object.defineProperty(exports, "toScopeViews", { enumerable: true, get: function () { return consent_controller_js_1.toScopeViews; } });
122
+ Object.defineProperty(exports, "warnUndescribedScopes", { enumerable: true, get: function () { return consent_controller_js_1.warnUndescribedScopes; } });
123
+ Object.defineProperty(exports, "SCOPE_DESCRIPTIONS_LOCAL", { enumerable: true, get: function () { return consent_controller_js_1.SCOPE_DESCRIPTIONS_LOCAL; } });
124
+ var token_controller_js_1 = require("./token-controller.js");
125
+ Object.defineProperty(exports, "createTokenHandlers", { enumerable: true, get: function () { return token_controller_js_1.createTokenHandlers; } });
126
+ Object.defineProperty(exports, "createTokenRouter", { enumerable: true, get: function () { return token_controller_js_1.createTokenRouter; } });
127
+ Object.defineProperty(exports, "parseScopes", { enumerable: true, get: function () { return token_controller_js_1.parseScopes; } });
128
+ Object.defineProperty(exports, "OFFLINE_ACCESS_SCOPE", { enumerable: true, get: function () { return token_controller_js_1.OFFLINE_ACCESS_SCOPE; } });
129
+ var bearer_js_1 = require("./bearer.js");
130
+ Object.defineProperty(exports, "createOAuthBearerMiddleware", { enumerable: true, get: function () { return bearer_js_1.createOAuthBearerMiddleware; } });
131
+ Object.defineProperty(exports, "createOAuthResourceServer", { enumerable: true, get: function () { return bearer_js_1.createOAuthResourceServer; } });
132
+ Object.defineProperty(exports, "createOAuthTokenResolver", { enumerable: true, get: function () { return bearer_js_1.createOAuthTokenResolver; } });
133
+ Object.defineProperty(exports, "missingScopes", { enumerable: true, get: function () { return bearer_js_1.missingScopes; } });
134
+ Object.defineProperty(exports, "requireOAuth", { enumerable: true, get: function () { return bearer_js_1.requireOAuth; } });
135
+ Object.defineProperty(exports, "DEFAULT_BEARER_CHALLENGE", { enumerable: true, get: function () { return bearer_js_1.DEFAULT_BEARER_CHALLENGE; } });
136
+ var revocation_service_js_1 = require("./revocation-service.js");
137
+ Object.defineProperty(exports, "createRevocationService", { enumerable: true, get: function () { return revocation_service_js_1.createRevocationService; } });
138
+ Object.defineProperty(exports, "REVOKED_BY_CLIENT", { enumerable: true, get: function () { return revocation_service_js_1.REVOKED_BY_CLIENT; } });
139
+ Object.defineProperty(exports, "REVOKED_BY_USER", { enumerable: true, get: function () { return revocation_service_js_1.REVOKED_BY_USER; } });
140
+ Object.defineProperty(exports, "REVOKED_CLIENT_WIDE", { enumerable: true, get: function () { return revocation_service_js_1.REVOKED_CLIENT_WIDE; } });
141
+ var revocation_controller_js_1 = require("./revocation-controller.js");
142
+ Object.defineProperty(exports, "createRevocationHandlers", { enumerable: true, get: function () { return revocation_controller_js_1.createRevocationHandlers; } });
143
+ Object.defineProperty(exports, "createRevocationRouter", { enumerable: true, get: function () { return revocation_controller_js_1.createRevocationRouter; } });
144
+ var connections_controller_js_1 = require("./connections-controller.js");
145
+ Object.defineProperty(exports, "createConnectionsHandlers", { enumerable: true, get: function () { return connections_controller_js_1.createConnectionsHandlers; } });
146
+ Object.defineProperty(exports, "createConnectionsRouter", { enumerable: true, get: function () { return connections_controller_js_1.createConnectionsRouter; } });
147
+ Object.defineProperty(exports, "ACCOUNT_COVERAGE_STATEMENT", { enumerable: true, get: function () { return connections_controller_js_1.ACCOUNT_COVERAGE_STATEMENT; } });
148
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { ClientIdMetadataDocument } from './types.js';
2
+ /**
3
+ * Fetching a Client ID Metadata Document.
4
+ *
5
+ * A CIMD client's `client_id` *is* an `https` URL, and the document at that URL
6
+ * is the client's metadata. So this function reaches out to a host we do not
7
+ * control, on a path a stranger chose, during an authorization request a user
8
+ * is waiting on. Everything here is a bound on what that can cost or claim.
9
+ *
10
+ * The HTTP boundary is injected rather than imported, so the component tests
11
+ * drive it directly: what a failing fetch, an oversized body or a lying
12
+ * document do is behaviour worth pinning, and none of it is reachable through a
13
+ * real network in a test suite.
14
+ */
15
+ /** The `fetch` shape this module needs. Narrower than the global on purpose. */
16
+ export type FetchLike = (url: string, init: {
17
+ method: string;
18
+ redirect: 'manual';
19
+ signal: AbortSignal;
20
+ headers: Record<string, string>;
21
+ }) => Promise<FetchLikeResponse>;
22
+ export interface FetchLikeResponse {
23
+ status: number;
24
+ headers: {
25
+ get(name: string): string | null;
26
+ };
27
+ text(): Promise<string>;
28
+ }
29
+ export interface MetadataFetchOptions {
30
+ /**
31
+ * Three seconds, well inside Claude's ten-second budget for the whole
32
+ * authorization step. The user is on the consent redirect while this runs.
33
+ */
34
+ timeoutMs?: number;
35
+ /** Bytes. A metadata document is a few hundred; 64 KiB is generous. */
36
+ maxBytes?: number;
37
+ /** How many `https`→`https` hops to follow before giving up. */
38
+ maxRedirects?: number;
39
+ }
40
+ export declare const DEFAULT_METADATA_TIMEOUT_MS = 3000;
41
+ export declare const DEFAULT_METADATA_MAX_BYTES: number;
42
+ export declare const DEFAULT_METADATA_MAX_REDIRECTS = 3;
43
+ /**
44
+ * Is this a URL we are willing to treat as a `client_id`?
45
+ *
46
+ * `https` only, no credentials, no fragment. The fragment rule matters because
47
+ * `client_id` is compared for equality against the document's own `client_id`,
48
+ * and two URLs differing only in fragment address the same document while
49
+ * comparing unequal — an ambiguity a registry key cannot afford.
50
+ */
51
+ export declare function isValidMetadataUri(value: string): boolean;
52
+ /**
53
+ * Fetch and parse the document at `clientId`.
54
+ *
55
+ * Throws `ClientRegistryError('boop_metadata_document_unusable')` for every
56
+ * failure, so the caller has one thing to catch and one decision to make: fall
57
+ * back to a cached copy, or fail the request.
58
+ */
59
+ export declare function fetchMetadataDocument(clientId: string, fetchImpl: FetchLike, options?: MetadataFetchOptions): Promise<ClientIdMetadataDocument>;
60
+ //# sourceMappingURL=metadata-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-document.d.ts","sourceRoot":"","sources":["../src/metadata-document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;;;;;;;GAYG;AAEH,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,KACE,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEhC,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC9C,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AACjD,eAAO,MAAM,0BAA0B,QAAY,CAAC;AACpD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAKhD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAczD;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CA+CnC"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_METADATA_MAX_REDIRECTS = exports.DEFAULT_METADATA_MAX_BYTES = exports.DEFAULT_METADATA_TIMEOUT_MS = void 0;
4
+ exports.isValidMetadataUri = isValidMetadataUri;
5
+ exports.fetchMetadataDocument = fetchMetadataDocument;
6
+ const errors_js_1 = require("./errors.js");
7
+ exports.DEFAULT_METADATA_TIMEOUT_MS = 3000;
8
+ exports.DEFAULT_METADATA_MAX_BYTES = 64 * 1024;
9
+ exports.DEFAULT_METADATA_MAX_REDIRECTS = 3;
10
+ const unusable = (message) => new errors_js_1.ClientRegistryError('boop_metadata_document_unusable', message);
11
+ /**
12
+ * Is this a URL we are willing to treat as a `client_id`?
13
+ *
14
+ * `https` only, no credentials, no fragment. The fragment rule matters because
15
+ * `client_id` is compared for equality against the document's own `client_id`,
16
+ * and two URLs differing only in fragment address the same document while
17
+ * comparing unequal — an ambiguity a registry key cannot afford.
18
+ */
19
+ function isValidMetadataUri(value) {
20
+ let url;
21
+ try {
22
+ url = new URL(value);
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ return (url.protocol === 'https:' &&
28
+ url.hostname !== '' &&
29
+ url.username === '' &&
30
+ url.password === '' &&
31
+ url.hash === '');
32
+ }
33
+ /**
34
+ * Fetch and parse the document at `clientId`.
35
+ *
36
+ * Throws `ClientRegistryError('boop_metadata_document_unusable')` for every
37
+ * failure, so the caller has one thing to catch and one decision to make: fall
38
+ * back to a cached copy, or fail the request.
39
+ */
40
+ async function fetchMetadataDocument(clientId, fetchImpl, options = {}) {
41
+ const timeoutMs = options.timeoutMs ?? exports.DEFAULT_METADATA_TIMEOUT_MS;
42
+ const maxBytes = options.maxBytes ?? exports.DEFAULT_METADATA_MAX_BYTES;
43
+ const maxRedirects = options.maxRedirects ?? exports.DEFAULT_METADATA_MAX_REDIRECTS;
44
+ if (!isValidMetadataUri(clientId)) {
45
+ throw unusable(`client_id is not a usable https metadata document URL: ${clientId}`);
46
+ }
47
+ const body = await readDocument(clientId, fetchImpl, { timeoutMs, maxBytes, maxRedirects });
48
+ let parsed;
49
+ try {
50
+ parsed = JSON.parse(body);
51
+ }
52
+ catch {
53
+ throw unusable(`metadata document at ${clientId} is not JSON`);
54
+ }
55
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
56
+ throw unusable(`metadata document at ${clientId} is not a JSON object`);
57
+ }
58
+ const doc = parsed;
59
+ /**
60
+ * **The check that stops one document claiming another's identity.**
61
+ *
62
+ * Without it, anyone who can publish a redirect — or simply a document — can
63
+ * assert someone else's `client_id`, and the consent screen then shows a name
64
+ * and logo belonging to a client the user trusts while the redirect goes
65
+ * somewhere else entirely.
66
+ *
67
+ * It is deliberately compared against the URL we were *asked* for rather than
68
+ * the URL we ended up at. That is the stricter reading: if `a.example`
69
+ * redirects to a document whose `client_id` is `b.example`, then following
70
+ * the redirect and accepting `b.example`'s claim would let the owner of
71
+ * `a.example` register under `b.example`'s identity. Requiring the document
72
+ * to name the URL the client presented closes that, and costs a CIMD
73
+ * publisher nothing — the specification already requires the document's
74
+ * `client_id` to be its own URL.
75
+ */
76
+ if (doc.client_id !== clientId) {
77
+ throw unusable(`metadata document at ${clientId} claims a different client_id (${String(doc.client_id)})`);
78
+ }
79
+ return doc;
80
+ }
81
+ /** The transport half: redirects, timeout, size cap. */
82
+ async function readDocument(startUrl, fetchImpl, limits) {
83
+ let url = startUrl;
84
+ for (let hop = 0; hop <= limits.maxRedirects; hop += 1) {
85
+ const controller = new AbortController();
86
+ const timer = setTimeout(() => controller.abort(), limits.timeoutMs);
87
+ let response;
88
+ try {
89
+ response = await fetchImpl(url, {
90
+ method: 'GET',
91
+ // Manual, so a redirect is a decision this code makes rather than one
92
+ // the HTTP client makes for it. `fetch`'s own redirect following would
93
+ // happily walk `https` → `http`, which is the hop this refuses.
94
+ redirect: 'manual',
95
+ signal: controller.signal,
96
+ headers: { accept: 'application/json' },
97
+ });
98
+ }
99
+ catch (err) {
100
+ throw unusable(`metadata document at ${url} could not be fetched: ${describe(err)}`);
101
+ }
102
+ finally {
103
+ clearTimeout(timer);
104
+ }
105
+ if (response.status >= 300 && response.status < 400) {
106
+ const location = response.headers.get('location');
107
+ if (!location)
108
+ throw unusable(`metadata document at ${url} redirected with no Location`);
109
+ let next;
110
+ try {
111
+ next = new URL(location, url);
112
+ }
113
+ catch {
114
+ throw unusable(`metadata document at ${url} redirected to an unparseable ${location}`);
115
+ }
116
+ if (next.protocol !== 'https:') {
117
+ throw unusable(`metadata document at ${url} redirected to a non-https origin (${next.protocol}//${next.host})`);
118
+ }
119
+ url = next.toString();
120
+ continue;
121
+ }
122
+ if (response.status !== 200) {
123
+ throw unusable(`metadata document at ${url} answered ${response.status}`);
124
+ }
125
+ // Two size checks, because either alone has a hole. A declared
126
+ // `content-length` refuses a large body before it is read; measuring the
127
+ // body afterwards catches a chunked response that declared nothing. Neither
128
+ // caps the bytes actually pulled over the wire — that would need a stream,
129
+ // and `fetch`'s body is one, but the injected boundary these tests drive is
130
+ // not. The timeout is what bounds the pathological case in the meantime.
131
+ const declared = Number(response.headers.get('content-length'));
132
+ if (Number.isFinite(declared) && declared > limits.maxBytes) {
133
+ throw unusable(`metadata document at ${url} declares ${declared} bytes, over the ${limits.maxBytes} cap`);
134
+ }
135
+ const text = await response.text();
136
+ if (Buffer.byteLength(text, 'utf8') > limits.maxBytes) {
137
+ throw unusable(`metadata document at ${url} is over the ${limits.maxBytes}-byte cap`);
138
+ }
139
+ return text;
140
+ }
141
+ throw unusable(`metadata document at ${startUrl} redirected more than ${limits.maxRedirects} times`);
142
+ }
143
+ function describe(err) {
144
+ if (err instanceof Error)
145
+ return err.message;
146
+ return String(err);
147
+ }
148
+ //# sourceMappingURL=metadata-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-document.js","sourceRoot":"","sources":["../src/metadata-document.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * RFC 6749 error responses, as a typed refusal the controllers translate once.
3
+ *
4
+ * ## Why this is separate from `ClientRegistryError`
5
+ *
6
+ * `errors.ts` carries registration's vocabulary — RFC 7591 §3.2.2 plus a few
7
+ * `boop_` codes for things the specification has no word for. This carries the
8
+ * *grant* vocabulary: RFC 6749 §5.2's five codes, which a client library parses
9
+ * and branches on. They are different registries with different consumers, and
10
+ * a single enum spanning both would let a registration code reach a token
11
+ * response, which no client knows how to read.
12
+ *
13
+ * ## Status codes are not free choices
14
+ *
15
+ * §5.2 fixes them. `invalid_client` is 401 (with a `WWW-Authenticate` header
16
+ * when the client tried to authenticate); everything else is 400. Answering
17
+ * `invalid_grant` with a 401 makes a well-written client discard its refresh
18
+ * token *and* its access token and start a whole new authorization, which is a
19
+ * user-visible re-consent for what may be a transient server fault.
20
+ */
21
+ /**
22
+ * RFC 6749 §5.2, plus §4.1.2.1's `access_denied` for the authorize redirect and
23
+ * RFC 7009 §2.2.1's `unsupported_token_type` for the revocation endpoint.
24
+ *
25
+ * `unsupported_token_type` belongs here rather than in `errors.ts` for the same
26
+ * reason the rest of this list does: RFC 7009 registers it in the OAuth
27
+ * Extensions Error Registry the token endpoint draws from, and a client library
28
+ * parses it off a body of exactly this shape. Its status is the default 400, so
29
+ * `STATUS_BY_CODE` needs no entry for it.
30
+ */
31
+ export type OAuthErrorCode = 'invalid_request' | 'invalid_client' | 'invalid_grant' | 'unauthorized_client' | 'unsupported_grant_type' | 'unsupported_token_type' | 'invalid_scope' | 'access_denied' | 'server_error' | 'temporarily_unavailable' | 'unsupported_response_type';
32
+ export declare class OAuthError extends Error {
33
+ readonly error: OAuthErrorCode;
34
+ readonly status: number;
35
+ readonly description: string;
36
+ constructor(error: OAuthErrorCode, description: string, status?: number);
37
+ /** The response body, exactly as §5.2 shapes it. */
38
+ toBody(): {
39
+ error: OAuthErrorCode;
40
+ error_description: string;
41
+ };
42
+ }
43
+ /** Narrower than `instanceof`, which is a false negative across module copies. */
44
+ export declare function isOAuthError(err: unknown): err is OAuthError;
45
+ //# sourceMappingURL=oauth-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-error.d.ts","sourceRoot":"","sources":["../src/oauth-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,GACtB,iBAAiB,GACjB,gBAAgB,GAChB,eAAe,GACf,qBAAqB,GACrB,wBAAwB,GACxB,wBAAwB,GACxB,eAAe,GACf,eAAe,GACf,cAAc,GACd,yBAAyB,GACzB,2BAA2B,CAAC;AAQhC,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAQvE,oDAAoD;IACpD,MAAM,IAAI;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE;CAG/D;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU,CAO5D"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * RFC 6749 error responses, as a typed refusal the controllers translate once.
4
+ *
5
+ * ## Why this is separate from `ClientRegistryError`
6
+ *
7
+ * `errors.ts` carries registration's vocabulary — RFC 7591 §3.2.2 plus a few
8
+ * `boop_` codes for things the specification has no word for. This carries the
9
+ * *grant* vocabulary: RFC 6749 §5.2's five codes, which a client library parses
10
+ * and branches on. They are different registries with different consumers, and
11
+ * a single enum spanning both would let a registration code reach a token
12
+ * response, which no client knows how to read.
13
+ *
14
+ * ## Status codes are not free choices
15
+ *
16
+ * §5.2 fixes them. `invalid_client` is 401 (with a `WWW-Authenticate` header
17
+ * when the client tried to authenticate); everything else is 400. Answering
18
+ * `invalid_grant` with a 401 makes a well-written client discard its refresh
19
+ * token *and* its access token and start a whole new authorization, which is a
20
+ * user-visible re-consent for what may be a transient server fault.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.OAuthError = void 0;
24
+ exports.isOAuthError = isOAuthError;
25
+ const STATUS_BY_CODE = {
26
+ invalid_client: 401,
27
+ server_error: 500,
28
+ temporarily_unavailable: 503,
29
+ };
30
+ class OAuthError extends Error {
31
+ constructor(error, description, status) {
32
+ super(`${error}: ${description}`);
33
+ this.name = 'OAuthError';
34
+ this.error = error;
35
+ this.description = description;
36
+ this.status = status ?? STATUS_BY_CODE[error] ?? 400;
37
+ }
38
+ /** The response body, exactly as §5.2 shapes it. */
39
+ toBody() {
40
+ return { error: this.error, error_description: this.description };
41
+ }
42
+ }
43
+ exports.OAuthError = OAuthError;
44
+ /** Narrower than `instanceof`, which is a false negative across module copies. */
45
+ function isOAuthError(err) {
46
+ return (typeof err === 'object' &&
47
+ err !== null &&
48
+ err.name === 'OAuthError' &&
49
+ typeof err.error === 'string');
50
+ }
51
+ //# sourceMappingURL=oauth-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-error.js","sourceRoot":"","sources":["../src/oauth-error.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;;AAmDH,oCAOC;AAjCD,MAAM,cAAc,GAA4C;IAC9D,cAAc,EAAE,GAAG;IACnB,YAAY,EAAE,GAAG;IACjB,uBAAuB,EAAE,GAAG;CAC7B,CAAC;AAEF,MAAa,UAAW,SAAQ,KAAK;IAKnC,YAAY,KAAqB,EAAE,WAAmB,EAAE,MAAe;QACrE,KAAK,CAAC,GAAG,KAAK,KAAK,WAAW,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;IACvD,CAAC;IAED,oDAAoD;IACpD,MAAM;QACJ,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACpE,CAAC;CACF;AAjBD,gCAiBC;AAED,kFAAkF;AAClF,SAAgB,YAAY,CAAC,GAAY;IACvC,OAAO,CACL,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACX,GAA0B,CAAC,IAAI,KAAK,YAAY;QACjD,OAAQ,GAA2B,CAAC,KAAK,KAAK,QAAQ,CACvD,CAAC;AACJ,CAAC"}
package/dist/pkce.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PKCE, RFC 7636 — and only `S256`.
3
+ *
4
+ * `plain` is not a weaker method, it is the absence of one: the "challenge" is
5
+ * the verifier, so an attacker who intercepted the authorization response has
6
+ * everything needed to redeem the code. The discovery document advertises
7
+ * `["S256"]` and this module is the other half of that promise — a request
8
+ * carrying `code_challenge_method=plain` is refused rather than downgraded to.
9
+ *
10
+ * OAuth 2.1 requires PKCE for public clients, and every client this server will
11
+ * ever see is public, so the challenge is **required** rather than optional.
12
+ */
13
+ /** The only method this server accepts. Matches the discovery document. */
14
+ export declare const CODE_CHALLENGE_METHOD = "S256";
15
+ export declare function isValidCodeVerifier(value: unknown): value is string;
16
+ export declare function isValidCodeChallenge(value: unknown): value is string;
17
+ /** BASE64URL-ENCODE(SHA256(ASCII(verifier))), per RFC 7636 §4.6. */
18
+ export declare function deriveCodeChallenge(verifier: string): string;
19
+ /**
20
+ * Does `verifier` satisfy the `challenge` the authorization request carried?
21
+ *
22
+ * Compared with `timingSafeEqual` rather than `===`. The challenge is not a
23
+ * secret — it travelled in a query string — but the comparison is on the
24
+ * redemption path next to comparisons that are, and a codebase where one string
25
+ * equality is constant-time and its neighbour is not teaches the wrong habit to
26
+ * whoever writes the third one.
27
+ */
28
+ export declare function verifyCodeChallenge(verifier: unknown, challenge: unknown, method?: unknown): boolean;
29
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAc5C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEnE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEpE;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,OAAO,EAClB,MAAM,GAAE,OAA+B,GACtC,OAAO,CAST"}