@geekmidas/auth 0.0.5 → 0.2.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 (117) hide show
  1. package/README.md +343 -214
  2. package/dist/{cacheTokenStorage-Ca05vf3T.mjs → cacheTokenStorage-16NE8Cd9.mjs} +3 -3
  3. package/dist/cacheTokenStorage-16NE8Cd9.mjs.map +1 -0
  4. package/dist/{cacheTokenStorage-BzBRJfd-.d.mts → cacheTokenStorage-B7sOoysu.d.cts} +8 -6
  5. package/dist/cacheTokenStorage-B7sOoysu.d.cts.map +1 -0
  6. package/dist/{cacheTokenStorage-CvptztkW.cjs → cacheTokenStorage-CEpMniTi.cjs} +3 -3
  7. package/dist/cacheTokenStorage-CEpMniTi.cjs.map +1 -0
  8. package/dist/{cacheTokenStorage-yNUpDD8W.d.cts → cacheTokenStorage-_tq4Kmhc.d.mts} +8 -6
  9. package/dist/cacheTokenStorage-_tq4Kmhc.d.mts.map +1 -0
  10. package/dist/cacheTokenStorage.cjs +1 -1
  11. package/dist/cacheTokenStorage.d.cts +1 -1
  12. package/dist/cacheTokenStorage.d.mts +1 -1
  13. package/dist/cacheTokenStorage.mjs +1 -1
  14. package/dist/{client-DaiUm0UZ.cjs → client-BPl_mMvb.cjs} +14 -8
  15. package/dist/client-BPl_mMvb.cjs.map +1 -0
  16. package/dist/{client-DjNZS6vZ.mjs → client-eidYNJSH.mjs} +14 -8
  17. package/dist/client-eidYNJSH.mjs.map +1 -0
  18. package/dist/client.cjs +2 -2
  19. package/dist/client.d.cts +1 -1
  20. package/dist/client.d.mts +1 -1
  21. package/dist/client.mjs +2 -2
  22. package/dist/hono/jwt.cjs +1 -1
  23. package/dist/hono/jwt.cjs.map +1 -1
  24. package/dist/hono/jwt.d.cts +2 -1
  25. package/dist/hono/jwt.d.cts.map +1 -0
  26. package/dist/hono/jwt.d.mts +2 -1
  27. package/dist/hono/jwt.d.mts.map +1 -0
  28. package/dist/hono/jwt.mjs +1 -1
  29. package/dist/hono/jwt.mjs.map +1 -1
  30. package/dist/hono/oidc.cjs +1 -1
  31. package/dist/hono/oidc.cjs.map +1 -1
  32. package/dist/hono/oidc.d.cts +3 -2
  33. package/dist/hono/oidc.d.cts.map +1 -0
  34. package/dist/hono/oidc.d.mts +3 -2
  35. package/dist/hono/oidc.d.mts.map +1 -0
  36. package/dist/hono/oidc.mjs +1 -1
  37. package/dist/hono/oidc.mjs.map +1 -1
  38. package/dist/index.cjs +3 -3
  39. package/dist/index.d.cts +2 -2
  40. package/dist/index.d.mts +2 -2
  41. package/dist/index.mjs +3 -3
  42. package/dist/{jwt-DF9kFbmh.d.cts → jwt-3eIuY2dg.d.cts} +2 -1
  43. package/dist/jwt-3eIuY2dg.d.cts.map +1 -0
  44. package/dist/jwt-Bo_eACEi.cjs.map +1 -1
  45. package/dist/{jwt-DH8CJ2xC.d.mts → jwt-BqLlRkw-.d.mts} +2 -1
  46. package/dist/jwt-BqLlRkw-.d.mts.map +1 -0
  47. package/dist/jwt-D88cPJyT.mjs.map +1 -1
  48. package/dist/jwt.d.cts +1 -1
  49. package/dist/jwt.d.mts +1 -1
  50. package/dist/lambda/jwt.cjs +2 -2
  51. package/dist/lambda/jwt.cjs.map +1 -1
  52. package/dist/lambda/jwt.d.cts +2 -1
  53. package/dist/lambda/jwt.d.cts.map +1 -0
  54. package/dist/lambda/jwt.d.mts +2 -1
  55. package/dist/lambda/jwt.d.mts.map +1 -0
  56. package/dist/lambda/jwt.mjs +2 -2
  57. package/dist/lambda/jwt.mjs.map +1 -1
  58. package/dist/lambda/oidc.cjs +2 -2
  59. package/dist/lambda/oidc.cjs.map +1 -1
  60. package/dist/lambda/oidc.d.cts +3 -2
  61. package/dist/lambda/oidc.d.cts.map +1 -0
  62. package/dist/lambda/oidc.d.mts +3 -2
  63. package/dist/lambda/oidc.d.mts.map +1 -0
  64. package/dist/lambda/oidc.mjs +2 -2
  65. package/dist/lambda/oidc.mjs.map +1 -1
  66. package/dist/oidc-C0KyYaAK.cjs.map +1 -1
  67. package/dist/{oidc-CKOGLxjV.d.mts → oidc-ChA17wLB.d.cts} +3 -2
  68. package/dist/oidc-ChA17wLB.d.cts.map +1 -0
  69. package/dist/{oidc-DDLIB5gb.d.cts → oidc-DTRgBBl6.d.mts} +3 -2
  70. package/dist/oidc-DTRgBBl6.d.mts.map +1 -0
  71. package/dist/oidc-KA30gMlx.mjs.map +1 -1
  72. package/dist/oidc.d.cts +2 -2
  73. package/dist/oidc.d.mts +2 -2
  74. package/dist/server.cjs +2 -2
  75. package/dist/server.d.cts +2 -2
  76. package/dist/server.d.mts +2 -2
  77. package/dist/server.mjs +2 -2
  78. package/dist/{tokenManager--Q93eNYr.d.mts → tokenManager-CL3yE06D.d.cts} +2 -1
  79. package/dist/tokenManager-CL3yE06D.d.cts.map +1 -0
  80. package/dist/{tokenManager-BVXxfHRa.mjs → tokenManager-Ci2Tgxp8.mjs} +5 -3
  81. package/dist/tokenManager-Ci2Tgxp8.mjs.map +1 -0
  82. package/dist/{tokenManager-EPmwgai2.cjs → tokenManager-CvEMgxOp.cjs} +5 -3
  83. package/dist/tokenManager-CvEMgxOp.cjs.map +1 -0
  84. package/dist/{tokenManager-H6-lWEah.d.cts → tokenManager-RrwjL0y-.d.mts} +2 -1
  85. package/dist/tokenManager-RrwjL0y-.d.mts.map +1 -0
  86. package/dist/tokenManager.cjs +1 -1
  87. package/dist/tokenManager.d.cts +1 -1
  88. package/dist/tokenManager.d.mts +1 -1
  89. package/dist/tokenManager.mjs +1 -1
  90. package/package.json +10 -5
  91. package/src/__tests__/cacheTokenStorage.spec.ts +148 -148
  92. package/src/__tests__/client.spec.ts +339 -339
  93. package/src/__tests__/hono-jwt.spec.ts +219 -219
  94. package/src/__tests__/hono-oidc.spec.ts +560 -560
  95. package/src/__tests__/jwt.spec.ts +150 -127
  96. package/src/__tests__/lambda-jwt.spec.ts +205 -205
  97. package/src/__tests__/lambda-oidc.spec.ts +580 -579
  98. package/src/__tests__/oidc.spec.ts +365 -365
  99. package/src/__tests__/tokenManager.spec.ts +254 -254
  100. package/src/cacheTokenStorage.ts +32 -32
  101. package/src/client.ts +199 -190
  102. package/src/hono/jwt.ts +111 -111
  103. package/src/hono/oidc.ts +131 -131
  104. package/src/index.ts +2 -2
  105. package/src/jwt.ts +57 -57
  106. package/src/lambda/jwt.ts +170 -170
  107. package/src/lambda/oidc.ts +165 -165
  108. package/src/oidc.ts +121 -121
  109. package/src/server.ts +6 -7
  110. package/src/tokenManager.ts +89 -87
  111. package/tsconfig.json +10 -0
  112. package/dist/cacheTokenStorage-Ca05vf3T.mjs.map +0 -1
  113. package/dist/cacheTokenStorage-CvptztkW.cjs.map +0 -1
  114. package/dist/client-DaiUm0UZ.cjs.map +0 -1
  115. package/dist/client-DjNZS6vZ.mjs.map +0 -1
  116. package/dist/tokenManager-BVXxfHRa.mjs.map +0 -1
  117. package/dist/tokenManager-EPmwgai2.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"oidc.mjs","names":["c: Context","options: TokenExtractionOptions","options: OidcMiddlewareOptions<TClaims, TUserInfo>","next: Next","userInfo: TUserInfo | undefined"],"sources":["../../src/hono/oidc.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport {\n type OidcClaims,\n type OidcConfig,\n type OidcUserInfo,\n OidcVerifier,\n type TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n OidcVerifier,\n type OidcClaims,\n type OidcConfig,\n type OidcUserInfo,\n type TokenExtractionOptions,\n};\n\nfunction extractToken(\n c: Context,\n options: TokenExtractionOptions = {},\n): string | null {\n const {\n headerName = 'authorization',\n cookieName,\n tokenPrefix = 'Bearer ',\n } = options;\n\n const headerValue = c.req.header(headerName);\n if (headerValue) {\n if (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n return headerValue.slice(tokenPrefix.length);\n }\n return headerValue;\n }\n\n if (cookieName) {\n const cookieHeader = c.req.header('cookie');\n if (cookieHeader) {\n const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n if (match) {\n return match[1];\n }\n }\n }\n\n return null;\n}\n\nexport interface OidcMiddlewareOptions<\n TClaims extends OidcClaims = OidcClaims,\n TUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n config: OidcConfig;\n extraction?: TokenExtractionOptions;\n contextKey?: string;\n fetchUserInfo?: boolean;\n onError?: (c: Context, error: Error) => Response | Promise<Response>;\n transformClaims?: (claims: OidcClaims, userInfo?: TUserInfo) => TClaims;\n}\n\n/**\n * OIDC Middleware for Hono\n *\n * @example\n * ```typescript\n * const oidc = new OidcMiddleware({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-client-id',\n * },\n * });\n *\n * app.use('/api/*', oidc.handler());\n *\n * // With user info\n * const oidcWithUserInfo = new OidcMiddleware({\n * config: { issuer: '...', audience: '...' },\n * fetchUserInfo: true,\n * });\n * ```\n */\nexport class OidcMiddleware<\n TClaims extends OidcClaims = OidcClaims,\n TUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n private readonly verifier: OidcVerifier<TClaims, TUserInfo>;\n private readonly extraction: TokenExtractionOptions;\n private readonly contextKey: string;\n private readonly fetchUserInfo: boolean;\n private readonly onError?: (\n c: Context,\n error: Error,\n ) => Response | Promise<Response>;\n private readonly transformClaims?: (\n claims: OidcClaims,\n userInfo?: TUserInfo,\n ) => TClaims;\n\n constructor(options: OidcMiddlewareOptions<TClaims, TUserInfo>) {\n this.verifier = new OidcVerifier(options.config);\n this.extraction = options.extraction ?? {};\n this.contextKey = options.contextKey ?? 'oidcClaims';\n this.fetchUserInfo = options.fetchUserInfo ?? false;\n this.onError = options.onError;\n this.transformClaims = options.transformClaims;\n }\n\n handler(): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const token = extractToken(c, this.extraction);\n\n if (!token) {\n if (this.onError) {\n return this.onError(c, new Error('No token provided'));\n }\n return c.json({ error: 'Unauthorized' }, 401);\n }\n\n try {\n const payload = await this.verifier.verify(token);\n\n let userInfo: TUserInfo | undefined;\n if (this.fetchUserInfo) {\n userInfo = (await this.verifier.fetchUserInfo(token)) ?? undefined;\n c.set('oidcUserInfo', userInfo);\n }\n\n const claims = this.transformClaims\n ? this.transformClaims(payload, userInfo)\n : payload;\n\n c.set(this.contextKey, claims);\n c.set('oidcToken', token);\n\n await next();\n } catch (error) {\n if (this.onError) {\n return this.onError(c, error as Error);\n }\n return c.json({ error: 'Invalid token' }, 401);\n }\n };\n }\n\n optional(): MiddlewareHandler {\n return async (c: Context, next: Next) => {\n const token = extractToken(c, this.extraction);\n\n if (token) {\n const payload = await this.verifier.verifyOrNull(token);\n if (payload) {\n let userInfo: TUserInfo | undefined;\n if (this.fetchUserInfo) {\n userInfo = (await this.verifier.fetchUserInfo(token)) ?? undefined;\n c.set('oidcUserInfo', userInfo);\n }\n\n const claims = this.transformClaims\n ? this.transformClaims(payload, userInfo)\n : payload;\n\n c.set(this.contextKey, claims);\n c.set('oidcToken', token);\n }\n }\n\n await next();\n };\n }\n}\n"],"mappings":";;;AAiBA,SAAS,aACPA,GACAC,UAAkC,CAAE,GACrB;CACf,MAAM,EACJ,aAAa,iBACb,YACA,cAAc,WACf,GAAG;CAEJ,MAAM,cAAc,EAAE,IAAI,OAAO,WAAW;AAC5C,KAAI,aAAa;AACf,MAAI,eAAe,YAAY,WAAW,YAAY,CACpD,QAAO,YAAY,MAAM,YAAY,OAAO;AAE9C,SAAO;CACR;AAED,KAAI,YAAY;EACd,MAAM,eAAe,EAAE,IAAI,OAAO,SAAS;AAC3C,MAAI,cAAc;GAChB,MAAM,QAAQ,aAAa,MAAM,IAAI,QAAQ,EAAE,WAAW,WAAW;AACrE,OAAI,MACF,QAAO,MAAM;EAEhB;CACF;AAED,QAAO;AACR;;;;;;;;;;;;;;;;;;;;;;AAmCD,IAAa,iBAAb,MAGE;CACA,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAIjB,AAAiB;CAKjB,YAAYC,SAAoD;AAC9D,OAAK,WAAW,IAAI,aAAa,QAAQ;AACzC,OAAK,aAAa,QAAQ,cAAc,CAAE;AAC1C,OAAK,aAAa,QAAQ,cAAc;AACxC,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU,QAAQ;AACvB,OAAK,kBAAkB,QAAQ;CAChC;CAED,UAA6B;AAC3B,SAAO,OAAOF,GAAYG,SAAe;GACvC,MAAM,QAAQ,aAAa,GAAG,KAAK,WAAW;AAE9C,QAAK,OAAO;AACV,QAAI,KAAK,QACP,QAAO,KAAK,QAAQ,GAAG,IAAI,MAAM,qBAAqB;AAExD,WAAO,EAAE,KAAK,EAAE,OAAO,eAAgB,GAAE,IAAI;GAC9C;AAED,OAAI;IACF,MAAM,UAAU,MAAM,KAAK,SAAS,OAAO,MAAM;IAEjD,IAAIC;AACJ,QAAI,KAAK,eAAe;AACtB,gBAAY,MAAM,KAAK,SAAS,cAAc,MAAM;AACpD,OAAE,IAAI,gBAAgB,SAAS;IAChC;IAED,MAAM,SAAS,KAAK,kBAChB,KAAK,gBAAgB,SAAS,SAAS,GACvC;AAEJ,MAAE,IAAI,KAAK,YAAY,OAAO;AAC9B,MAAE,IAAI,aAAa,MAAM;AAEzB,UAAM,MAAM;GACb,SAAQ,OAAO;AACd,QAAI,KAAK,QACP,QAAO,KAAK,QAAQ,GAAG,MAAe;AAExC,WAAO,EAAE,KAAK,EAAE,OAAO,gBAAiB,GAAE,IAAI;GAC/C;EACF;CACF;CAED,WAA8B;AAC5B,SAAO,OAAOJ,GAAYG,SAAe;GACvC,MAAM,QAAQ,aAAa,GAAG,KAAK,WAAW;AAE9C,OAAI,OAAO;IACT,MAAM,UAAU,MAAM,KAAK,SAAS,aAAa,MAAM;AACvD,QAAI,SAAS;KACX,IAAIC;AACJ,SAAI,KAAK,eAAe;AACtB,iBAAY,MAAM,KAAK,SAAS,cAAc,MAAM;AACpD,QAAE,IAAI,gBAAgB,SAAS;KAChC;KAED,MAAM,SAAS,KAAK,kBAChB,KAAK,gBAAgB,SAAS,SAAS,GACvC;AAEJ,OAAE,IAAI,KAAK,YAAY,OAAO;AAC9B,OAAE,IAAI,aAAa,MAAM;IAC1B;GACF;AAED,SAAM,MAAM;EACb;CACF;AACF"}
