@sentropic/auth-hono 0.2.1 → 0.3.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 (90) hide show
  1. package/README.md +115 -1
  2. package/dist/contracts.d.ts +1 -1
  3. package/dist/contracts.d.ts.map +1 -1
  4. package/dist/contracts.js +2 -0
  5. package/dist/contracts.js.map +1 -1
  6. package/dist/index.d.ts +15 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +15 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/oauth/authorize-handler.d.ts +13 -0
  11. package/dist/oauth/authorize-handler.d.ts.map +1 -0
  12. package/dist/oauth/authorize-handler.js +143 -0
  13. package/dist/oauth/authorize-handler.js.map +1 -0
  14. package/dist/oauth/consent-decision-handler.d.ts +11 -0
  15. package/dist/oauth/consent-decision-handler.d.ts.map +1 -0
  16. package/dist/oauth/consent-decision-handler.js +58 -0
  17. package/dist/oauth/consent-decision-handler.js.map +1 -0
  18. package/dist/oauth/crypto-utils.d.ts +3 -0
  19. package/dist/oauth/crypto-utils.d.ts.map +1 -0
  20. package/dist/oauth/crypto-utils.js +13 -0
  21. package/dist/oauth/crypto-utils.js.map +1 -0
  22. package/dist/oauth/dpop.d.ts +18 -0
  23. package/dist/oauth/dpop.d.ts.map +1 -0
  24. package/dist/oauth/dpop.js +54 -0
  25. package/dist/oauth/dpop.js.map +1 -0
  26. package/dist/oauth/http-utils.d.ts +6 -0
  27. package/dist/oauth/http-utils.d.ts.map +1 -0
  28. package/dist/oauth/http-utils.js +27 -0
  29. package/dist/oauth/http-utils.js.map +1 -0
  30. package/dist/oauth/introspect-handler.d.ts +8 -0
  31. package/dist/oauth/introspect-handler.d.ts.map +1 -0
  32. package/dist/oauth/introspect-handler.js +63 -0
  33. package/dist/oauth/introspect-handler.js.map +1 -0
  34. package/dist/oauth/jwks-service.d.ts +25 -0
  35. package/dist/oauth/jwks-service.d.ts.map +1 -0
  36. package/dist/oauth/jwks-service.js +61 -0
  37. package/dist/oauth/jwks-service.js.map +1 -0
  38. package/dist/oauth/revoke-handler.d.ts +8 -0
  39. package/dist/oauth/revoke-handler.d.ts.map +1 -0
  40. package/dist/oauth/revoke-handler.js +55 -0
  41. package/dist/oauth/revoke-handler.js.map +1 -0
  42. package/dist/oauth/router.d.ts +8 -0
  43. package/dist/oauth/router.d.ts.map +1 -0
  44. package/dist/oauth/router.js +30 -0
  45. package/dist/oauth/router.js.map +1 -0
  46. package/dist/oauth/session-resolver.d.ts +9 -0
  47. package/dist/oauth/session-resolver.d.ts.map +1 -0
  48. package/dist/oauth/session-resolver.js +28 -0
  49. package/dist/oauth/session-resolver.js.map +1 -0
  50. package/dist/oauth/state-codec.d.ts +25 -0
  51. package/dist/oauth/state-codec.d.ts.map +1 -0
  52. package/dist/oauth/state-codec.js +60 -0
  53. package/dist/oauth/state-codec.js.map +1 -0
  54. package/dist/oauth/state-store-types.d.ts +86 -0
  55. package/dist/oauth/state-store-types.d.ts.map +1 -0
  56. package/dist/oauth/state-store-types.js +2 -0
  57. package/dist/oauth/state-store-types.js.map +1 -0
  58. package/dist/oauth/token-handler.d.ts +11 -0
  59. package/dist/oauth/token-handler.d.ts.map +1 -0
  60. package/dist/oauth/token-handler.js +176 -0
  61. package/dist/oauth/token-handler.js.map +1 -0
  62. package/dist/oauth/userinfo-handler.d.ts +9 -0
  63. package/dist/oauth/userinfo-handler.d.ts.map +1 -0
  64. package/dist/oauth/userinfo-handler.js +93 -0
  65. package/dist/oauth/userinfo-handler.js.map +1 -0
  66. package/dist/oauth/wellknown-handler.d.ts +9 -0
  67. package/dist/oauth/wellknown-handler.d.ts.map +1 -0
  68. package/dist/oauth/wellknown-handler.js +37 -0
  69. package/dist/oauth/wellknown-handler.js.map +1 -0
  70. package/dist/ports.d.ts +4 -0
  71. package/dist/ports.d.ts.map +1 -1
  72. package/package.json +1 -1
  73. package/src/contracts.ts +2 -0
  74. package/src/index.ts +15 -0
  75. package/src/oauth/authorize-handler.ts +201 -0
  76. package/src/oauth/consent-decision-handler.ts +93 -0
  77. package/src/oauth/crypto-utils.ts +14 -0
  78. package/src/oauth/dpop.ts +93 -0
  79. package/src/oauth/http-utils.ts +58 -0
  80. package/src/oauth/introspect-handler.ts +88 -0
  81. package/src/oauth/jwks-service.ts +103 -0
  82. package/src/oauth/revoke-handler.ts +70 -0
  83. package/src/oauth/router.ts +42 -0
  84. package/src/oauth/session-resolver.ts +48 -0
  85. package/src/oauth/state-codec.ts +98 -0
  86. package/src/oauth/state-store-types.ts +94 -0
  87. package/src/oauth/token-handler.ts +252 -0
  88. package/src/oauth/userinfo-handler.ts +129 -0
  89. package/src/oauth/wellknown-handler.ts +52 -0
  90. package/src/ports.ts +16 -0