1
+ {"version":3,"file":"oidc.mjs","names":["c: Context","options: TokenExtractionOptions","options: OidcMiddlewareOptions<TClaims, TUserInfo>","next: Next","userInfo: TUserInfo | undefined"],"sources":["../../src/hono/oidc.ts"],"sourcesContent":["import type { Context, MiddlewareHandler, Next } from 'hono';\nimport {\n\ttype OidcClaims,\n\ttype OidcConfig,\n\ttype OidcUserInfo,\n\tOidcVerifier,\n\ttype TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n\tOidcVerifier,\n\ttype OidcClaims,\n\ttype OidcConfig,\n\ttype OidcUserInfo,\n\ttype TokenExtractionOptions,\n};\n\nfunction extractToken(\n\tc: Context,\n\toptions: TokenExtractionOptions = {},\n): string | null {\n\tconst {\n\t\theaderName = 'authorization',\n\t\tcookieName,\n\t\ttokenPrefix = 'Bearer ',\n\t} = options;\n\n\tconst headerValue = c.req.header(headerName);\n\tif (headerValue) {\n\t\tif (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n\t\t\treturn headerValue.slice(tokenPrefix.length);\n\t\t}\n\t\treturn headerValue;\n\t}\n\n\tif (cookieName) {\n\t\tconst cookieHeader = c.req.header('cookie');\n\t\tif (cookieHeader) {\n\t\t\tconst match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n\t\t\tif (match?.[1]) {\n\t\t\t\treturn match[1];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport interface OidcMiddlewareOptions<\n\tTClaims extends OidcClaims = OidcClaims,\n\tTUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n\tconfig: OidcConfig;\n\textraction?: TokenExtractionOptions;\n\tcontextKey?: string;\n\tfetchUserInfo?: boolean;\n\tonError?: (c: Context, error: Error) => Response | Promise<Response>;\n\ttransformClaims?: (claims: OidcClaims, userInfo?: TUserInfo) => TClaims;\n}\n\n/**\n * OIDC Middleware for Hono\n *\n * @example\n * ```typescript\n * const oidc = new OidcMiddleware({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-client-id',\n * },\n * });\n *\n * app.use('/api/*', oidc.handler());\n *\n * // With user info\n * const oidcWithUserInfo = new OidcMiddleware({\n * config: { issuer: '...', audience: '...' },\n * fetchUserInfo: true,\n * });\n * ```\n */\nexport class OidcMiddleware<\n\tTClaims extends OidcClaims = OidcClaims,\n\tTUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n\tprivate readonly verifier: OidcVerifier<TClaims, TUserInfo>;\n\tprivate readonly extraction: TokenExtractionOptions;\n\tprivate readonly contextKey: string;\n\tprivate readonly fetchUserInfo: boolean;\n\tprivate readonly onError?: (\n\t\tc: Context,\n\t\terror: Error,\n\t) => Response | Promise<Response>;\n\tprivate readonly transformClaims?: (\n\t\tclaims: OidcClaims,\n\t\tuserInfo?: TUserInfo,\n\t) => TClaims;\n\n\tconstructor(options: OidcMiddlewareOptions<TClaims, TUserInfo>) {\n\t\tthis.verifier = new OidcVerifier(options.config);\n\t\tthis.extraction = options.extraction ?? {};\n\t\tthis.contextKey = options.contextKey ?? 'oidcClaims';\n\t\tthis.fetchUserInfo = options.fetchUserInfo ?? false;\n\t\tthis.onError = options.onError;\n\t\tthis.transformClaims = options.transformClaims;\n\t}\n\n\thandler(): MiddlewareHandler {\n\t\treturn async (c: Context, next: Next) => {\n\t\t\tconst token = extractToken(c, this.extraction);\n\n\t\t\tif (!token) {\n\t\t\t\tif (this.onError) {\n\t\t\t\t\treturn this.onError(c, new Error('No token provided'));\n\t\t\t\t}\n\t\t\t\treturn c.json({ error: 'Unauthorized' }, 401);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst payload = await this.verifier.verify(token);\n\n\t\t\t\tlet userInfo: TUserInfo | undefined;\n\t\t\t\tif (this.fetchUserInfo) {\n\t\t\t\t\tuserInfo = (await this.verifier.fetchUserInfo(token)) ?? undefined;\n\t\t\t\t\tc.set('oidcUserInfo', userInfo);\n\t\t\t\t}\n\n\t\t\t\tconst claims = this.transformClaims\n\t\t\t\t\t? this.transformClaims(payload, userInfo)\n\t\t\t\t\t: payload;\n\n\t\t\t\tc.set(this.contextKey, claims);\n\t\t\t\tc.set('oidcToken', token);\n\n\t\t\t\tawait next();\n\t\t\t} catch (error) {\n\t\t\t\tif (this.onError) {\n\t\t\t\t\treturn this.onError(c, error as Error);\n\t\t\t\t}\n\t\t\t\treturn c.json({ error: 'Invalid token' }, 401);\n\t\t\t}\n\t\t};\n\t}\n\n\toptional(): MiddlewareHandler {\n\t\treturn async (c: Context, next: Next) => {\n\t\t\tconst token = extractToken(c, this.extraction);\n\n\t\t\tif (token) {\n\t\t\t\tconst payload = await this.verifier.verifyOrNull(token);\n\t\t\t\tif (payload) {\n\t\t\t\t\tlet userInfo: TUserInfo | undefined;\n\t\t\t\t\tif (this.fetchUserInfo) {\n\t\t\t\t\t\tuserInfo = (await this.verifier.fetchUserInfo(token)) ?? undefined;\n\t\t\t\t\t\tc.set('oidcUserInfo', userInfo);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst claims = this.transformClaims\n\t\t\t\t\t\t? this.transformClaims(payload, userInfo)\n\t\t\t\t\t\t: payload;\n\n\t\t\t\t\tc.set(this.contextKey, claims);\n\t\t\t\t\tc.set('oidcToken', token);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait next();\n\t\t};\n\t}\n}\n"],"mappings":";;;AAiBA,SAAS,aACRA,GACAC,UAAkC,CAAE,GACpB;CAChB,MAAM,EACL,aAAa,iBACb,YACA,cAAc,WACd,GAAG;CAEJ,MAAM,cAAc,EAAE,IAAI,OAAO,WAAW;AAC5C,KAAI,aAAa;AAChB,MAAI,eAAe,YAAY,WAAW,YAAY,CACrD,QAAO,YAAY,MAAM,YAAY,OAAO;AAE7C,SAAO;CACP;AAED,KAAI,YAAY;EACf,MAAM,eAAe,EAAE,IAAI,OAAO,SAAS;AAC3C,MAAI,cAAc;GACjB,MAAM,QAAQ,aAAa,MAAM,IAAI,QAAQ,EAAE,WAAW,WAAW;AACrE,OAAI,QAAQ,GACX,QAAO,MAAM;EAEd;CACD;AAED,QAAO;AACP;;;;;;;;;;;;;;;;;;;;;;AAmCD,IAAa,iBAAb,MAGE;CACD,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAIjB,AAAiB;CAKjB,YAAYC,SAAoD;AAC/D,OAAK,WAAW,IAAI,aAAa,QAAQ;AACzC,OAAK,aAAa,QAAQ,cAAc,CAAE;AAC1C,OAAK,aAAa,QAAQ,cAAc;AACxC,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU,QAAQ;AACvB,OAAK,kBAAkB,QAAQ;CAC/B;CAED,UAA6B;AAC5B,SAAO,OAAOF,GAAYG,SAAe;GACxC,MAAM,QAAQ,aAAa,GAAG,KAAK,WAAW;AAE9C,QAAK,OAAO;AACX,QAAI,KAAK,QACR,QAAO,KAAK,QAAQ,GAAG,IAAI,MAAM,qBAAqB;AAEvD,WAAO,EAAE,KAAK,EAAE,OAAO,eAAgB,GAAE,IAAI;GAC7C;AAED,OAAI;IACH,MAAM,UAAU,MAAM,KAAK,SAAS,OAAO,MAAM;IAEjD,IAAIC;AACJ,QAAI,KAAK,eAAe;AACvB,gBAAY,MAAM,KAAK,SAAS,cAAc,MAAM;AACpD,OAAE,IAAI,gBAAgB,SAAS;IAC/B;IAED,MAAM,SAAS,KAAK,kBACjB,KAAK,gBAAgB,SAAS,SAAS,GACvC;AAEH,MAAE,IAAI,KAAK,YAAY,OAAO;AAC9B,MAAE,IAAI,aAAa,MAAM;AAEzB,UAAM,MAAM;GACZ,SAAQ,OAAO;AACf,QAAI,KAAK,QACR,QAAO,KAAK,QAAQ,GAAG,MAAe;AAEvC,WAAO,EAAE,KAAK,EAAE,OAAO,gBAAiB,GAAE,IAAI;GAC9C;EACD;CACD;CAED,WAA8B;AAC7B,SAAO,OAAOJ,GAAYG,SAAe;GACxC,MAAM,QAAQ,aAAa,GAAG,KAAK,WAAW;AAE9C,OAAI,OAAO;IACV,MAAM,UAAU,MAAM,KAAK,SAAS,aAAa,MAAM;AACvD,QAAI,SAAS;KACZ,IAAIC;AACJ,SAAI,KAAK,eAAe;AACvB,iBAAY,MAAM,KAAK,SAAS,cAAc,MAAM;AACpD,QAAE,IAAI,gBAAgB,SAAS;KAC/B;KAED,MAAM,SAAS,KAAK,kBACjB,KAAK,gBAAgB,SAAS,SAAS,GACvC;AAEH,OAAE,IAAI,KAAK,YAAY,OAAO;AAC9B,OAAE,IAAI,aAAa,MAAM;IACzB;GACD;AAED,SAAM,MAAM;EACZ;CACD;AACD"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
- const require_cacheTokenStorage = require('./cacheTokenStorage-CvptztkW.cjs');
2
- const require_client = require('./client-DaiUm0UZ.cjs');
3
- const require_tokenManager = require('./tokenManager-EPmwgai2.cjs');
1
+ const require_cacheTokenStorage = require('./cacheTokenStorage-CEpMniTi.cjs');
2
+ const require_client = require('./client-BPl_mMvb.cjs');
3
+ const require_tokenManager = require('./tokenManager-CvEMgxOp.cjs');
4
4
 
5
5
  exports.CacheTokenStorage = require_cacheTokenStorage.CacheTokenStorage;
6
6
  exports.LocalStorageTokenStorage = require_client.LocalStorageTokenStorage;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import { CacheTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenStorage } from "./cacheTokenStorage-yNUpDD8W.cjs";
2
- import { DecodedToken, TokenManager, TokenManagerOptions, TokenPair, TokenPayload } from "./tokenManager-H6-lWEah.cjs";
1
+ import { CacheTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenStorage } from "./cacheTokenStorage-B7sOoysu.cjs";
2
+ import { DecodedToken, TokenManager, TokenManagerOptions, TokenPair, TokenPayload } from "./tokenManager-CL3yE06D.cjs";
3
3
  export { CacheTokenStorage, DecodedToken, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenManager, TokenManagerOptions, TokenPair, TokenPayload, TokenStorage };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { CacheTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenStorage } from "./cacheTokenStorage-BzBRJfd-.mjs";
2
- import { DecodedToken, TokenManager, TokenManagerOptions, TokenPair, TokenPayload } from "./tokenManager--Q93eNYr.mjs";
1
+ import { CacheTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenStorage } from "./cacheTokenStorage-_tq4Kmhc.mjs";
2
+ import { DecodedToken, TokenManager, TokenManagerOptions, TokenPair, TokenPayload } from "./tokenManager-RrwjL0y-.mjs";
3
3
  export { CacheTokenStorage, DecodedToken, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenClientOptions, TokenManager, TokenManagerOptions, TokenPair, TokenPayload, TokenStorage };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { CacheTokenStorage } from "./cacheTokenStorage-Ca05vf3T.mjs";
2
- import { LocalStorageTokenStorage, MemoryTokenStorage, TokenClient } from "./client-DjNZS6vZ.mjs";
3
- import { TokenManager } from "./tokenManager-BVXxfHRa.mjs";
1
+ import { CacheTokenStorage } from "./cacheTokenStorage-16NE8Cd9.mjs";
2
+ import { LocalStorageTokenStorage, MemoryTokenStorage, TokenClient } from "./client-eidYNJSH.mjs";
3
+ import { TokenManager } from "./tokenManager-Ci2Tgxp8.mjs";
4
4
 
5
5
  export { CacheTokenStorage, LocalStorageTokenStorage, MemoryTokenStorage, TokenClient, TokenManager };
@@ -56,6 +56,7 @@ declare class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {
56
56
  * WARNING: This does NOT verify the token signature!
57
57
  */
58
58
  declare function decodeJwt<TClaims extends JwtClaims = JwtClaims>(token: string): TClaims;
59
+ //# sourceMappingURL=jwt.d.ts.map
59
60
  //#endregion
60
61
  export { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig };
61
- //# sourceMappingURL=jwt-DF9kFbmh.d.cts.map
62
+ //# sourceMappingURL=jwt-3eIuY2dg.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-3eIuY2dg.d.cts","names":[],"sources":["../src/jwt.ts"],"sourcesContent":[],"mappings":";;AAKA;AAaA;AAUiB,UAvBA,SAAA,CAuBa;EAOlB,GAAA,CAAA,EAAA,MAAS;EAAA,GAAA,CAAA,EAAA,MAAA;EAAA,GAAG,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAe,GAAG,CAAA,EAAA,MAAA;EAAa,GAAA,CAAA,EAAA,MAAA;EAKtC,GAAA,CAAA,EAAA,MAAA;EAMD,GAAA,CAAA,EAAA,MAAA;;;;AAAwD;AAO3D,UAnCI,eAAA,CAmCO;EAAA,MAAA,EAAA,MAAA;EAAA,MAAiB,CAAA,EAAA,MAAA;EAAS,QAAG,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAS,UAIxB,CAAA,EAAA,MAAA,EAAA;;;;;AA2BK,UAxD1B,aAAA,CAwD0B;EAiB3B,OAAA,EAAA,MAAS;EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,QAAiB,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAS,UAAG,CAAA,EAAA,MAAA,EAAA;;AAE5C,KApEE,SAAA,GAAY,eAoEd,GApEgC,aAoEhC;;;;UA/DO,sBAAA;;;;;iBAMD,YAAA,SAAqB,sBAAsB;;;;cAO9C,4BAA4B,YAAY;;;;sBAIf;yBASR,QAAQ;+BAkBF,QAAQ;;;;;;;iBAiB5B,0BAA0B,YAAY,2BAEnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-Bo_eACEi.cjs","names":["config: JwtConfig","token: string","payload"],"sources":["../src/jwt.ts"],"sourcesContent":["import * as jose from 'jose';\n\n/**\n * Standard JWT claims\n */\nexport interface JwtClaims {\n sub?: string;\n iss?: string;\n aud?: string | string[];\n exp?: number;\n iat?: number;\n nbf?: number;\n jti?: string;\n}\n\n/**\n * Configuration for JWT verification with a symmetric secret\n */\nexport interface JwtSecretConfig {\n secret: string;\n issuer?: string;\n audience?: string | string[];\n algorithms?: string[];\n}\n\n/**\n * Configuration for JWT verification with JWKS\n */\nexport interface JwtJwksConfig {\n jwksUri: string;\n issuer?: string;\n audience?: string | string[];\n algorithms?: string[];\n}\n\nexport type JwtConfig = JwtSecretConfig | JwtJwksConfig;\n\n/**\n * Options for token extraction from requests\n */\nexport interface TokenExtractionOptions {\n headerName?: string;\n cookieName?: string;\n tokenPrefix?: string;\n}\n\nexport function isJwksConfig(config: JwtConfig): config is JwtJwksConfig {\n return 'jwksUri' in config;\n}\n\n/**\n * JWT Verifier with JWKS caching\n */\nexport class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {\n private jwks: jose.JWTVerifyGetKey | null = null;\n private readonly verifyOptions: jose.JWTVerifyOptions;\n\n constructor(private readonly config: JwtConfig) {\n this.verifyOptions = {\n issuer: config.issuer,\n audience: config.audience,\n algorithms:\n config.algorithms ?? (isJwksConfig(config) ? undefined : ['HS256']),\n };\n }\n\n async verify(token: string): Promise<TClaims> {\n if (isJwksConfig(this.config)) {\n if (!this.jwks) {\n this.jwks = jose.createRemoteJWKSet(new URL(this.config.jwksUri));\n }\n const { payload } = await jose.jwtVerify(\n token,\n this.jwks,\n this.verifyOptions,\n );\n return payload as unknown as TClaims;\n }\n\n const secret = new TextEncoder().encode(this.config.secret);\n const { payload } = await jose.jwtVerify(token, secret, this.verifyOptions);\n return payload as unknown as TClaims;\n }\n\n async verifyOrNull(token: string): Promise<TClaims | null> {\n try {\n return await this.verify(token);\n } catch {\n return null;\n }\n }\n\n clearCache(): void {\n this.jwks = null;\n }\n}\n\n/**\n * Decode a JWT without verification\n * WARNING: This does NOT verify the token signature!\n */\nexport function decodeJwt<TClaims extends JwtClaims = JwtClaims>(\n token: string,\n): TClaims {\n return jose.decodeJwt(token) as unknown as TClaims;\n}\n"],"mappings":";;;;AA8CA,SAAgB,aAAaA,QAA4C;AACvE,QAAO,aAAa;AACrB;;;;AAKD,IAAa,cAAb,MAAgE;CAC9D,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAmB;EAAnB;AAC3B,OAAK,gBAAgB;GACnB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,YACE,OAAO,eAAe,aAAa,OAAO,YAAe,CAAC,OAAQ;EACrE;CACF;CAED,MAAM,OAAOC,OAAiC;AAC5C,MAAI,aAAa,KAAK,OAAO,EAAE;AAC7B,QAAK,KAAK,KACR,MAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,OAAO,SAAS;GAEnE,MAAM,EAAE,oBAAS,GAAG,MAAM,KAAK,UAC7B,OACA,KAAK,MACL,KAAK,cACN;AACD,UAAOC;EACR;EAED,MAAM,SAAS,IAAI,cAAc,OAAO,KAAK,OAAO,OAAO;EAC3D,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK,cAAc;AAC3E,SAAO;CACR;CAED,MAAM,aAAaD,OAAwC;AACzD,MAAI;AACF,UAAO,MAAM,KAAK,OAAO,MAAM;EAChC,QAAO;AACN,UAAO;EACR;CACF;CAED,aAAmB;AACjB,OAAK,OAAO;CACb;AACF;;;;;AAMD,SAAgB,UACdA,OACS;AACT,QAAO,KAAK,UAAU,MAAM;AAC7B"}
1
+ {"version":3,"file":"jwt-Bo_eACEi.cjs","names":["config: JwtConfig","token: string","payload"],"sources":["../src/jwt.ts"],"sourcesContent":["import * as jose from 'jose';\n\n/**\n * Standard JWT claims\n */\nexport interface JwtClaims {\n\tsub?: string;\n\tiss?: string;\n\taud?: string | string[];\n\texp?: number;\n\tiat?: number;\n\tnbf?: number;\n\tjti?: string;\n}\n\n/**\n * Configuration for JWT verification with a symmetric secret\n */\nexport interface JwtSecretConfig {\n\tsecret: string;\n\tissuer?: string;\n\taudience?: string | string[];\n\talgorithms?: string[];\n}\n\n/**\n * Configuration for JWT verification with JWKS\n */\nexport interface JwtJwksConfig {\n\tjwksUri: string;\n\tissuer?: string;\n\taudience?: string | string[];\n\talgorithms?: string[];\n}\n\nexport type JwtConfig = JwtSecretConfig | JwtJwksConfig;\n\n/**\n * Options for token extraction from requests\n */\nexport interface TokenExtractionOptions {\n\theaderName?: string;\n\tcookieName?: string;\n\ttokenPrefix?: string;\n}\n\nexport function isJwksConfig(config: JwtConfig): config is JwtJwksConfig {\n\treturn 'jwksUri' in config;\n}\n\n/**\n * JWT Verifier with JWKS caching\n */\nexport class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {\n\tprivate jwks: jose.JWTVerifyGetKey | null = null;\n\tprivate readonly verifyOptions: jose.JWTVerifyOptions;\n\n\tconstructor(private readonly config: JwtConfig) {\n\t\tthis.verifyOptions = {\n\t\t\tissuer: config.issuer,\n\t\t\taudience: config.audience,\n\t\t\talgorithms:\n\t\t\t\tconfig.algorithms ?? (isJwksConfig(config) ? undefined : ['HS256']),\n\t\t};\n\t}\n\n\tasync verify(token: string): Promise<TClaims> {\n\t\tif (isJwksConfig(this.config)) {\n\t\t\tif (!this.jwks) {\n\t\t\t\tthis.jwks = jose.createRemoteJWKSet(new URL(this.config.jwksUri));\n\t\t\t}\n\t\t\tconst { payload } = await jose.jwtVerify(\n\t\t\t\ttoken,\n\t\t\t\tthis.jwks,\n\t\t\t\tthis.verifyOptions,\n\t\t\t);\n\t\t\treturn payload as unknown as TClaims;\n\t\t}\n\n\t\tconst secret = new TextEncoder().encode(this.config.secret);\n\t\tconst { payload } = await jose.jwtVerify(token, secret, this.verifyOptions);\n\t\treturn payload as unknown as TClaims;\n\t}\n\n\tasync verifyOrNull(token: string): Promise<TClaims | null> {\n\t\ttry {\n\t\t\treturn await this.verify(token);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tclearCache(): void {\n\t\tthis.jwks = null;\n\t}\n}\n\n/**\n * Decode a JWT without verification\n * WARNING: This does NOT verify the token signature!\n */\nexport function decodeJwt<TClaims extends JwtClaims = JwtClaims>(\n\ttoken: string,\n): TClaims {\n\treturn jose.decodeJwt(token) as unknown as TClaims;\n}\n"],"mappings":";;;;AA8CA,SAAgB,aAAaA,QAA4C;AACxE,QAAO,aAAa;AACpB;;;;AAKD,IAAa,cAAb,MAAgE;CAC/D,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAmB;EAAnB;AAC5B,OAAK,gBAAgB;GACpB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,YACC,OAAO,eAAe,aAAa,OAAO,YAAe,CAAC,OAAQ;EACnE;CACD;CAED,MAAM,OAAOC,OAAiC;AAC7C,MAAI,aAAa,KAAK,OAAO,EAAE;AAC9B,QAAK,KAAK,KACT,MAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,OAAO,SAAS;GAElE,MAAM,EAAE,oBAAS,GAAG,MAAM,KAAK,UAC9B,OACA,KAAK,MACL,KAAK,cACL;AACD,UAAOC;EACP;EAED,MAAM,SAAS,IAAI,cAAc,OAAO,KAAK,OAAO,OAAO;EAC3D,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK,cAAc;AAC3E,SAAO;CACP;CAED,MAAM,aAAaD,OAAwC;AAC1D,MAAI;AACH,UAAO,MAAM,KAAK,OAAO,MAAM;EAC/B,QAAO;AACP,UAAO;EACP;CACD;CAED,aAAmB;AAClB,OAAK,OAAO;CACZ;AACD;;;;;AAMD,SAAgB,UACfA,OACU;AACV,QAAO,KAAK,UAAU,MAAM;AAC5B"}
@@ -56,6 +56,7 @@ declare class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {
56
56
  * WARNING: This does NOT verify the token signature!
57
57
  */
58
58
  declare function decodeJwt<TClaims extends JwtClaims = JwtClaims>(token: string): TClaims;
59
+ //# sourceMappingURL=jwt.d.ts.map
59
60
  //#endregion
60
61
  export { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig };
61
- //# sourceMappingURL=jwt-DH8CJ2xC.d.mts.map
62
+ //# sourceMappingURL=jwt-BqLlRkw-.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-BqLlRkw-.d.mts","names":[],"sources":["../src/jwt.ts"],"sourcesContent":[],"mappings":";;AAKA;AAaA;AAUiB,UAvBA,SAAA,CAuBa;EAOlB,GAAA,CAAA,EAAA,MAAS;EAAA,GAAA,CAAA,EAAA,MAAA;EAAA,GAAG,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAe,GAAG,CAAA,EAAA,MAAA;EAAa,GAAA,CAAA,EAAA,MAAA;EAKtC,GAAA,CAAA,EAAA,MAAA;EAMD,GAAA,CAAA,EAAA,MAAA;;;;AAAwD;AAO3D,UAnCI,eAAA,CAmCO;EAAA,MAAA,EAAA,MAAA;EAAA,MAAiB,CAAA,EAAA,MAAA;EAAS,QAAG,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAS,UAIxB,CAAA,EAAA,MAAA,EAAA;;;;;AA2BK,UAxD1B,aAAA,CAwD0B;EAiB3B,OAAA,EAAA,MAAS;EAAA,MAAA,CAAA,EAAA,MAAA;EAAA,QAAiB,CAAA,EAAA,MAAA,GAAA,MAAA,EAAA;EAAS,UAAG,CAAA,EAAA,MAAA,EAAA;;AAE5C,KApEE,SAAA,GAAY,eAoEd,GApEgC,aAoEhC;;;;UA/DO,sBAAA;;;;;iBAMD,YAAA,SAAqB,sBAAsB;;;;cAO9C,4BAA4B,YAAY;;;;sBAIf;yBASR,QAAQ;+BAkBF,QAAQ;;;;;;;iBAiB5B,0BAA0B,YAAY,2BAEnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-D88cPJyT.mjs","names":["config: JwtConfig","token: string","payload"],"sources":["../src/jwt.ts"],"sourcesContent":["import * as jose from 'jose';\n\n/**\n * Standard JWT claims\n */\nexport interface JwtClaims {\n sub?: string;\n iss?: string;\n aud?: string | string[];\n exp?: number;\n iat?: number;\n nbf?: number;\n jti?: string;\n}\n\n/**\n * Configuration for JWT verification with a symmetric secret\n */\nexport interface JwtSecretConfig {\n secret: string;\n issuer?: string;\n audience?: string | string[];\n algorithms?: string[];\n}\n\n/**\n * Configuration for JWT verification with JWKS\n */\nexport interface JwtJwksConfig {\n jwksUri: string;\n issuer?: string;\n audience?: string | string[];\n algorithms?: string[];\n}\n\nexport type JwtConfig = JwtSecretConfig | JwtJwksConfig;\n\n/**\n * Options for token extraction from requests\n */\nexport interface TokenExtractionOptions {\n headerName?: string;\n cookieName?: string;\n tokenPrefix?: string;\n}\n\nexport function isJwksConfig(config: JwtConfig): config is JwtJwksConfig {\n return 'jwksUri' in config;\n}\n\n/**\n * JWT Verifier with JWKS caching\n */\nexport class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {\n private jwks: jose.JWTVerifyGetKey | null = null;\n private readonly verifyOptions: jose.JWTVerifyOptions;\n\n constructor(private readonly config: JwtConfig) {\n this.verifyOptions = {\n issuer: config.issuer,\n audience: config.audience,\n algorithms:\n config.algorithms ?? (isJwksConfig(config) ? undefined : ['HS256']),\n };\n }\n\n async verify(token: string): Promise<TClaims> {\n if (isJwksConfig(this.config)) {\n if (!this.jwks) {\n this.jwks = jose.createRemoteJWKSet(new URL(this.config.jwksUri));\n }\n const { payload } = await jose.jwtVerify(\n token,\n this.jwks,\n this.verifyOptions,\n );\n return payload as unknown as TClaims;\n }\n\n const secret = new TextEncoder().encode(this.config.secret);\n const { payload } = await jose.jwtVerify(token, secret, this.verifyOptions);\n return payload as unknown as TClaims;\n }\n\n async verifyOrNull(token: string): Promise<TClaims | null> {\n try {\n return await this.verify(token);\n } catch {\n return null;\n }\n }\n\n clearCache(): void {\n this.jwks = null;\n }\n}\n\n/**\n * Decode a JWT without verification\n * WARNING: This does NOT verify the token signature!\n */\nexport function decodeJwt<TClaims extends JwtClaims = JwtClaims>(\n token: string,\n): TClaims {\n return jose.decodeJwt(token) as unknown as TClaims;\n}\n"],"mappings":";;;AA8CA,SAAgB,aAAaA,QAA4C;AACvE,QAAO,aAAa;AACrB;;;;AAKD,IAAa,cAAb,MAAgE;CAC9D,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAmB;EAAnB;AAC3B,OAAK,gBAAgB;GACnB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,YACE,OAAO,eAAe,aAAa,OAAO,YAAe,CAAC,OAAQ;EACrE;CACF;CAED,MAAM,OAAOC,OAAiC;AAC5C,MAAI,aAAa,KAAK,OAAO,EAAE;AAC7B,QAAK,KAAK,KACR,MAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,OAAO,SAAS;GAEnE,MAAM,EAAE,oBAAS,GAAG,MAAM,KAAK,UAC7B,OACA,KAAK,MACL,KAAK,cACN;AACD,UAAOC;EACR;EAED,MAAM,SAAS,IAAI,cAAc,OAAO,KAAK,OAAO,OAAO;EAC3D,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK,cAAc;AAC3E,SAAO;CACR;CAED,MAAM,aAAaD,OAAwC;AACzD,MAAI;AACF,UAAO,MAAM,KAAK,OAAO,MAAM;EAChC,QAAO;AACN,UAAO;EACR;CACF;CAED,aAAmB;AACjB,OAAK,OAAO;CACb;AACF;;;;;AAMD,SAAgB,UACdA,OACS;AACT,QAAO,KAAK,UAAU,MAAM;AAC7B"}
1
+ {"version":3,"file":"jwt-D88cPJyT.mjs","names":["config: JwtConfig","token: string","payload"],"sources":["../src/jwt.ts"],"sourcesContent":["import * as jose from 'jose';\n\n/**\n * Standard JWT claims\n */\nexport interface JwtClaims {\n\tsub?: string;\n\tiss?: string;\n\taud?: string | string[];\n\texp?: number;\n\tiat?: number;\n\tnbf?: number;\n\tjti?: string;\n}\n\n/**\n * Configuration for JWT verification with a symmetric secret\n */\nexport interface JwtSecretConfig {\n\tsecret: string;\n\tissuer?: string;\n\taudience?: string | string[];\n\talgorithms?: string[];\n}\n\n/**\n * Configuration for JWT verification with JWKS\n */\nexport interface JwtJwksConfig {\n\tjwksUri: string;\n\tissuer?: string;\n\taudience?: string | string[];\n\talgorithms?: string[];\n}\n\nexport type JwtConfig = JwtSecretConfig | JwtJwksConfig;\n\n/**\n * Options for token extraction from requests\n */\nexport interface TokenExtractionOptions {\n\theaderName?: string;\n\tcookieName?: string;\n\ttokenPrefix?: string;\n}\n\nexport function isJwksConfig(config: JwtConfig): config is JwtJwksConfig {\n\treturn 'jwksUri' in config;\n}\n\n/**\n * JWT Verifier with JWKS caching\n */\nexport class JwtVerifier<TClaims extends JwtClaims = JwtClaims> {\n\tprivate jwks: jose.JWTVerifyGetKey | null = null;\n\tprivate readonly verifyOptions: jose.JWTVerifyOptions;\n\n\tconstructor(private readonly config: JwtConfig) {\n\t\tthis.verifyOptions = {\n\t\t\tissuer: config.issuer,\n\t\t\taudience: config.audience,\n\t\t\talgorithms:\n\t\t\t\tconfig.algorithms ?? (isJwksConfig(config) ? undefined : ['HS256']),\n\t\t};\n\t}\n\n\tasync verify(token: string): Promise<TClaims> {\n\t\tif (isJwksConfig(this.config)) {\n\t\t\tif (!this.jwks) {\n\t\t\t\tthis.jwks = jose.createRemoteJWKSet(new URL(this.config.jwksUri));\n\t\t\t}\n\t\t\tconst { payload } = await jose.jwtVerify(\n\t\t\t\ttoken,\n\t\t\t\tthis.jwks,\n\t\t\t\tthis.verifyOptions,\n\t\t\t);\n\t\t\treturn payload as unknown as TClaims;\n\t\t}\n\n\t\tconst secret = new TextEncoder().encode(this.config.secret);\n\t\tconst { payload } = await jose.jwtVerify(token, secret, this.verifyOptions);\n\t\treturn payload as unknown as TClaims;\n\t}\n\n\tasync verifyOrNull(token: string): Promise<TClaims | null> {\n\t\ttry {\n\t\t\treturn await this.verify(token);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tclearCache(): void {\n\t\tthis.jwks = null;\n\t}\n}\n\n/**\n * Decode a JWT without verification\n * WARNING: This does NOT verify the token signature!\n */\nexport function decodeJwt<TClaims extends JwtClaims = JwtClaims>(\n\ttoken: string,\n): TClaims {\n\treturn jose.decodeJwt(token) as unknown as TClaims;\n}\n"],"mappings":";;;AA8CA,SAAgB,aAAaA,QAA4C;AACxE,QAAO,aAAa;AACpB;;;;AAKD,IAAa,cAAb,MAAgE;CAC/D,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAmB;EAAnB;AAC5B,OAAK,gBAAgB;GACpB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,YACC,OAAO,eAAe,aAAa,OAAO,YAAe,CAAC,OAAQ;EACnE;CACD;CAED,MAAM,OAAOC,OAAiC;AAC7C,MAAI,aAAa,KAAK,OAAO,EAAE;AAC9B,QAAK,KAAK,KACT,MAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,OAAO,SAAS;GAElE,MAAM,EAAE,oBAAS,GAAG,MAAM,KAAK,UAC9B,OACA,KAAK,MACL,KAAK,cACL;AACD,UAAOC;EACP;EAED,MAAM,SAAS,IAAI,cAAc,OAAO,KAAK,OAAO,OAAO;EAC3D,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK,cAAc;AAC3E,SAAO;CACP;CAED,MAAM,aAAaD,OAAwC;AAC1D,MAAI;AACH,UAAO,MAAM,KAAK,OAAO,MAAM;EAC/B,QAAO;AACP,UAAO;EACP;CACD;CAED,aAAmB;AAClB,OAAK,OAAO;CACZ;AACD;;;;;AAMD,SAAgB,UACfA,OACU;AACV,QAAO,KAAK,UAAU,MAAM;AAC5B"}
package/dist/jwt.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig } from "./jwt-DF9kFbmh.cjs";
1
+ import { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig } from "./jwt-3eIuY2dg.cjs";
2
2
  export { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig };
package/dist/jwt.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig } from "./jwt-DH8CJ2xC.mjs";
1
+ import { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig } from "./jwt-BqLlRkw-.mjs";
2
2
  export { JwtClaims, JwtConfig, JwtJwksConfig, JwtSecretConfig, JwtVerifier, TokenExtractionOptions, decodeJwt, isJwksConfig };
@@ -93,9 +93,9 @@ var JwtAuthorizer = class {
93
93
  }
94
94
  }