@@ -0,0 +1,27 @@
1
+ export const appendParams = (target, params, baseUrl) => {
2
+ const url = new URL(target, baseUrl);
3
+ for (const [key, value] of Object.entries(params)) {
4
+ if (value !== null && value !== undefined) {
5
+ url.searchParams.set(key, value);
6
+ }
7
+ }
8
+ return url.toString();
9
+ };
10
+ export const oauthJsonError = (c, status, code, message) => c.json({
11
+ error: {
12
+ code,
13
+ message,
14
+ },
15
+ }, status);
16
+ export const redirectWithOAuthError = (redirectUri, code, state, baseUrl) => Response.redirect(appendParams(redirectUri, {
17
+ error: code,
18
+ state,
19
+ }, baseUrl), 302);
20
+ export const redirectOrJson = (c, redirectTo) => {
21
+ const accept = c.req.header('accept') ?? '';
22
+ if (accept.includes('application/json')) {
23
+ return c.json({ redirectTo });
24
+ }
25
+ return c.redirect(redirectTo, 302);
26
+ };
27
+ //# sourceMappingURL=http-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-utils.js","sourceRoot":"","sources":["../../src/oauth/http-utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,MAAc,EACd,MAAiD,EACjD,OAAe,EACP,EAAE;IACV,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,CAAU,EACV,MAAiB,EACjB,IAAY,EACZ,OAAe,EACL,EAAE,CACZ,CAAC,CAAC,IAAI,CACJ;IACE,KAAK,EAAE;QACL,IAAI;QACJ,OAAO;KACR;CACF,EACD,MAAM,CACP,CAAC;AAEJ,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,WAAmB,EACnB,IAAY,EACZ,KAAoB,EACpB,OAAe,EACL,EAAE,CACZ,QAAQ,CAAC,QAAQ,CACf,YAAY,CACV,WAAW,EACX;IACE,KAAK,EAAE,IAAI;IACX,KAAK;CACN,EACD,OAAO,CACR,EACD,GAAG,CACJ,CAAC;AAEJ,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAU,EAAE,UAAkB,EAAY,EAAE;IACzE,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Context } from 'hono';
2
+ import type { AuthHonoPorts } from '../ports.js';
3
+ export interface OAuthIntrospectHandlerOptions {
4
+ issuer: string;
5
+ ports: AuthHonoPorts;
6
+ }
7
+ export declare const createOAuthIntrospectHandler: (options: OAuthIntrospectHandlerOptions) => (c: Context) => Promise<Response>;
8
+ //# sourceMappingURL=introspect-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/introspect-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,eAAO,MAAM,4BAA4B,YAC7B,6BAA6B,SAC7B,OAAO,KAAG,QAAQ,QAAQ,CAgCnC,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { oauthJsonError } from './http-utils.js';
2
+ import { createJwksService } from './jwks-service.js';
3
+ export const createOAuthIntrospectHandler = (options) => async (c) => {
4
+ const authenticated = await authenticateIntrospectionClient(c, options.ports);
5
+ if (authenticated instanceof Response)
6
+ return authenticated;
7
+ const form = new URLSearchParams(await c.req.text());
8
+ const token = form.get('token');
9
+ if (!token)
10
+ return c.json({ active: false });
11
+ const payload = await verifyToken(options, token);
12
+ if (!payload?.jti)
13
+ return c.json({ active: false });
14
+ const meta = await options.ports.oauthStateStore.findTokenMeta(payload.jti);
15
+ if (!meta ||
16
+ meta.expiresAt <= options.ports.clock.now() ||
17
+ (await options.ports.oauthStateStore.isTokenRevoked(payload.jti))) {
18
+ return c.json({ active: false });
19
+ }
20
+ return c.json({
21
+ active: true,
22
+ aud: meta.audience,
23
+ client_id: meta.clientId,
24
+ ...(meta.dpopJkt ? { cnf: { jkt: meta.dpopJkt } } : {}),
25
+ exp: toEpochSeconds(meta.expiresAt),
26
+ iat: typeof payload.iat === 'number' ? payload.iat : undefined,
27
+ jti: meta.jti,
28
+ scope: meta.scope,
29
+ sub: meta.userId,
30
+ token_type: meta.tokenType,
31
+ });
32
+ };
33
+ const authenticateIntrospectionClient = async (c, ports) => {
34
+ const authorization = c.req.header('authorization');
35
+ if (!authorization?.startsWith('Basic ')) {
36
+ return oauthJsonError(c, 401, 'invalid_client', 'Client authentication is required.');
37
+ }
38
+ const decoded = atob(authorization.slice('Basic '.length));
39
+ const separator = decoded.indexOf(':');
40
+ const clientId = separator >= 0 ? decoded.slice(0, separator) : decoded;
41
+ const secret = separator >= 0 ? decoded.slice(separator + 1) : '';
42
+ const client = await ports.oauthStateStore.findClient(clientId);
43
+ if (!client?.clientSecretHash || (await ports.tokens.hashSecret(secret)) !== client.clientSecretHash) {
44
+ return oauthJsonError(c, 401, 'invalid_client', 'Client authentication failed.');
45
+ }
46
+ return true;
47
+ };
48
+ const verifyToken = async (options, token) => {
49
+ try {
50
+ const jwks = createJwksService({ clock: options.ports.clock, jwksPort: options.ports.jwks });
51
+ const result = await jwks.verifyJwt(token, {
52
+ currentDate: options.ports.clock.now(),
53
+ issuer: trimTrailingSlash(options.issuer),
54
+ });
55
+ return result.payload;
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ };
61
+ const toEpochSeconds = (date) => Math.floor(date.getTime() / 1000);
62
+ const trimTrailingSlash = (value) => value.replace(/\/+$/u, '');
63
+ //# sourceMappingURL=introspect-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect-handler.js","sourceRoot":"","sources":["../../src/oauth/introspect-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type JWTVerifyOptions, type JWTVerifyResult, type JWTPayload } from 'jose';
2
+ import type { AuthHonoClockPort } from '../ports.js';
3
+ import type { JwksPort } from './state-store-types.js';
4
+ export interface CreateJwksServiceOptions {
5
+ clock: AuthHonoClockPort;
6
+ jwksPort: JwksPort;
7
+ }
8
+ export interface JwksSignOptions {
9
+ audience?: string | string[];
10
+ expiresAt?: Date;
11
+ issuer?: string;
12
+ jti?: string;
13
+ subject?: string;
14
+ type?: string;
15
+ }
16
+ export interface PublicJwks {
17
+ keys: Array<Record<string, unknown>>;
18
+ }
19
+ export interface JwksService {
20
+ getPublicJwks(): Promise<PublicJwks>;
21
+ signJwt(payload: JWTPayload, options?: JwksSignOptions): Promise<string>;
22
+ verifyJwt<T extends JWTPayload = JWTPayload>(jwt: string, options?: JWTVerifyOptions): Promise<JWTVerifyResult<T>>;
23
+ }
24
+ export declare const createJwksService: ({ clock, jwksPort }: CreateJwksServiceOptions) => JwksService;
25
+ //# sourceMappingURL=jwks-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwks-service.d.ts","sourceRoot":"","sources":["../../src/oauth/jwks-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,SAAS,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,EACzC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CAChC;AAED,eAAO,MAAM,iBAAiB,wBAAyB,wBAAwB,KAAG,WA4DhF,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { decodeProtectedHeader, importJWK, jwtVerify, SignJWT, } from 'jose';
2
+ export const createJwksService = ({ clock, jwksPort }) => ({
3
+ async getPublicJwks() {
4
+ const keys = await jwksPort.listPublicKeys();
5
+ return {
6
+ keys: keys.map((key) => {
7
+ const { d: _privateExponent, ...publicJwk } = key.publicJwk;
8
+ return {
9
+ ...publicJwk,
10
+ alg: key.alg,
11
+ crv: key.crv,
12
+ kid: key.kid,
13
+ kty: publicJwk.kty,
14
+ status: key.active ? 'active' : 'rotated',
15
+ use: 'sig',
16
+ };
17
+ }),
18
+ };
19
+ },
20
+ async signJwt(payload, options = {}) {
21
+ const activeKey = await jwksPort.getActiveKey();
22
+ if (!activeKey) {
23
+ throw new Error('No active JWKS signing key is configured.');
24
+ }
25
+ if (!activeKey.privateKey) {
26
+ throw new Error(`Active JWKS signing key ${activeKey.kid} has no private key material.`);
27
+ }
28
+ let jwt = new SignJWT(payload).setProtectedHeader({
29
+ alg: activeKey.alg,
30
+ kid: activeKey.kid,
31
+ ...(options.type ? { typ: options.type } : {}),
32
+ });
33
+ jwt = jwt.setIssuedAt(toEpochSeconds(clock.now()));
34
+ if (options.audience)
35
+ jwt = jwt.setAudience(options.audience);
36
+ if (options.expiresAt)
37
+ jwt = jwt.setExpirationTime(toEpochSeconds(options.expiresAt));
38
+ if (options.issuer)
39
+ jwt = jwt.setIssuer(options.issuer);
40
+ if (options.jti)
41
+ jwt = jwt.setJti(options.jti);
42
+ if (options.subject)
43
+ jwt = jwt.setSubject(options.subject);
44
+ return jwt.sign(activeKey.privateKey);
45
+ },
46
+ async verifyJwt(jwt, options = {}) {
47
+ const protectedHeader = decodeProtectedHeader(jwt);
48
+ const kid = protectedHeader.kid;
49
+ if (!kid) {
50
+ throw new Error('JWT protected header is missing kid.');
51
+ }
52
+ const key = await jwksPort.findKeyByKid(kid);
53
+ if (!key) {
54
+ throw new Error(`Unknown JWKS kid: ${kid}`);
55
+ }
56
+ const publicKey = await importJWK(key.publicJwk, key.alg);
57
+ return jwtVerify(jwt, publicKey, options);
58
+ },
59
+ });
60
+ const toEpochSeconds = (date) => Math.floor(date.getTime() / 1000);
61
+ //# sourceMappingURL=jwks-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwks-service.js","sourceRoot":"","sources":["../../src/oauth/jwks-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Context } from 'hono';
2
+ import type { AuthHonoPorts } from '../ports.js';
3
+ export interface OAuthRevokeHandlerOptions {
4
+ dpopIatSkewSeconds?: number;
5
+ ports: AuthHonoPorts;
6
+ }
7
+ export declare const createOAuthRevokeHandler: (options: OAuthRevokeHandlerOptions) => (c: Context) => Promise<Response>;
8
+ //# sourceMappingURL=revoke-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoke-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/revoke-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,WAAW,yBAAyB;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,eAAO,MAAM,wBAAwB,YACzB,yBAAyB,SACzB,OAAO,KAAG,QAAQ,QAAQ,CAgBnC,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { decodeJwt } from 'jose';
2
+ import { OAuthDpopProofError, verifyOAuthDpopProof } from './dpop.js';
3
+ import { oauthJsonError } from './http-utils.js';
4
+ export const createOAuthRevokeHandler = (options) => async (c) => {
5
+ const form = new URLSearchParams(await c.req.text());
6
+ const token = form.get('token');
7
+ if (!token)
8
+ return oauthJsonError(c, 400, 'invalid_request', 'token is required.');
9
+ const jti = decodeTokenJti(token);
10
+ if (!jti)
11
+ return c.json({ success: true });
12
+ const meta = await options.ports.oauthStateStore.findTokenMeta(jti);
13
+ if (meta?.dpopJkt) {
14
+ const dpop = await validateRevokeDpop(c, options, token, meta.dpopJkt);
15
+ if (dpop instanceof Response)
16
+ return dpop;
17
+ }
18
+ await options.ports.oauthStateStore.revokeToken(jti);
19
+ return c.json({ success: true });
20
+ };
21
+ const validateRevokeDpop = async (c, options, accessToken, expectedJkt) => {
22
+ const proof = c.req.header('dpop');
23
+ if (!proof)
24
+ return oauthJsonError(c, 400, 'invalid_dpop_proof', 'DPoP proof is required.');
25
+ try {
26
+ const verified = await verifyOAuthDpopProof({
27
+ accessToken,
28
+ htm: 'POST',
29
+ htu: c.req.url,
30
+ iatSkewSeconds: options.dpopIatSkewSeconds,
31
+ ports: options.ports,
32
+ proof,
33
+ });
34
+ if (verified.jkt !== expectedJkt) {
35
+ return oauthJsonError(c, 400, 'invalid_dpop_proof', 'DPoP proof key does not match the token.');
36
+ }
37
+ return null;
38
+ }
39
+ catch (error) {
40
+ if (error instanceof OAuthDpopProofError) {
41
+ return oauthJsonError(c, 400, 'invalid_dpop_proof', error.message);
42
+ }
43
+ throw error;
44
+ }
45
+ };
46
+ const decodeTokenJti = (token) => {
47
+ try {
48
+ const payload = decodeJwt(token);
49
+ return typeof payload.jti === 'string' ? payload.jti : null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ };
55
+ //# sourceMappingURL=revoke-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoke-handler.js","sourceRoot":"","sources":["../../src/oauth/revoke-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Hono } from 'hono';
2
+ import { type OAuthAuthorizeHandlerOptions } from './authorize-handler.js';
3
+ export interface CreateOAuthRouterOptions extends OAuthAuthorizeHandlerOptions {
4
+ authorizationCodeTtlSeconds?: number;
5
+ routePrefix?: string;
6
+ }
7
+ export declare const createOAuthRouter: (options: CreateOAuthRouterOptions) => Hono;
8
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/oauth/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAA+B,KAAK,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAUxG,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,YAAa,wBAAwB,KAAG,IAcrE,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Hono } from 'hono';
2
+ import { createOAuthAuthorizeHandler } from './authorize-handler.js';
3
+ import { createOAuthConsentDecisionHandler, createOAuthConsentDetailsHandler, } from './consent-decision-handler.js';
4
+ import { createOAuthIntrospectHandler } from './introspect-handler.js';
5
+ import { createOAuthRevokeHandler } from './revoke-handler.js';
6
+ import { createOAuthTokenHandler } from './token-handler.js';
7
+ import { createOAuthUserInfoHandler } from './userinfo-handler.js';
8
+ export const createOAuthRouter = (options) => {
9
+ const router = new Hono();
10
+ const prefix = normalizeRoutePrefix(options.routePrefix ?? '/oauth');
11
+ router.get(joinRoutePath(prefix, '/authorize'), createOAuthAuthorizeHandler(options));
12
+ router.get(joinRoutePath(prefix, '/consent'), createOAuthConsentDetailsHandler(options));
13
+ router.post(joinRoutePath(prefix, '/consent/decision'), createOAuthConsentDecisionHandler(options));
14
+ router.post(joinRoutePath(prefix, '/token'), createOAuthTokenHandler(options));
15
+ router.get(joinRoutePath(prefix, '/userinfo'), createOAuthUserInfoHandler(options));
16
+ router.post(joinRoutePath(prefix, '/userinfo'), createOAuthUserInfoHandler(options));
17
+ router.post(joinRoutePath(prefix, '/revoke'), createOAuthRevokeHandler(options));
18
+ router.post(joinRoutePath(prefix, '/introspect'), createOAuthIntrospectHandler(options));
19
+ return router;
20
+ };
21
+ const normalizeRoutePrefix = (prefix) => {
22
+ if (!prefix || prefix === '/')
23
+ return '';
24
+ return `/${prefix.replace(/^\/+|\/+$/g, '')}`;
25
+ };
26
+ const joinRoutePath = (prefix, path) => {
27
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`;
28
+ return `${prefix}${normalizedPath}`;
29
+ };
30
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/oauth/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,2BAA2B,EAAqC,MAAM,wBAAwB,CAAC;AACxG,OAAO,EACL,iCAAiC,EACjC,gCAAgC,GACjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAOnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAiC,EAAQ,EAAE;IAC3E,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC,CAAC;IAErE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;IACtF,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,gCAAgC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAAE,iCAAiC,CAAC,OAAO,CAAC,CAAC,CAAC;IACpG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;IACrF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;IACjF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,4BAA4B,CAAC,OAAO,CAAC,CAAC,CAAC;IAEzF,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,MAAc,EAAU,EAAE;IACtD,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACzC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE;IAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAChE,OAAO,GAAG,MAAM,GAAG,cAAc,EAAE,CAAC;AACtC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { AuthHonoPorts, AuthHonoSessionClaims, AuthHonoSessionRecord, AuthHonoUserRecord } from '../ports.js';
2
+ export interface OAuthResolvedSession {
3
+ claims: AuthHonoSessionClaims;
4
+ sessionRecord: AuthHonoSessionRecord;
5
+ user: AuthHonoUserRecord;
6
+ }
7
+ export declare const resolveOAuthSession: (request: Request, ports: AuthHonoPorts) => Promise<OAuthResolvedSession | null>;
8
+ export declare const resolveOAuthAcr: (session: AuthHonoSessionRecord) => string;
9
+ //# sourceMappingURL=session-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.d.ts","sourceRoot":"","sources":["../../src/oauth/session-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,qBAAqB,CAAC;IACrC,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED,eAAO,MAAM,mBAAmB,YACrB,OAAO,SACT,aAAa,KACnB,QAAQ,oBAAoB,GAAG,IAAI,CA4BrC,CAAC;AAEF,eAAO,MAAM,eAAe,YAAa,qBAAqB,KAAG,MACqB,CAAC"}
@@ -0,0 +1,28 @@
1
+ export const resolveOAuthSession = async (request, ports) => {
2
+ const token = ports.cookies.readSessionToken(request);
3
+ if (!token)
4
+ return null;
5
+ const claims = await ports.tokens.verifySessionToken(token);
6
+ if (!claims)
7
+ return null;
8
+ const tokenHash = await ports.tokens.hashSecret(token);
9
+ const sessionRecord = await ports.sessions.findByTokenHash(tokenHash);
10
+ const now = ports.clock.now();
11
+ if (!sessionRecord ||
12
+ sessionRecord.id !== claims.sessionId ||
13
+ sessionRecord.userId !== claims.userId ||
14
+ sessionRecord.revokedAt ||
15
+ sessionRecord.expiresAt <= now) {
16
+ return null;
17
+ }
18
+ const user = await ports.users.findById(claims.userId);
19
+ if (!user)
20
+ return null;
21
+ const decision = await ports.accountPolicy.canAuthenticate(user, now);
22
+ if (!decision.allowed)
23
+ return null;
24
+ await ports.sessions.touch(sessionRecord.id, now);
25
+ return { claims, sessionRecord, user };
26
+ };
27
+ export const resolveOAuthAcr = (session) => session.mfaVerified ? 'urn:sentropic:loa:passkey-fresh' : 'urn:sentropic:loa:bearer';
28
+ //# sourceMappingURL=session-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-resolver.js","sourceRoot":"","sources":["../../src/oauth/session-resolver.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,OAAgB,EAChB,KAAoB,EACkB,EAAE;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAC9B,IACE,CAAC,aAAa;QACd,aAAa,CAAC,EAAE,KAAK,MAAM,CAAC,SAAS;QACrC,aAAa,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;QACtC,aAAa,CAAC,SAAS;QACvB,aAAa,CAAC,SAAS,IAAI,GAAG,EAC9B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtE,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAA8B,EAAU,EAAE,CACxE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,0BAA0B,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface OAuthContinuationState {
2
+ acr?: string;
3
+ authTime?: string;
4
+ clientId: string;
5
+ codeChallenge: string;
6
+ codeChallengeMethod: 'S256';
7
+ createdAt: string;
8
+ dpopJkt: string | null;
9
+ expiresAt: string;
10
+ nonce: string | null;
11
+ redirectUri: string;
12
+ scope: string;
13
+ state: string | null;
14
+ tenantId: string | null;
15
+ userId?: string;
16
+ }
17
+ export interface OAuthContinuationCodec {
18
+ seal(payload: OAuthContinuationState): Promise<string> | string;
19
+ unseal(token: string): Promise<OAuthContinuationState | null> | OAuthContinuationState | null;
20
+ }
21
+ export interface CreateOAuthHmacStateCodecOptions {
22
+ secret: string;
23
+ }
24
+ export declare const createOAuthHmacStateCodec: ({ secret, }: CreateOAuthHmacStateCodecOptions) => OAuthContinuationCodec;
25
+ //# sourceMappingURL=state-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-codec.d.ts","sourceRoot":"","sources":["../../src/oauth/state-codec.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAChE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,sBAAsB,GAAG,IAAI,CAAC;CAC/F;AAED,MAAM,WAAW,gCAAgC;IAC/C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,yBAAyB,gBAEnC,gCAAgC,KAAG,sBA2BrC,CAAC"}
@@ -0,0 +1,60 @@
1
+ export const createOAuthHmacStateCodec = ({ secret, }) => {
2
+ if (!secret) {
3
+ throw new Error('OAuth state codec secret is required.');
4
+ }
5
+ return {
6
+ async seal(payload) {
7
+ const body = base64urlEncode(textEncoder.encode(JSON.stringify(payload)));
8
+ return `${body}.${await sign(body, secret)}`;
9
+ },
10
+ async unseal(token) {
11
+ const [body, signature, extra] = token.split('.');
12
+ if (!body || !signature || extra !== undefined)
13
+ return null;
14
+ const expected = await sign(body, secret);
15
+ const actualBytes = base64urlDecode(signature);
16
+ const expectedBytes = base64urlDecode(expected);
17
+ if (!timingSafeEqual(actualBytes, expectedBytes))
18
+ return null;
19
+ try {
20
+ return JSON.parse(textDecoder.decode(base64urlDecode(body)));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ },
26
+ };
27
+ };
28
+ const textEncoder = new TextEncoder();
29
+ const textDecoder = new TextDecoder();
30
+ const sign = async (body, secret) => {
31
+ const key = await crypto.subtle.importKey('raw', textEncoder.encode(secret), { hash: 'SHA-256', name: 'HMAC' }, false, ['sign']);
32
+ const signature = await crypto.subtle.sign('HMAC', key, textEncoder.encode(body));
33
+ return base64urlEncode(new Uint8Array(signature));
34
+ };
35
+ const timingSafeEqual = (actual, expected) => {
36
+ if (actual.byteLength !== expected.byteLength)
37
+ return false;
38
+ let diff = 0;
39
+ for (let index = 0; index < actual.byteLength; index += 1) {
40
+ diff |= actual[index] ^ expected[index];
41
+ }
42
+ return diff === 0;
43
+ };
44
+ const base64urlEncode = (bytes) => {
45
+ let binary = '';
46
+ for (const byte of bytes) {
47
+ binary += String.fromCharCode(byte);
48
+ }
49
+ return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/u, '');
50
+ };
51
+ const base64urlDecode = (value) => {
52
+ const base64 = value.replaceAll('-', '+').replaceAll('_', '/').padEnd(Math.ceil(value.length / 4) * 4, '=');
53
+ const binary = atob(base64);
54
+ const bytes = new Uint8Array(binary.length);
55
+ for (let index = 0; index < binary.length; index += 1) {
56
+ bytes[index] = binary.charCodeAt(index);
57
+ }
58
+ return bytes;
59
+ };
60
+ //# sourceMappingURL=state-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-codec.js","sourceRoot":"","sources":["../../src/oauth/state-codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import type { JWK, KeyLike } from 'jose';
2
+ export type OauthTokenType = 'access_token' | 'id_token';
3
+ export interface OauthClientRecord {
4
+ id: string;
5
+ clientId: string;
6
+ clientSecretHash: string | null;
7
+ name: string;
8
+ redirectUris: string[];
9
+ allowedScopes: string[];
10
+ grantTypes: string[];
11
+ responseTypes: string[];
12
+ tokenEndpointAuthMethod: 'client_secret_basic' | 'none' | (string & {});
13
+ dpopBoundAccessTokens: boolean;
14
+ requirePkce: boolean;
15
+ tenantId: string | null;
16
+ ownerUserId: string | null;
17
+ createdAt: Date;
18
+ updatedAt: Date;
19
+ }
20
+ export interface AuthCodePayload {
21
+ clientId: string;
22
+ userId: string;
23
+ tenantId: string | null;
24
+ redirectUri: string;
25
+ scope: string;
26
+ codeChallenge: string;
27
+ codeChallengeMethod: 'S256';
28
+ dpopJkt: string | null;
29
+ nonce: string | null;
30
+ acr: string;
31
+ authTime: Date;
32
+ expiresAt: Date;
33
+ createdAt: Date;
34
+ }
35
+ export interface TokenMeta {
36
+ jti: string;
37
+ tokenType: OauthTokenType;
38
+ clientId: string;
39
+ userId: string;
40
+ tenantId: string | null;
41
+ scope: string;
42
+ audience: string;
43
+ dpopJkt: string | null;
44
+ expiresAt: Date;
45
+ createdAt: Date;
46
+ }
47
+ export interface DpopProofRecord {
48
+ jti: string;
49
+ expiresAt: Date;
50
+ createdAt: Date;
51
+ }
52
+ export interface OauthStateStorePort {
53
+ findClient(clientId: string): Promise<OauthClientRecord | null>;
54
+ saveAuthCode(code: string, payload: AuthCodePayload, ttlSec: number): Promise<void>;
55
+ consumeAuthCode(code: string): Promise<AuthCodePayload | null>;
56
+ saveTokenMeta(jti: string, meta: TokenMeta, ttlSec: number): Promise<void>;
57
+ findTokenMeta(jti: string): Promise<TokenMeta | null>;
58
+ revokeToken(jti: string): Promise<boolean>;
59
+ isTokenRevoked(jti: string): Promise<boolean>;
60
+ recordDpopJti(jti: string, expiresAt: Date): Promise<boolean>;
61
+ purgeExpired(): Promise<number>;
62
+ }
63
+ export type JwksPublicJwk = JWK & {
64
+ alg?: 'EdDSA' | (string & {});
65
+ crv: 'Ed25519' | (string & {});
66
+ kid?: string;
67
+ kty: 'OKP' | (string & {});
68
+ use?: 'sig' | (string & {});
69
+ x: string;
70
+ };
71
+ export interface JwksKeyRecord {
72
+ kid: string;
73
+ alg: 'EdDSA' | (string & {});
74
+ crv: 'Ed25519' | (string & {});
75
+ publicJwk: JwksPublicJwk;
76
+ privateKey?: KeyLike | Uint8Array;
77
+ active: boolean;
78
+ createdAt: Date;
79
+ rotatedAt: Date | null;
80
+ }
81
+ export interface JwksPort {
82
+ getActiveKey(): Promise<JwksKeyRecord | null>;
83
+ findKeyByKid(kid: string): Promise<JwksKeyRecord | null>;
84
+ listPublicKeys(): Promise<JwksKeyRecord[]>;
85
+ }
86
+ //# sourceMappingURL=state-store-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store-types.d.ts","sourceRoot":"","sources":["../../src/oauth/state-store-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=state-store-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store-types.js","sourceRoot":"","sources":["../../src/oauth/state-store-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { Context } from 'hono';
2
+ import type { AuthHonoPorts } from '../ports.js';
3
+ export interface OAuthTokenHandlerOptions {
4
+ accessTokenTtlSeconds?: number;
5
+ dpopIatSkewSeconds?: number;
6
+ idTokenTtlSeconds?: number;
7
+ issuer: string;
8
+ ports: AuthHonoPorts;
9
+ }
10
+ export declare const createOAuthTokenHandler: (options: OAuthTokenHandlerOptions) => (c: Context) => Promise<Response>;
11
+ //# sourceMappingURL=token-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/token-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAOrE,MAAM,WAAW,wBAAwB;IACvC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;CACtB;AAOD,eAAO,MAAM,uBAAuB,YACxB,wBAAwB,SACxB,OAAO,KAAG,QAAQ,QAAQ,CA4BnC,CAAC"}