95
95
  if (cookieName) {
96
- const cookieHeader = headers["cookie"] ?? headers["Cookie"] ?? "";
96
+ const cookieHeader = headers.cookie ?? headers.Cookie ?? "";
97
97
  const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));
98
- if (match) return match[1];
98
+ if (match?.[1]) return match[1];
99
99
  }
100
100
  return null;
101
101
  };
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.cjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: JwtAuthorizerOptions<TClaims>","JwtVerifier","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":["import type {\n APIGatewayAuthorizerResult,\n APIGatewayRequestAuthorizerEvent,\n APIGatewayTokenAuthorizerEvent,\n Context as LambdaContext,\n PolicyDocument,\n} from 'aws-lambda';\nimport {\n type JwtClaims,\n type JwtConfig,\n JwtVerifier,\n type TokenExtractionOptions,\n} from '../jwt';\n\nexport {\n JwtVerifier,\n type JwtClaims,\n type JwtConfig,\n type TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n principalId: string,\n effect: 'Allow' | 'Deny',\n resource: string,\n context?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n const policyDocument: PolicyDocument = {\n Version: '2012-10-17',\n Statement: [\n {\n Action: 'execute-api:Invoke',\n Effect: effect,\n Resource: resource,\n },\n ],\n };\n\n return {\n principalId,\n policyDocument,\n context,\n };\n}\n\nfunction getWildcardResource(methodArn: string): string {\n const parts = methodArn.split('/');\n return `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface JwtAuthorizerOptions<TClaims extends JwtClaims = JwtClaims> {\n config: JwtConfig;\n extraction?: TokenExtractionOptions;\n wildcardResource?: boolean;\n getPrincipalId?: (claims: TClaims) => string;\n getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * JWT Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new JwtAuthorizer({\n * config: {\n * jwksUri: 'https://auth.example.com/.well-known/jwks.json',\n * issuer: 'https://auth.example.com',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * // TOKEN authorizer\n * export const tokenHandler = authorizer.tokenHandler();\n *\n * // REQUEST authorizer\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {\n private readonly verifier: JwtVerifier<TClaims>;\n private readonly extraction: TokenExtractionOptions;\n private readonly wildcardResource: boolean;\n private readonly getPrincipalId: (claims: TClaims) => string;\n private readonly getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n private readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n constructor(options: JwtAuthorizerOptions<TClaims>) {\n this.verifier = new JwtVerifier(options.config);\n this.extraction = options.extraction ?? {};\n this.wildcardResource = options.wildcardResource ?? true;\n this.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n this.getContext = options.getContext;\n this.authorize = options.authorize;\n }\n\n /**\n * Returns a TOKEN authorizer handler\n */\n tokenHandler() {\n return async (\n event: APIGatewayTokenAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const { authorizationToken, methodArn } = event;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = authorizationToken.startsWith('Bearer ')\n ? authorizationToken.slice(7)\n : authorizationToken;\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n\n /**\n * Returns a REQUEST authorizer handler\n */\n requestHandler() {\n const {\n headerName = 'authorization',\n cookieName,\n tokenPrefix = 'Bearer ',\n } = this.extraction;\n\n const extractToken = (\n event: APIGatewayRequestAuthorizerEvent,\n ): string | null => {\n const headers = event.headers ?? {};\n const headerKey = Object.keys(headers).find(\n (k) => k.toLowerCase() === headerName.toLowerCase(),\n );\n if (headerKey) {\n const headerValue = headers[headerKey];\n if (headerValue) {\n if (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n return headerValue.slice(tokenPrefix.length);\n }\n return headerValue;\n }\n }\n\n if (cookieName) {\n const cookieHeader = headers['cookie'] ?? headers['Cookie'] ?? '';\n const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n if (match) {\n return match[1];\n }\n }\n\n return null;\n };\n\n return async (\n event: APIGatewayRequestAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const methodArn = event.methodArn;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = extractToken(event);\n\n if (!token) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"jwt.cjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: JwtAuthorizerOptions<TClaims>","JwtVerifier","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":["import type {\n\tAPIGatewayAuthorizerResult,\n\tAPIGatewayRequestAuthorizerEvent,\n\tAPIGatewayTokenAuthorizerEvent,\n\tContext as LambdaContext,\n\tPolicyDocument,\n} from 'aws-lambda';\nimport {\n\ttype JwtClaims,\n\ttype JwtConfig,\n\tJwtVerifier,\n\ttype TokenExtractionOptions,\n} from '../jwt';\n\nexport {\n\tJwtVerifier,\n\ttype JwtClaims,\n\ttype JwtConfig,\n\ttype TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n\tprincipalId: string,\n\teffect: 'Allow' | 'Deny',\n\tresource: string,\n\tcontext?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n\tconst policyDocument: PolicyDocument = {\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tAction: 'execute-api:Invoke',\n\t\t\t\tEffect: effect,\n\t\t\t\tResource: resource,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn {\n\t\tprincipalId,\n\t\tpolicyDocument,\n\t\tcontext,\n\t};\n}\n\nfunction getWildcardResource(methodArn: string): string {\n\tconst parts = methodArn.split('/');\n\treturn `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface JwtAuthorizerOptions<TClaims extends JwtClaims = JwtClaims> {\n\tconfig: JwtConfig;\n\textraction?: TokenExtractionOptions;\n\twildcardResource?: boolean;\n\tgetPrincipalId?: (claims: TClaims) => string;\n\tgetContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tauthorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * JWT Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new JwtAuthorizer({\n * config: {\n * jwksUri: 'https://auth.example.com/.well-known/jwks.json',\n * issuer: 'https://auth.example.com',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * // TOKEN authorizer\n * export const tokenHandler = authorizer.tokenHandler();\n *\n * // REQUEST authorizer\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {\n\tprivate readonly verifier: JwtVerifier<TClaims>;\n\tprivate readonly extraction: TokenExtractionOptions;\n\tprivate readonly wildcardResource: boolean;\n\tprivate readonly getPrincipalId: (claims: TClaims) => string;\n\tprivate readonly getContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tprivate readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n\tconstructor(options: JwtAuthorizerOptions<TClaims>) {\n\t\tthis.verifier = new JwtVerifier(options.config);\n\t\tthis.extraction = options.extraction ?? {};\n\t\tthis.wildcardResource = options.wildcardResource ?? true;\n\t\tthis.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n\t\tthis.getContext = options.getContext;\n\t\tthis.authorize = options.authorize;\n\t}\n\n\t/**\n\t * Returns a TOKEN authorizer handler\n\t */\n\ttokenHandler() {\n\t\treturn async (\n\t\t\tevent: APIGatewayTokenAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst { authorizationToken, methodArn } = event;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = authorizationToken.startsWith('Bearer ')\n\t\t\t\t? authorizationToken.slice(7)\n\t\t\t\t: authorizationToken;\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Returns a REQUEST authorizer handler\n\t */\n\trequestHandler() {\n\t\tconst {\n\t\t\theaderName = 'authorization',\n\t\t\tcookieName,\n\t\t\ttokenPrefix = 'Bearer ',\n\t\t} = this.extraction;\n\n\t\tconst extractToken = (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t): string | null => {\n\t\t\tconst headers = event.headers ?? {};\n\t\t\tconst headerKey = Object.keys(headers).find(\n\t\t\t\t(k) => k.toLowerCase() === headerName.toLowerCase(),\n\t\t\t);\n\t\t\tif (headerKey) {\n\t\t\t\tconst headerValue = headers[headerKey];\n\t\t\t\tif (headerValue) {\n\t\t\t\t\tif (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n\t\t\t\t\t\treturn headerValue.slice(tokenPrefix.length);\n\t\t\t\t\t}\n\t\t\t\t\treturn headerValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (cookieName) {\n\t\t\t\tconst cookieHeader = headers.cookie ?? headers.Cookie ?? '';\n\t\t\t\tconst match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n\t\t\t\tif (match?.[1]) {\n\t\t\t\t\treturn match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\treturn async (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst methodArn = event.methodArn;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = extractToken(event);\n\n\t\t\tif (!token) {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions } from "../jwt-DF9kFbmh.cjs";
1
+ import { JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions } from "../jwt-3eIuY2dg.cjs";
2
2
  import { APIGatewayAuthorizerResult, APIGatewayRequestAuthorizerEvent, APIGatewayTokenAuthorizerEvent, Context } from "aws-lambda";
3
3
 
4
4
  //#region src/lambda/jwt.d.ts
@@ -47,6 +47,7 @@ declare class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {
47
47
  */
48
48
  requestHandler(): (event: APIGatewayRequestAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
49
49
  }
50
+ //# sourceMappingURL=jwt.d.ts.map
50
51
  //#endregion
51
52
  export { JwtAuthorizer, JwtAuthorizerOptions, JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions };
52
53
  //# sourceMappingURL=jwt.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.cts","names":[],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":[],"mappings":";;;;UAkDiB,qCAAqC,YAAY;EAAjD,MAAA,EACR,SADQ;EAAoB,UAAA,CAAA,EAEvB,sBAFuB;EAAA,gBAAiB,CAAA,EAAA,OAAA;EAAS,cAAG,CAAA,EAAA,CAAA,MAAA,EAIvC,OAJuC,EAAA,GAAA,MAAA;EAAS,UAClE,CAAA,EAAA,CAAA,MAAA,EAKC,OALD,EAAA,GAMH,MANG,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAS,SACJ,CAAA,EAAA,CAAA,MAAA,EAMQ,OANR,EAAA,GAAA,OAAA,GAM8B,OAN9B,CAAA,OAAA,CAAA;;;;;;AAMqC;AAuBnD;;;;;;;;;;;;;;AAiGY;cAjGC,8BAA8B,YAAY;;;;;;;uBAUjC,qBAAqB;;;;0BAcjC,0CACG,YACR,QAAQ;;;;4BAqEH,4CACG,YACR,QAAQ"}
@@ -1,4 +1,4 @@
1
- import { JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions } from "../jwt-DH8CJ2xC.mjs";
1
+ import { JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions } from "../jwt-BqLlRkw-.mjs";
2
2
  import { APIGatewayAuthorizerResult, APIGatewayRequestAuthorizerEvent, APIGatewayTokenAuthorizerEvent, Context } from "aws-lambda";
3
3
 
4
4
  //#region src/lambda/jwt.d.ts
@@ -47,6 +47,7 @@ declare class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {
47
47
  */
48
48
  requestHandler(): (event: APIGatewayRequestAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
49
49
  }
50
+ //# sourceMappingURL=jwt.d.ts.map
50
51
  //#endregion
51
52
  export { JwtAuthorizer, JwtAuthorizerOptions, JwtClaims, JwtConfig, JwtVerifier, TokenExtractionOptions };
52
53
  //# sourceMappingURL=jwt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.mts","names":[],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":[],"mappings":";;;;UAkDiB,qCAAqC,YAAY;EAAjD,MAAA,EACR,SADQ;EAAoB,UAAA,CAAA,EAEvB,sBAFuB;EAAA,gBAAiB,CAAA,EAAA,OAAA;EAAS,cAAG,CAAA,EAAA,CAAA,MAAA,EAIvC,OAJuC,EAAA,GAAA,MAAA;EAAS,UAClE,CAAA,EAAA,CAAA,MAAA,EAKC,OALD,EAAA,GAMH,MANG,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAS,SACJ,CAAA,EAAA,CAAA,MAAA,EAMQ,OANR,EAAA,GAAA,OAAA,GAM8B,OAN9B,CAAA,OAAA,CAAA;;;;;;AAMqC;AAuBnD;;;;;;;;;;;;;;AAiGY;cAjGC,8BAA8B,YAAY;;;;;;;uBAUjC,qBAAqB;;;;0BAcjC,0CACG,YACR,QAAQ;;;;4BAqEH,4CACG,YACR,QAAQ"}
@@ -93,9 +93,9 @@ var JwtAuthorizer = class {
93
93
  }
94
94
  }
95
95
  if (cookieName) {
96
- const cookieHeader = headers["cookie"] ?? headers["Cookie"] ?? "";
96
+ const cookieHeader = headers.cookie ?? headers.Cookie ?? "";
97
97
  const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));
98
- if (match) return match[1];
98
+ if (match?.[1]) return match[1];
99
99
  }
100
100
  return null;
101
101
  };
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.mjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: JwtAuthorizerOptions<TClaims>","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":["import type {\n APIGatewayAuthorizerResult,\n APIGatewayRequestAuthorizerEvent,\n APIGatewayTokenAuthorizerEvent,\n Context as LambdaContext,\n PolicyDocument,\n} from 'aws-lambda';\nimport {\n type JwtClaims,\n type JwtConfig,\n JwtVerifier,\n type TokenExtractionOptions,\n} from '../jwt';\n\nexport {\n JwtVerifier,\n type JwtClaims,\n type JwtConfig,\n type TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n principalId: string,\n effect: 'Allow' | 'Deny',\n resource: string,\n context?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n const policyDocument: PolicyDocument = {\n Version: '2012-10-17',\n Statement: [\n {\n Action: 'execute-api:Invoke',\n Effect: effect,\n Resource: resource,\n },\n ],\n };\n\n return {\n principalId,\n policyDocument,\n context,\n };\n}\n\nfunction getWildcardResource(methodArn: string): string {\n const parts = methodArn.split('/');\n return `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface JwtAuthorizerOptions<TClaims extends JwtClaims = JwtClaims> {\n config: JwtConfig;\n extraction?: TokenExtractionOptions;\n wildcardResource?: boolean;\n getPrincipalId?: (claims: TClaims) => string;\n getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * JWT Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new JwtAuthorizer({\n * config: {\n * jwksUri: 'https://auth.example.com/.well-known/jwks.json',\n * issuer: 'https://auth.example.com',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * // TOKEN authorizer\n * export const tokenHandler = authorizer.tokenHandler();\n *\n * // REQUEST authorizer\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {\n private readonly verifier: JwtVerifier<TClaims>;\n private readonly extraction: TokenExtractionOptions;\n private readonly wildcardResource: boolean;\n private readonly getPrincipalId: (claims: TClaims) => string;\n private readonly getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n private readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n constructor(options: JwtAuthorizerOptions<TClaims>) {\n this.verifier = new JwtVerifier(options.config);\n this.extraction = options.extraction ?? {};\n this.wildcardResource = options.wildcardResource ?? true;\n this.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n this.getContext = options.getContext;\n this.authorize = options.authorize;\n }\n\n /**\n * Returns a TOKEN authorizer handler\n */\n tokenHandler() {\n return async (\n event: APIGatewayTokenAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const { authorizationToken, methodArn } = event;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = authorizationToken.startsWith('Bearer ')\n ? authorizationToken.slice(7)\n : authorizationToken;\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n\n /**\n * Returns a REQUEST authorizer handler\n */\n requestHandler() {\n const {\n headerName = 'authorization',\n cookieName,\n tokenPrefix = 'Bearer ',\n } = this.extraction;\n\n const extractToken = (\n event: APIGatewayRequestAuthorizerEvent,\n ): string | null => {\n const headers = event.headers ?? {};\n const headerKey = Object.keys(headers).find(\n (k) => k.toLowerCase() === headerName.toLowerCase(),\n );\n if (headerKey) {\n const headerValue = headers[headerKey];\n if (headerValue) {\n if (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n return headerValue.slice(tokenPrefix.length);\n }\n return headerValue;\n }\n }\n\n if (cookieName) {\n const cookieHeader = headers['cookie'] ?? headers['Cookie'] ?? '';\n const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n if (match) {\n return match[1];\n }\n }\n\n return null;\n };\n\n return async (\n event: APIGatewayRequestAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const methodArn = event.methodArn;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = extractToken(event);\n\n if (!token) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n}\n"],"mappings":";;;AAqBA,SAAS,eACPA,aACAC,QACAC,UACAC,SAC4B;CAC5B,MAAMC,iBAAiC;EACrC,SAAS;EACT,WAAW,CACT;GACE,QAAQ;GACR,QAAQ;GACR,UAAU;EACX,CACF;CACF;AAED,QAAO;EACL;EACA;EACA;CACD;AACF;AAED,SAAS,oBAAoBC,WAA2B;CACtD,MAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,SAAQ,EAAE,MAAM,GAAG,GAAG,MAAM,GAAG;AAChC;;;;;;;;;;;;;;;;;;;;;AAiCD,IAAa,gBAAb,MAAkE;CAChE,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAGjB,AAAiB;CAEjB,YAAYC,SAAwC;AAClD,OAAK,WAAW,IAAI,YAAY,QAAQ;AACxC,OAAK,aAAa,QAAQ,cAAc,CAAE;AAC1C,OAAK,mBAAmB,QAAQ,oBAAoB;AACpD,OAAK,iBAAiB,QAAQ,mBAAmB,CAAC,MAAM,EAAE,OAAO;AACjE,OAAK,aAAa,QAAQ;AAC1B,OAAK,YAAY,QAAQ;CAC1B;;;;CAKD,eAAe;AACb,SAAO,OACLC,OACAC,aACwC;GACxC,MAAM,EAAE,oBAAoB,WAAW,GAAG;GAC1C,MAAM,WAAW,KAAK,mBAClB,oBAAoB,UAAU,GAC9B;GAEJ,MAAM,QAAQ,mBAAmB,WAAW,UAAU,GAClD,mBAAmB,MAAM,EAAE,GAC3B;AAEJ,OAAI;IACF,MAAM,SAAS,MAAM,KAAK,SAAS,OAAO,MAAM;AAEhD,QAAI,KAAK,WAAW;KAClB,MAAM,eAAe,MAAM,KAAK,UAAU,OAAO;AACjD,UAAK,aACH,QAAO,eAAe,gBAAgB,QAAQ,SAAS;IAE1D;IAED,MAAM,cAAc,KAAK,eAAe,OAAO;IAC/C,MAAM,UAAU,KAAK,aAAa,OAAO;AAEzC,WAAO,eAAe,aAAa,SAAS,UAAU,QAAQ;GAC/D,QAAO;AACN,WAAO,eAAe,gBAAgB,QAAQ,SAAS;GACxD;EACF;CACF;;;;CAKD,iBAAiB;EACf,MAAM,EACJ,aAAa,iBACb,YACA,cAAc,WACf,GAAG,KAAK;EAET,MAAM,eAAe,CACnBC,UACkB;GAClB,MAAM,UAAU,MAAM,WAAW,CAAE;GACnC,MAAM,YAAY,OAAO,KAAK,QAAQ,CAAC,KACrC,CAAC,MAAM,EAAE,aAAa,KAAK,WAAW,aAAa,CACpD;AACD,OAAI,WAAW;IACb,MAAM,cAAc,QAAQ;AAC5B,QAAI,aAAa;AACf,SAAI,eAAe,YAAY,WAAW,YAAY,CACpD,QAAO,YAAY,MAAM,YAAY,OAAO;AAE9C,YAAO;IACR;GACF;AAED,OAAI,YAAY;IACd,MAAM,eAAe,QAAQ,aAAa,QAAQ,aAAa;IAC/D,MAAM,QAAQ,aAAa,MAAM,IAAI,QAAQ,EAAE,WAAW,WAAW;AACrE,QAAI,MACF,QAAO,MAAM;GAEhB;AAED,UAAO;EACR;AAED,SAAO,OACLA,OACAD,aACwC;GACxC,MAAM,YAAY,MAAM;GACxB,MAAM,WAAW,KAAK,mBAClB,oBAAoB,UAAU,GAC9B;GAEJ,MAAM,QAAQ,aAAa,MAAM;AAEjC,QAAK,MACH,QAAO,eAAe,gBAAgB,QAAQ,SAAS;AAGzD,OAAI;IACF,MAAM,SAAS,MAAM,KAAK,SAAS,OAAO,MAAM;AAEhD,QAAI,KAAK,WAAW;KAClB,MAAM,eAAe,MAAM,KAAK,UAAU,OAAO;AACjD,UAAK,aACH,QAAO,eAAe,gBAAgB,QAAQ,SAAS;IAE1D;IAED,MAAM,cAAc,KAAK,eAAe,OAAO;IAC/C,MAAM,UAAU,KAAK,aAAa,OAAO;AAEzC,WAAO,eAAe,aAAa,SAAS,UAAU,QAAQ;GAC/D,QAAO;AACN,WAAO,eAAe,gBAAgB,QAAQ,SAAS;GACxD;EACF;CACF;AACF"}
1
+ {"version":3,"file":"jwt.mjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: JwtAuthorizerOptions<TClaims>","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/jwt.ts"],"sourcesContent":["import type {\n\tAPIGatewayAuthorizerResult,\n\tAPIGatewayRequestAuthorizerEvent,\n\tAPIGatewayTokenAuthorizerEvent,\n\tContext as LambdaContext,\n\tPolicyDocument,\n} from 'aws-lambda';\nimport {\n\ttype JwtClaims,\n\ttype JwtConfig,\n\tJwtVerifier,\n\ttype TokenExtractionOptions,\n} from '../jwt';\n\nexport {\n\tJwtVerifier,\n\ttype JwtClaims,\n\ttype JwtConfig,\n\ttype TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n\tprincipalId: string,\n\teffect: 'Allow' | 'Deny',\n\tresource: string,\n\tcontext?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n\tconst policyDocument: PolicyDocument = {\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tAction: 'execute-api:Invoke',\n\t\t\t\tEffect: effect,\n\t\t\t\tResource: resource,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn {\n\t\tprincipalId,\n\t\tpolicyDocument,\n\t\tcontext,\n\t};\n}\n\nfunction getWildcardResource(methodArn: string): string {\n\tconst parts = methodArn.split('/');\n\treturn `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface JwtAuthorizerOptions<TClaims extends JwtClaims = JwtClaims> {\n\tconfig: JwtConfig;\n\textraction?: TokenExtractionOptions;\n\twildcardResource?: boolean;\n\tgetPrincipalId?: (claims: TClaims) => string;\n\tgetContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tauthorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * JWT Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new JwtAuthorizer({\n * config: {\n * jwksUri: 'https://auth.example.com/.well-known/jwks.json',\n * issuer: 'https://auth.example.com',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * // TOKEN authorizer\n * export const tokenHandler = authorizer.tokenHandler();\n *\n * // REQUEST authorizer\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class JwtAuthorizer<TClaims extends JwtClaims = JwtClaims> {\n\tprivate readonly verifier: JwtVerifier<TClaims>;\n\tprivate readonly extraction: TokenExtractionOptions;\n\tprivate readonly wildcardResource: boolean;\n\tprivate readonly getPrincipalId: (claims: TClaims) => string;\n\tprivate readonly getContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tprivate readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n\tconstructor(options: JwtAuthorizerOptions<TClaims>) {\n\t\tthis.verifier = new JwtVerifier(options.config);\n\t\tthis.extraction = options.extraction ?? {};\n\t\tthis.wildcardResource = options.wildcardResource ?? true;\n\t\tthis.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n\t\tthis.getContext = options.getContext;\n\t\tthis.authorize = options.authorize;\n\t}\n\n\t/**\n\t * Returns a TOKEN authorizer handler\n\t */\n\ttokenHandler() {\n\t\treturn async (\n\t\t\tevent: APIGatewayTokenAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst { authorizationToken, methodArn } = event;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = authorizationToken.startsWith('Bearer ')\n\t\t\t\t? authorizationToken.slice(7)\n\t\t\t\t: authorizationToken;\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Returns a REQUEST authorizer handler\n\t */\n\trequestHandler() {\n\t\tconst {\n\t\t\theaderName = 'authorization',\n\t\t\tcookieName,\n\t\t\ttokenPrefix = 'Bearer ',\n\t\t} = this.extraction;\n\n\t\tconst extractToken = (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t): string | null => {\n\t\t\tconst headers = event.headers ?? {};\n\t\t\tconst headerKey = Object.keys(headers).find(\n\t\t\t\t(k) => k.toLowerCase() === headerName.toLowerCase(),\n\t\t\t);\n\t\t\tif (headerKey) {\n\t\t\t\tconst headerValue = headers[headerKey];\n\t\t\t\tif (headerValue) {\n\t\t\t\t\tif (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n\t\t\t\t\t\treturn headerValue.slice(tokenPrefix.length);\n\t\t\t\t\t}\n\t\t\t\t\treturn headerValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (cookieName) {\n\t\t\t\tconst cookieHeader = headers.cookie ?? headers.Cookie ?? '';\n\t\t\t\tconst match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n\t\t\t\tif (match?.[1]) {\n\t\t\t\t\treturn match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\treturn async (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst methodArn = event.methodArn;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = extractToken(event);\n\n\t\t\tif (!token) {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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"}
@@ -84,9 +84,9 @@ var OidcAuthorizer = class {
84
84
  }
85
85
  }
86
86
  if (cookieName) {
87
- const cookieHeader = headers["cookie"] ?? headers["Cookie"] ?? "";
87
+ const cookieHeader = headers.cookie ?? headers.Cookie ?? "";
88
88
  const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));
89
- if (match) return match[1];
89
+ if (match?.[1]) return match[1];
90
90
  }
91
91
  return null;
92
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"oidc.cjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: OidcAuthorizerOptions<TClaims>","OidcVerifier","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":["import type {\n APIGatewayAuthorizerResult,\n APIGatewayRequestAuthorizerEvent,\n APIGatewayTokenAuthorizerEvent,\n Context as LambdaContext,\n PolicyDocument,\n} from 'aws-lambda';\nimport {\n type OidcClaims,\n type OidcConfig,\n OidcVerifier,\n type TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n OidcVerifier,\n type OidcClaims,\n type OidcConfig,\n type TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n principalId: string,\n effect: 'Allow' | 'Deny',\n resource: string,\n context?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n const policyDocument: PolicyDocument = {\n Version: '2012-10-17',\n Statement: [\n {\n Action: 'execute-api:Invoke',\n Effect: effect,\n Resource: resource,\n },\n ],\n };\n\n return {\n principalId,\n policyDocument,\n context,\n };\n}\n\nfunction getWildcardResource(methodArn: string): string {\n const parts = methodArn.split('/');\n return `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface OidcAuthorizerOptions<\n TClaims extends OidcClaims = OidcClaims,\n> {\n config: OidcConfig;\n extraction?: TokenExtractionOptions;\n wildcardResource?: boolean;\n getPrincipalId?: (claims: TClaims) => string;\n getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * OIDC Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new OidcAuthorizer({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-api',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * export const tokenHandler = authorizer.tokenHandler();\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {\n private readonly verifier: OidcVerifier<TClaims>;\n private readonly extraction: TokenExtractionOptions;\n private readonly wildcardResource: boolean;\n private readonly getPrincipalId: (claims: TClaims) => string;\n private readonly getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n private readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n constructor(options: OidcAuthorizerOptions<TClaims>) {\n this.verifier = new OidcVerifier(options.config);\n this.extraction = options.extraction ?? {};\n this.wildcardResource = options.wildcardResource ?? true;\n this.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n this.getContext = options.getContext;\n this.authorize = options.authorize;\n }\n\n tokenHandler() {\n return async (\n event: APIGatewayTokenAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const { authorizationToken, methodArn } = event;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = authorizationToken.startsWith('Bearer ')\n ? authorizationToken.slice(7)\n : authorizationToken;\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n\n requestHandler() {\n const {\n headerName = 'authorization',\n cookieName,\n tokenPrefix = 'Bearer ',\n } = this.extraction;\n\n const extractToken = (\n event: APIGatewayRequestAuthorizerEvent,\n ): string | null => {\n const headers = event.headers ?? {};\n const headerKey = Object.keys(headers).find(\n (k) => k.toLowerCase() === headerName.toLowerCase(),\n );\n if (headerKey) {\n const headerValue = headers[headerKey];\n if (headerValue) {\n if (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n return headerValue.slice(tokenPrefix.length);\n }\n return headerValue;\n }\n }\n\n if (cookieName) {\n const cookieHeader = headers['cookie'] ?? headers['Cookie'] ?? '';\n const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n if (match) {\n return match[1];\n }\n }\n\n return null;\n };\n\n return async (\n event: APIGatewayRequestAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const methodArn = event.methodArn;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = extractToken(event);\n\n if (!token) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"oidc.cjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: OidcAuthorizerOptions<TClaims>","OidcVerifier","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":["import type {\n\tAPIGatewayAuthorizerResult,\n\tAPIGatewayRequestAuthorizerEvent,\n\tAPIGatewayTokenAuthorizerEvent,\n\tContext as LambdaContext,\n\tPolicyDocument,\n} from 'aws-lambda';\nimport {\n\ttype OidcClaims,\n\ttype OidcConfig,\n\tOidcVerifier,\n\ttype TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n\tOidcVerifier,\n\ttype OidcClaims,\n\ttype OidcConfig,\n\ttype TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n\tprincipalId: string,\n\teffect: 'Allow' | 'Deny',\n\tresource: string,\n\tcontext?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n\tconst policyDocument: PolicyDocument = {\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tAction: 'execute-api:Invoke',\n\t\t\t\tEffect: effect,\n\t\t\t\tResource: resource,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn {\n\t\tprincipalId,\n\t\tpolicyDocument,\n\t\tcontext,\n\t};\n}\n\nfunction getWildcardResource(methodArn: string): string {\n\tconst parts = methodArn.split('/');\n\treturn `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface OidcAuthorizerOptions<\n\tTClaims extends OidcClaims = OidcClaims,\n> {\n\tconfig: OidcConfig;\n\textraction?: TokenExtractionOptions;\n\twildcardResource?: boolean;\n\tgetPrincipalId?: (claims: TClaims) => string;\n\tgetContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tauthorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * OIDC Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new OidcAuthorizer({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-api',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * export const tokenHandler = authorizer.tokenHandler();\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {\n\tprivate readonly verifier: OidcVerifier<TClaims>;\n\tprivate readonly extraction: TokenExtractionOptions;\n\tprivate readonly wildcardResource: boolean;\n\tprivate readonly getPrincipalId: (claims: TClaims) => string;\n\tprivate readonly getContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tprivate readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n\tconstructor(options: OidcAuthorizerOptions<TClaims>) {\n\t\tthis.verifier = new OidcVerifier(options.config);\n\t\tthis.extraction = options.extraction ?? {};\n\t\tthis.wildcardResource = options.wildcardResource ?? true;\n\t\tthis.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n\t\tthis.getContext = options.getContext;\n\t\tthis.authorize = options.authorize;\n\t}\n\n\ttokenHandler() {\n\t\treturn async (\n\t\t\tevent: APIGatewayTokenAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst { authorizationToken, methodArn } = event;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = authorizationToken.startsWith('Bearer ')\n\t\t\t\t? authorizationToken.slice(7)\n\t\t\t\t: authorizationToken;\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n\n\trequestHandler() {\n\t\tconst {\n\t\t\theaderName = 'authorization',\n\t\t\tcookieName,\n\t\t\ttokenPrefix = 'Bearer ',\n\t\t} = this.extraction;\n\n\t\tconst extractToken = (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t): string | null => {\n\t\t\tconst headers = event.headers ?? {};\n\t\t\tconst headerKey = Object.keys(headers).find(\n\t\t\t\t(k) => k.toLowerCase() === headerName.toLowerCase(),\n\t\t\t);\n\t\t\tif (headerKey) {\n\t\t\t\tconst headerValue = headers[headerKey];\n\t\t\t\tif (headerValue) {\n\t\t\t\t\tif (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n\t\t\t\t\t\treturn headerValue.slice(tokenPrefix.length);\n\t\t\t\t\t}\n\t\t\t\t\treturn headerValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (cookieName) {\n\t\t\t\tconst cookieHeader = headers.cookie ?? headers.Cookie ?? '';\n\t\t\t\tconst match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n\t\t\t\tif (match?.[1]) {\n\t\t\t\t\treturn match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\treturn async (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst methodArn = event.methodArn;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = extractToken(event);\n\n\t\t\tif (!token) {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { TokenExtractionOptions } from "../jwt-DF9kFbmh.cjs";
2
- import { OidcClaims, OidcConfig, OidcVerifier } from "../oidc-DDLIB5gb.cjs";
1
+ import { TokenExtractionOptions } from "../jwt-3eIuY2dg.cjs";
2
+ import { OidcClaims, OidcConfig, OidcVerifier } from "../oidc-ChA17wLB.cjs";
3
3
  import { APIGatewayAuthorizerResult, APIGatewayRequestAuthorizerEvent, APIGatewayTokenAuthorizerEvent, Context } from "aws-lambda";
4
4
 
5
5
  //#region src/lambda/oidc.d.ts
@@ -39,6 +39,7 @@ declare class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {
39
39
  tokenHandler(): (event: APIGatewayTokenAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
40
40
  requestHandler(): (event: APIGatewayRequestAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
41
41
  }
42
+ //# sourceMappingURL=oidc.d.ts.map
42
43
  //#endregion
43
44
  export { OidcAuthorizer, OidcAuthorizerOptions, OidcClaims, OidcConfig, OidcVerifier, TokenExtractionOptions };
44
45
  //# sourceMappingURL=oidc.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc.d.cts","names":[],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":[],"mappings":";;;;;UAkDiB,sCACA,aAAa;UAErB;EAHQ,UAAA,CAAA,EAIH,sBAJwB;EAAA,gBAAA,CAAA,EAAA,OAAA;EAAA,cACrB,CAAA,EAAA,CAAA,MAAA,EAKU,OALV,EAAA,GAAA,MAAA;EAAU,UAAG,CAAA,EAAA,CAAA,MAAA,EAOpB,OAPoB,EAAA,GAQxB,MARwB,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAU,SAE/B,CAAA,EAAA,CAAA,MAAA,EAOa,OAPb,EAAA,GAAA,OAAA,GAOmC,OAPnC,CAAA,OAAA,CAAA;;;;;;;AAO0C;AAoBnD;;;;;;;;;;;AA0Fa,cA1FA,cA0FA,CAAA,gBA1F+B,UA0F/B,GA1F4C,UA0F5C,CAAA,CAAA;EAAa,iBACb,QAAA;EAA0B,iBAAlC,UAAA;EAAO,iBAAA,gBAAA;;;;uBAjFU,sBAAsB;0BAWlC,0CACG,YACR,QAAQ;4BAkEH,4CACG,YACR,QAAQ"}
@@ -1,5 +1,5 @@
1
- import { TokenExtractionOptions } from "../jwt-DH8CJ2xC.mjs";
2
- import { OidcClaims, OidcConfig, OidcVerifier } from "../oidc-CKOGLxjV.mjs";
1
+ import { TokenExtractionOptions } from "../jwt-BqLlRkw-.mjs";
2
+ import { OidcClaims, OidcConfig, OidcVerifier } from "../oidc-DTRgBBl6.mjs";
3
3
  import { APIGatewayAuthorizerResult, APIGatewayRequestAuthorizerEvent, APIGatewayTokenAuthorizerEvent, Context } from "aws-lambda";
4
4
 
5
5
  //#region src/lambda/oidc.d.ts
@@ -39,6 +39,7 @@ declare class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {
39
39
  tokenHandler(): (event: APIGatewayTokenAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
40
40
  requestHandler(): (event: APIGatewayRequestAuthorizerEvent, _context: Context) => Promise<APIGatewayAuthorizerResult>;
41
41
  }
42
+ //# sourceMappingURL=oidc.d.ts.map
42
43
  //#endregion
43
44
  export { OidcAuthorizer, OidcAuthorizerOptions, OidcClaims, OidcConfig, OidcVerifier, TokenExtractionOptions };
44
45
  //# sourceMappingURL=oidc.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc.d.mts","names":[],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":[],"mappings":";;;;;UAkDiB,sCACA,aAAa;UAErB;EAHQ,UAAA,CAAA,EAIH,sBAJwB;EAAA,gBAAA,CAAA,EAAA,OAAA;EAAA,cACrB,CAAA,EAAA,CAAA,MAAA,EAKU,OALV,EAAA,GAAA,MAAA;EAAU,UAAG,CAAA,EAAA,CAAA,MAAA,EAOpB,OAPoB,EAAA,GAQxB,MARwB,CAAA,MAAA,EAAA,MAAA,GAAA,MAAA,GAAA,OAAA,CAAA,GAAA,SAAA;EAAU,SAE/B,CAAA,EAAA,CAAA,MAAA,EAOa,OAPb,EAAA,GAAA,OAAA,GAOmC,OAPnC,CAAA,OAAA,CAAA;;;;;;;AAO0C;AAoBnD;;;;;;;;;;;AA0Fa,cA1FA,cA0FA,CAAA,gBA1F+B,UA0F/B,GA1F4C,UA0F5C,CAAA,CAAA;EAAa,iBACb,QAAA;EAA0B,iBAAlC,UAAA;EAAO,iBAAA,gBAAA;;;;uBAjFU,sBAAsB;0BAWlC,0CACG,YACR,QAAQ;4BAkEH,4CACG,YACR,QAAQ"}
@@ -84,9 +84,9 @@ var OidcAuthorizer = class {
84
84
  }
85
85
  }
86
86
  if (cookieName) {
87
- const cookieHeader = headers["cookie"] ?? headers["Cookie"] ?? "";
87
+ const cookieHeader = headers.cookie ?? headers.Cookie ?? "";
88
88
  const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));
89
- if (match) return match[1];
89
+ if (match?.[1]) return match[1];
90
90
  }
91
91
  return null;
92
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"oidc.mjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: OidcAuthorizerOptions<TClaims>","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":["import type {\n APIGatewayAuthorizerResult,\n APIGatewayRequestAuthorizerEvent,\n APIGatewayTokenAuthorizerEvent,\n Context as LambdaContext,\n PolicyDocument,\n} from 'aws-lambda';\nimport {\n type OidcClaims,\n type OidcConfig,\n OidcVerifier,\n type TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n OidcVerifier,\n type OidcClaims,\n type OidcConfig,\n type TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n principalId: string,\n effect: 'Allow' | 'Deny',\n resource: string,\n context?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n const policyDocument: PolicyDocument = {\n Version: '2012-10-17',\n Statement: [\n {\n Action: 'execute-api:Invoke',\n Effect: effect,\n Resource: resource,\n },\n ],\n };\n\n return {\n principalId,\n policyDocument,\n context,\n };\n}\n\nfunction getWildcardResource(methodArn: string): string {\n const parts = methodArn.split('/');\n return `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface OidcAuthorizerOptions<\n TClaims extends OidcClaims = OidcClaims,\n> {\n config: OidcConfig;\n extraction?: TokenExtractionOptions;\n wildcardResource?: boolean;\n getPrincipalId?: (claims: TClaims) => string;\n getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * OIDC Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new OidcAuthorizer({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-api',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * export const tokenHandler = authorizer.tokenHandler();\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {\n private readonly verifier: OidcVerifier<TClaims>;\n private readonly extraction: TokenExtractionOptions;\n private readonly wildcardResource: boolean;\n private readonly getPrincipalId: (claims: TClaims) => string;\n private readonly getContext?: (\n claims: TClaims,\n ) => Record<string, string | number | boolean> | undefined;\n private readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n constructor(options: OidcAuthorizerOptions<TClaims>) {\n this.verifier = new OidcVerifier(options.config);\n this.extraction = options.extraction ?? {};\n this.wildcardResource = options.wildcardResource ?? true;\n this.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n this.getContext = options.getContext;\n this.authorize = options.authorize;\n }\n\n tokenHandler() {\n return async (\n event: APIGatewayTokenAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const { authorizationToken, methodArn } = event;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = authorizationToken.startsWith('Bearer ')\n ? authorizationToken.slice(7)\n : authorizationToken;\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n\n requestHandler() {\n const {\n headerName = 'authorization',\n cookieName,\n tokenPrefix = 'Bearer ',\n } = this.extraction;\n\n const extractToken = (\n event: APIGatewayRequestAuthorizerEvent,\n ): string | null => {\n const headers = event.headers ?? {};\n const headerKey = Object.keys(headers).find(\n (k) => k.toLowerCase() === headerName.toLowerCase(),\n );\n if (headerKey) {\n const headerValue = headers[headerKey];\n if (headerValue) {\n if (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n return headerValue.slice(tokenPrefix.length);\n }\n return headerValue;\n }\n }\n\n if (cookieName) {\n const cookieHeader = headers['cookie'] ?? headers['Cookie'] ?? '';\n const match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n if (match) {\n return match[1];\n }\n }\n\n return null;\n };\n\n return async (\n event: APIGatewayRequestAuthorizerEvent,\n _context: LambdaContext,\n ): Promise<APIGatewayAuthorizerResult> => {\n const methodArn = event.methodArn;\n const resource = this.wildcardResource\n ? getWildcardResource(methodArn)\n : methodArn;\n\n const token = extractToken(event);\n\n if (!token) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n\n try {\n const claims = await this.verifier.verify(token);\n\n if (this.authorize) {\n const isAuthorized = await this.authorize(claims);\n if (!isAuthorized) {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n }\n\n const principalId = this.getPrincipalId(claims);\n const context = this.getContext?.(claims);\n\n return generatePolicy(principalId, 'Allow', resource, context);\n } catch {\n return generatePolicy('unauthorized', 'Deny', resource);\n }\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"oidc.mjs","names":["principalId: string","effect: 'Allow' | 'Deny'","resource: string","context?: Record<string, string | number | boolean>","policyDocument: PolicyDocument","methodArn: string","options: OidcAuthorizerOptions<TClaims>","event: APIGatewayTokenAuthorizerEvent","_context: LambdaContext","event: APIGatewayRequestAuthorizerEvent"],"sources":["../../src/lambda/oidc.ts"],"sourcesContent":["import type {\n\tAPIGatewayAuthorizerResult,\n\tAPIGatewayRequestAuthorizerEvent,\n\tAPIGatewayTokenAuthorizerEvent,\n\tContext as LambdaContext,\n\tPolicyDocument,\n} from 'aws-lambda';\nimport {\n\ttype OidcClaims,\n\ttype OidcConfig,\n\tOidcVerifier,\n\ttype TokenExtractionOptions,\n} from '../oidc';\n\nexport {\n\tOidcVerifier,\n\ttype OidcClaims,\n\ttype OidcConfig,\n\ttype TokenExtractionOptions,\n};\n\nfunction generatePolicy(\n\tprincipalId: string,\n\teffect: 'Allow' | 'Deny',\n\tresource: string,\n\tcontext?: Record<string, string | number | boolean>,\n): APIGatewayAuthorizerResult {\n\tconst policyDocument: PolicyDocument = {\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tAction: 'execute-api:Invoke',\n\t\t\t\tEffect: effect,\n\t\t\t\tResource: resource,\n\t\t\t},\n\t\t],\n\t};\n\n\treturn {\n\t\tprincipalId,\n\t\tpolicyDocument,\n\t\tcontext,\n\t};\n}\n\nfunction getWildcardResource(methodArn: string): string {\n\tconst parts = methodArn.split('/');\n\treturn `${parts[0]}/${parts[1]}/*`;\n}\n\nexport interface OidcAuthorizerOptions<\n\tTClaims extends OidcClaims = OidcClaims,\n> {\n\tconfig: OidcConfig;\n\textraction?: TokenExtractionOptions;\n\twildcardResource?: boolean;\n\tgetPrincipalId?: (claims: TClaims) => string;\n\tgetContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tauthorize?: (claims: TClaims) => boolean | Promise<boolean>;\n}\n\n/**\n * OIDC Lambda Authorizer\n *\n * @example\n * ```typescript\n * const authorizer = new OidcAuthorizer({\n * config: {\n * issuer: 'https://auth.example.com',\n * audience: 'my-api',\n * },\n * getContext: (claims) => ({ userId: claims.sub! }),\n * });\n *\n * export const tokenHandler = authorizer.tokenHandler();\n * export const requestHandler = authorizer.requestHandler();\n * ```\n */\nexport class OidcAuthorizer<TClaims extends OidcClaims = OidcClaims> {\n\tprivate readonly verifier: OidcVerifier<TClaims>;\n\tprivate readonly extraction: TokenExtractionOptions;\n\tprivate readonly wildcardResource: boolean;\n\tprivate readonly getPrincipalId: (claims: TClaims) => string;\n\tprivate readonly getContext?: (\n\t\tclaims: TClaims,\n\t) => Record<string, string | number | boolean> | undefined;\n\tprivate readonly authorize?: (claims: TClaims) => boolean | Promise<boolean>;\n\n\tconstructor(options: OidcAuthorizerOptions<TClaims>) {\n\t\tthis.verifier = new OidcVerifier(options.config);\n\t\tthis.extraction = options.extraction ?? {};\n\t\tthis.wildcardResource = options.wildcardResource ?? true;\n\t\tthis.getPrincipalId = options.getPrincipalId ?? ((c) => c.sub ?? 'unknown');\n\t\tthis.getContext = options.getContext;\n\t\tthis.authorize = options.authorize;\n\t}\n\n\ttokenHandler() {\n\t\treturn async (\n\t\t\tevent: APIGatewayTokenAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst { authorizationToken, methodArn } = event;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = authorizationToken.startsWith('Bearer ')\n\t\t\t\t? authorizationToken.slice(7)\n\t\t\t\t: authorizationToken;\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n\n\trequestHandler() {\n\t\tconst {\n\t\t\theaderName = 'authorization',\n\t\t\tcookieName,\n\t\t\ttokenPrefix = 'Bearer ',\n\t\t} = this.extraction;\n\n\t\tconst extractToken = (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t): string | null => {\n\t\t\tconst headers = event.headers ?? {};\n\t\t\tconst headerKey = Object.keys(headers).find(\n\t\t\t\t(k) => k.toLowerCase() === headerName.toLowerCase(),\n\t\t\t);\n\t\t\tif (headerKey) {\n\t\t\t\tconst headerValue = headers[headerKey];\n\t\t\t\tif (headerValue) {\n\t\t\t\t\tif (tokenPrefix && headerValue.startsWith(tokenPrefix)) {\n\t\t\t\t\t\treturn headerValue.slice(tokenPrefix.length);\n\t\t\t\t\t}\n\t\t\t\t\treturn headerValue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (cookieName) {\n\t\t\t\tconst cookieHeader = headers.cookie ?? headers.Cookie ?? '';\n\t\t\t\tconst match = cookieHeader.match(new RegExp(`${cookieName}=([^;]+)`));\n\t\t\t\tif (match?.[1]) {\n\t\t\t\t\treturn match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn null;\n\t\t};\n\n\t\treturn async (\n\t\t\tevent: APIGatewayRequestAuthorizerEvent,\n\t\t\t_context: LambdaContext,\n\t\t): Promise<APIGatewayAuthorizerResult> => {\n\t\t\tconst methodArn = event.methodArn;\n\t\t\tconst resource = this.wildcardResource\n\t\t\t\t? getWildcardResource(methodArn)\n\t\t\t\t: methodArn;\n\n\t\t\tconst token = extractToken(event);\n\n\t\t\tif (!token) {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst claims = await this.verifier.verify(token);\n\n\t\t\t\tif (this.authorize) {\n\t\t\t\t\tconst isAuthorized = await this.authorize(claims);\n\t\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst principalId = this.getPrincipalId(claims);\n\t\t\t\tconst context = this.getContext?.(claims);\n\n\t\t\t\treturn generatePolicy(principalId, 'Allow', resource, context);\n\t\t\t} catch {\n\t\t\t\treturn generatePolicy('unauthorized', 'Deny', resource);\n\t\t\t}\n\t\t};\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"oidc-C0KyYaAK.cjs","names":["config: OidcConfig","token: string"],"sources":["../src/oidc.ts"],"sourcesContent":["import * as jose from 'jose';\nimport type { JwtClaims, TokenExtractionOptions } from './jwt';\n\nexport type { TokenExtractionOptions };\n\n/**\n * Standard OIDC claims (extends JWT claims)\n */\nexport interface OidcClaims extends JwtClaims {\n nonce?: string;\n auth_time?: number;\n at_hash?: string;\n c_hash?: string;\n azp?: string;\n}\n\n/**\n * Standard OIDC user info claims\n */\nexport interface OidcUserInfo {\n sub: string;\n name?: string;\n given_name?: string;\n family_name?: string;\n middle_name?: string;\n nickname?: string;\n preferred_username?: string;\n profile?: string;\n picture?: string;\n website?: string;\n email?: string;\n email_verified?: boolean;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n phone_number?: string;\n phone_number_verified?: boolean;\n address?: {\n formatted?: string;\n street_address?: string;\n locality?: string;\n region?: string;\n postal_code?: string;\n country?: string;\n };\n updated_at?: number;\n}\n\n/**\n * OIDC Discovery document\n */\nexport interface OidcDiscovery {\n issuer: string;\n authorization_endpoint: string;\n token_endpoint: string;\n userinfo_endpoint?: string;\n jwks_uri: string;\n scopes_supported?: string[];\n response_types_supported: string[];\n claims_supported?: string[];\n}\n\n/**\n * Configuration for OIDC verification\n */\nexport interface OidcConfig {\n issuer: string;\n audience: string | string[];\n cacheDiscovery?: boolean;\n}\n\n/**\n * OIDC Verifier with auto-discovery and caching\n */\nexport class OidcVerifier<\n TClaims extends OidcClaims = OidcClaims,\n TUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n private discovery: OidcDiscovery | null = null;\n private jwks: jose.JWTVerifyGetKey | null = null;\n private readonly discoveryUrl: string;\n\n constructor(private readonly config: OidcConfig) {\n this.discoveryUrl = config.issuer.endsWith('/')\n ? `${config.issuer}.well-known/openid-configuration`\n : `${config.issuer}/.well-known/openid-configuration`;\n }\n\n async getDiscovery(): Promise<OidcDiscovery> {\n if (this.discovery && this.config.cacheDiscovery !== false) {\n return this.discovery;\n }\n\n const response = await fetch(this.discoveryUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch OIDC discovery: ${response.statusText}`);\n }\n\n this.discovery = (await response.json()) as OidcDiscovery;\n return this.discovery;\n }\n\n private async getJwks(): Promise<jose.JWTVerifyGetKey> {\n if (this.jwks && this.config.cacheDiscovery !== false) {\n return this.jwks;\n }\n\n const disc = await this.getDiscovery();\n this.jwks = jose.createRemoteJWKSet(new URL(disc.jwks_uri));\n return this.jwks;\n }\n\n async verify(token: string): Promise<TClaims> {\n const key = await this.getJwks();\n const { payload } = await jose.jwtVerify(token, key, {\n issuer: this.config.issuer,\n audience: this.config.audience,\n });\n return payload as unknown as TClaims;\n }\n\n async verifyOrNull(token: string): Promise<TClaims | null> {\n try {\n return await this.verify(token);\n } catch {\n return null;\n }\n }\n\n async fetchUserInfo(token: string): Promise<TUserInfo | null> {\n try {\n const disc = await this.getDiscovery();\n if (!disc.userinfo_endpoint) {\n return null;\n }\n\n const response = await fetch(disc.userinfo_endpoint, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as TUserInfo;\n } catch {\n return null;\n }\n }\n\n clearCache(): void {\n this.discovery = null;\n this.jwks = null;\n }\n}\n"],"mappings":";;;;;;;AA2EA,IAAa,eAAb,MAGE;CACA,AAAQ,YAAkC;CAC1C,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAoB;EAApB;AAC3B,OAAK,eAAe,OAAO,OAAO,SAAS,IAAI,IAC1C,EAAE,OAAO,OAAO,qCAChB,EAAE,OAAO,OAAO;CACtB;CAED,MAAM,eAAuC;AAC3C,MAAI,KAAK,aAAa,KAAK,OAAO,mBAAmB,MACnD,QAAO,KAAK;EAGd,MAAM,WAAW,MAAM,MAAM,KAAK,aAAa;AAC/C,OAAK,SAAS,GACZ,OAAM,IAAI,OAAO,kCAAkC,SAAS,WAAW;AAGzE,OAAK,YAAa,MAAM,SAAS,MAAM;AACvC,SAAO,KAAK;CACb;CAED,MAAc,UAAyC;AACrD,MAAI,KAAK,QAAQ,KAAK,OAAO,mBAAmB,MAC9C,QAAO,KAAK;EAGd,MAAM,OAAO,MAAM,KAAK,cAAc;AACtC,OAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,UAAU;AAC3D,SAAO,KAAK;CACb;CAED,MAAM,OAAOC,OAAiC;EAC5C,MAAM,MAAM,MAAM,KAAK,SAAS;EAChC,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,KAAK;GACnD,QAAQ,KAAK,OAAO;GACpB,UAAU,KAAK,OAAO;EACvB,EAAC;AACF,SAAO;CACR;CAED,MAAM,aAAaA,OAAwC;AACzD,MAAI;AACF,UAAO,MAAM,KAAK,OAAO,MAAM;EAChC,QAAO;AACN,UAAO;EACR;CACF;CAED,MAAM,cAAcA,OAA0C;AAC5D,MAAI;GACF,MAAM,OAAO,MAAM,KAAK,cAAc;AACtC,QAAK,KAAK,kBACR,QAAO;GAGT,MAAM,WAAW,MAAM,MAAM,KAAK,mBAAmB,EACnD,SAAS,EAAE,gBAAgB,SAAS,MAAM,EAAG,EAC9C,EAAC;AAEF,QAAK,SAAS,GACZ,QAAO;AAGT,UAAQ,MAAM,SAAS,MAAM;EAC9B,QAAO;AACN,UAAO;EACR;CACF;CAED,aAAmB;AACjB,OAAK,YAAY;AACjB,OAAK,OAAO;CACb;AACF"}
1
+ {"version":3,"file":"oidc-C0KyYaAK.cjs","names":["config: OidcConfig","token: string"],"sources":["../src/oidc.ts"],"sourcesContent":["import * as jose from 'jose';\nimport type { JwtClaims, TokenExtractionOptions } from './jwt';\n\nexport type { TokenExtractionOptions };\n\n/**\n * Standard OIDC claims (extends JWT claims)\n */\nexport interface OidcClaims extends JwtClaims {\n\tnonce?: string;\n\tauth_time?: number;\n\tat_hash?: string;\n\tc_hash?: string;\n\tazp?: string;\n}\n\n/**\n * Standard OIDC user info claims\n */\nexport interface OidcUserInfo {\n\tsub: string;\n\tname?: string;\n\tgiven_name?: string;\n\tfamily_name?: string;\n\tmiddle_name?: string;\n\tnickname?: string;\n\tpreferred_username?: string;\n\tprofile?: string;\n\tpicture?: string;\n\twebsite?: string;\n\temail?: string;\n\temail_verified?: boolean;\n\tgender?: string;\n\tbirthdate?: string;\n\tzoneinfo?: string;\n\tlocale?: string;\n\tphone_number?: string;\n\tphone_number_verified?: boolean;\n\taddress?: {\n\t\tformatted?: string;\n\t\tstreet_address?: string;\n\t\tlocality?: string;\n\t\tregion?: string;\n\t\tpostal_code?: string;\n\t\tcountry?: string;\n\t};\n\tupdated_at?: number;\n}\n\n/**\n * OIDC Discovery document\n */\nexport interface OidcDiscovery {\n\tissuer: string;\n\tauthorization_endpoint: string;\n\ttoken_endpoint: string;\n\tuserinfo_endpoint?: string;\n\tjwks_uri: string;\n\tscopes_supported?: string[];\n\tresponse_types_supported: string[];\n\tclaims_supported?: string[];\n}\n\n/**\n * Configuration for OIDC verification\n */\nexport interface OidcConfig {\n\tissuer: string;\n\taudience: string | string[];\n\tcacheDiscovery?: boolean;\n}\n\n/**\n * OIDC Verifier with auto-discovery and caching\n */\nexport class OidcVerifier<\n\tTClaims extends OidcClaims = OidcClaims,\n\tTUserInfo extends OidcUserInfo = OidcUserInfo,\n> {\n\tprivate discovery: OidcDiscovery | null = null;\n\tprivate jwks: jose.JWTVerifyGetKey | null = null;\n\tprivate readonly discoveryUrl: string;\n\n\tconstructor(private readonly config: OidcConfig) {\n\t\tthis.discoveryUrl = config.issuer.endsWith('/')\n\t\t\t? `${config.issuer}.well-known/openid-configuration`\n\t\t\t: `${config.issuer}/.well-known/openid-configuration`;\n\t}\n\n\tasync getDiscovery(): Promise<OidcDiscovery> {\n\t\tif (this.discovery && this.config.cacheDiscovery !== false) {\n\t\t\treturn this.discovery;\n\t\t}\n\n\t\tconst response = await fetch(this.discoveryUrl);\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to fetch OIDC discovery: ${response.statusText}`);\n\t\t}\n\n\t\tthis.discovery = (await response.json()) as OidcDiscovery;\n\t\treturn this.discovery;\n\t}\n\n\tprivate async getJwks(): Promise<jose.JWTVerifyGetKey> {\n\t\tif (this.jwks && this.config.cacheDiscovery !== false) {\n\t\t\treturn this.jwks;\n\t\t}\n\n\t\tconst disc = await this.getDiscovery();\n\t\tthis.jwks = jose.createRemoteJWKSet(new URL(disc.jwks_uri));\n\t\treturn this.jwks;\n\t}\n\n\tasync verify(token: string): Promise<TClaims> {\n\t\tconst key = await this.getJwks();\n\t\tconst { payload } = await jose.jwtVerify(token, key, {\n\t\t\tissuer: this.config.issuer,\n\t\t\taudience: this.config.audience,\n\t\t});\n\t\treturn payload as unknown as TClaims;\n\t}\n\n\tasync verifyOrNull(token: string): Promise<TClaims | null> {\n\t\ttry {\n\t\t\treturn await this.verify(token);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tasync fetchUserInfo(token: string): Promise<TUserInfo | null> {\n\t\ttry {\n\t\t\tconst disc = await this.getDiscovery();\n\t\t\tif (!disc.userinfo_endpoint) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst response = await fetch(disc.userinfo_endpoint, {\n\t\t\t\theaders: { Authorization: `Bearer ${token}` },\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn (await response.json()) as TUserInfo;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tclearCache(): void {\n\t\tthis.discovery = null;\n\t\tthis.jwks = null;\n\t}\n}\n"],"mappings":";;;;;;;AA2EA,IAAa,eAAb,MAGE;CACD,AAAQ,YAAkC;CAC1C,AAAQ,OAAoC;CAC5C,AAAiB;CAEjB,YAA6BA,QAAoB;EAApB;AAC5B,OAAK,eAAe,OAAO,OAAO,SAAS,IAAI,IAC3C,EAAE,OAAO,OAAO,qCAChB,EAAE,OAAO,OAAO;CACpB;CAED,MAAM,eAAuC;AAC5C,MAAI,KAAK,aAAa,KAAK,OAAO,mBAAmB,MACpD,QAAO,KAAK;EAGb,MAAM,WAAW,MAAM,MAAM,KAAK,aAAa;AAC/C,OAAK,SAAS,GACb,OAAM,IAAI,OAAO,kCAAkC,SAAS,WAAW;AAGxE,OAAK,YAAa,MAAM,SAAS,MAAM;AACvC,SAAO,KAAK;CACZ;CAED,MAAc,UAAyC;AACtD,MAAI,KAAK,QAAQ,KAAK,OAAO,mBAAmB,MAC/C,QAAO,KAAK;EAGb,MAAM,OAAO,MAAM,KAAK,cAAc;AACtC,OAAK,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK,UAAU;AAC3D,SAAO,KAAK;CACZ;CAED,MAAM,OAAOC,OAAiC;EAC7C,MAAM,MAAM,MAAM,KAAK,SAAS;EAChC,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,UAAU,OAAO,KAAK;GACpD,QAAQ,KAAK,OAAO;GACpB,UAAU,KAAK,OAAO;EACtB,EAAC;AACF,SAAO;CACP;CAED,MAAM,aAAaA,OAAwC;AAC1D,MAAI;AACH,UAAO,MAAM,KAAK,OAAO,MAAM;EAC/B,QAAO;AACP,UAAO;EACP;CACD;CAED,MAAM,cAAcA,OAA0C;AAC7D,MAAI;GACH,MAAM,OAAO,MAAM,KAAK,cAAc;AACtC,QAAK,KAAK,kBACT,QAAO;GAGR,MAAM,WAAW,MAAM,MAAM,KAAK,mBAAmB,EACpD,SAAS,EAAE,gBAAgB,SAAS,MAAM,EAAG,EAC7C,EAAC;AAEF,QAAK,SAAS,GACb,QAAO;AAGR,UAAQ,MAAM,SAAS,MAAM;EAC7B,QAAO;AACP,UAAO;EACP;CACD;CAED,aAAmB;AAClB,OAAK,YAAY;AACjB,OAAK,OAAO;CACZ;AACD"}
@@ -1,4 +1,4 @@
1
- import { JwtClaims } from "./jwt-DH8CJ2xC.mjs";
1
+ import { JwtClaims } from "./jwt-3eIuY2dg.cjs";
2
2
 
3
3
  //#region src/oidc.d.ts
4
4
 
@@ -81,6 +81,7 @@ declare class OidcVerifier<TClaims extends OidcClaims = OidcClaims, TUserInfo ex
81
81
  fetchUserInfo(token: string): Promise<TUserInfo | null>;
82
82
  clearCache(): void;
83
83
  }
84
+ //# sourceMappingURL=oidc.d.ts.map
84
85
  //#endregion
85
86
  export { OidcClaims, OidcConfig, OidcDiscovery, OidcUserInfo, OidcVerifier };
86
- //# sourceMappingURL=oidc-CKOGLxjV.d.mts.map
87
+ //# sourceMappingURL=oidc-ChA17wLB.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-ChA17wLB.d.cts","names":[],"sources":["../src/oidc.ts"],"sourcesContent":[],"mappings":";;;;;AAQA;AAWA;AAiCiB,UA5CA,UAAA,SAAmB,SA4CN,CAAA;EAcb,KAAA,CAAA,EAAA,MAAU;EASd,SAAA,CAAA,EAAA,MAAY;EAAA,OAAA,CAAA,EAAA,MAAA;EAAA,MACR,CAAA,EAAA,MAAA;EAAU,GAAG,CAAA,EAAA,MAAA;;;;;AAaP,UAtEN,YAAA,CAsEM;EAAO,GAwBQ,EAAA,MAAA;EAAO,IAAf,CAAA,EAAA,MAAA;EAAO,UASO,CAAA,EAAA,MAAA;EAAO,WAAf,CAAA,EAAA,MAAA;EAAO,WAQE,CAAA,EAAA,MAAA;EAAS,QAAjB,CAAA,EAAA,MAAA;EAAO,kBAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;UA9E3B,aAAA;;;;;;;;;;;;;UAcA,UAAA;;;;;;;;cASJ,6BACI,aAAa,8BACX,eAAe;;;;;sBAMI;kBAMf,QAAQ;;yBAwBD,QAAQ;+BASF,QAAQ;gCAQP,QAAQ"}