bezzie 0.1.1 → 0.1.4

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 (81) hide show
  1. package/README.md +45 -1
  2. package/dist/src/adapters/cloudflare-kv.d.ts.map +1 -0
  3. package/dist/src/adapters/cloudflare-kv.js.map +1 -0
  4. package/dist/src/adapters/index.d.ts.map +1 -0
  5. package/dist/src/adapters/index.js.map +1 -0
  6. package/dist/src/adapters/memory.d.ts.map +1 -0
  7. package/dist/src/adapters/memory.js.map +1 -0
  8. package/dist/src/adapters/redis.d.ts.map +1 -0
  9. package/dist/src/adapters/redis.js.map +1 -0
  10. package/dist/src/adapters/types.d.ts.map +1 -0
  11. package/dist/{adapters → src/adapters}/types.js.map +1 -1
  12. package/dist/src/discovery.d.ts +10 -0
  13. package/dist/src/discovery.d.ts.map +1 -0
  14. package/dist/src/discovery.js +19 -0
  15. package/dist/src/discovery.js.map +1 -0
  16. package/dist/{index.d.ts → src/index.d.ts} +39 -0
  17. package/dist/src/index.d.ts.map +1 -0
  18. package/dist/{index.js → src/index.js} +6 -3
  19. package/dist/src/index.js.map +1 -0
  20. package/dist/{middleware.d.ts → src/middleware.d.ts} +2 -2
  21. package/dist/src/middleware.d.ts.map +1 -0
  22. package/dist/src/middleware.js +95 -0
  23. package/dist/src/middleware.js.map +1 -0
  24. package/dist/src/routes.d.ts +5 -0
  25. package/dist/src/routes.d.ts.map +1 -0
  26. package/dist/{routes.js → src/routes.js} +46 -40
  27. package/dist/src/routes.js.map +1 -0
  28. package/dist/{session.d.ts → src/session.d.ts} +9 -1
  29. package/dist/src/session.d.ts.map +1 -0
  30. package/dist/src/session.js.map +1 -0
  31. package/dist/test/index.test.d.ts +2 -0
  32. package/dist/test/index.test.d.ts.map +1 -0
  33. package/dist/test/index.test.js +96 -0
  34. package/dist/test/index.test.js.map +1 -0
  35. package/dist/test/middleware.test.d.ts +2 -0
  36. package/dist/test/middleware.test.d.ts.map +1 -0
  37. package/dist/test/middleware.test.js +340 -0
  38. package/dist/test/middleware.test.js.map +1 -0
  39. package/dist/test/routes.test.d.ts +2 -0
  40. package/dist/test/routes.test.d.ts.map +1 -0
  41. package/dist/test/routes.test.js +284 -0
  42. package/dist/test/routes.test.js.map +1 -0
  43. package/dist/test/session.test.d.ts +2 -0
  44. package/dist/test/session.test.d.ts.map +1 -0
  45. package/dist/test/session.test.js +96 -0
  46. package/dist/test/session.test.js.map +1 -0
  47. package/dist/vitest.config.d.ts +3 -0
  48. package/dist/vitest.config.d.ts.map +1 -0
  49. package/dist/vitest.config.js +10 -0
  50. package/dist/vitest.config.js.map +1 -0
  51. package/package.json +14 -10
  52. package/dist/adapters/cloudflare-kv.d.ts.map +0 -1
  53. package/dist/adapters/cloudflare-kv.js.map +0 -1
  54. package/dist/adapters/index.d.ts.map +0 -1
  55. package/dist/adapters/index.js.map +0 -1
  56. package/dist/adapters/memory.d.ts.map +0 -1
  57. package/dist/adapters/memory.js.map +0 -1
  58. package/dist/adapters/redis.d.ts.map +0 -1
  59. package/dist/adapters/redis.js.map +0 -1
  60. package/dist/adapters/types.d.ts.map +0 -1
  61. package/dist/index.d.ts.map +0 -1
  62. package/dist/index.js.map +0 -1
  63. package/dist/middleware.d.ts.map +0 -1
  64. package/dist/middleware.js +0 -81
  65. package/dist/middleware.js.map +0 -1
  66. package/dist/routes.d.ts +0 -5
  67. package/dist/routes.d.ts.map +0 -1
  68. package/dist/routes.js.map +0 -1
  69. package/dist/session.d.ts.map +0 -1
  70. package/dist/session.js.map +0 -1
  71. /package/dist/{adapters → src/adapters}/cloudflare-kv.d.ts +0 -0
  72. /package/dist/{adapters → src/adapters}/cloudflare-kv.js +0 -0
  73. /package/dist/{adapters → src/adapters}/index.d.ts +0 -0
  74. /package/dist/{adapters → src/adapters}/index.js +0 -0
  75. /package/dist/{adapters → src/adapters}/memory.d.ts +0 -0
  76. /package/dist/{adapters → src/adapters}/memory.js +0 -0
  77. /package/dist/{adapters → src/adapters}/redis.d.ts +0 -0
  78. /package/dist/{adapters → src/adapters}/redis.js +0 -0
  79. /package/dist/{adapters → src/adapters}/types.d.ts +0 -0
  80. /package/dist/{adapters → src/adapters}/types.js +0 -0
  81. /package/dist/{session.js → src/session.js} +0 -0
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  **Bezzie** — your BFF's BFF. Handles the Backend for Frontend OAuth pattern so you don't have to.
4
4
 
5
+ [![npm downloads](https://img.shields.io/npm/dw/bezzie)](https://www.npmjs.com/package/bezzie)
6
+
5
7
  A BFF (Backend for Frontend) OAuth 2.0 auth library for Cloudflare Workers.
6
8
 
7
9
  Implements the [OAuth 2.0 for Browser-Based Apps (BCP212)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) pattern — JWTs never touch the browser. The BFF owns the OAuth flow and issues a session cookie to the frontend instead.
@@ -10,6 +12,48 @@ Implements the [OAuth 2.0 for Browser-Based Apps (BCP212)](https://datatracker.i
10
12
  npm install bezzie
11
13
  ```
12
14
 
15
+ ## Get started in 5 minutes
16
+
17
+ **1. Install:**
18
+ ```sh
19
+ npm install bezzie
20
+ ```
21
+
22
+ **2. Add a KV namespace to `wrangler.toml`:**
23
+ ```toml
24
+ [[kv_namespaces]]
25
+ binding = "SESSION_KV"
26
+ id = "<your-kv-namespace-id>"
27
+ ```
28
+
29
+ **3. Add your client secret:**
30
+ ```sh
31
+ wrangler secret put AUTH0_CLIENT_SECRET
32
+ ```
33
+
34
+ **4. Wire it up:**
35
+ ```typescript
36
+ import { createBezzie, providers, cloudflareKV } from 'bezzie'
37
+
38
+ const auth = createBezzie({
39
+ ...providers.auth0('your-tenant.auth0.com'),
40
+ clientId: 'xxx',
41
+ clientSecret: env.AUTH0_CLIENT_SECRET,
42
+ adapter: cloudflareKV(env.SESSION_KV),
43
+ baseUrl: 'https://app.yourproject.com',
44
+ })
45
+
46
+ app.route('/auth', auth.routes())
47
+ app.use('/api/*', auth.middleware())
48
+ ```
49
+
50
+ **5. Protect a route:**
51
+ ```typescript
52
+ app.get('/api/me', (c) => c.json(c.var.user))
53
+ ```
54
+
55
+ Done. Your app now has BCP212-compliant BFF auth.
56
+
13
57
  ---
14
58
 
15
59
  ## Why
@@ -47,7 +91,7 @@ This gives you:
47
91
  |---|---|
48
92
  | `GET /auth/login` | Redirects to provider, initiates Authorization Code + PKCE flow. Supports `returnTo` query param for post-login redirect. |
49
93
  | `GET /auth/callback` | Exchanges code for tokens, stores session in KV, sets cookie. |
50
- | `GET /auth/logout` | Clears session, clears cookie, redirects to provider logout. |
94
+ | `POST /auth/logout` | Clears session, clears cookie, redirects to provider logout. |
51
95
 
52
96
  ---
53
97
 
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-kv.d.ts","sourceRoot":"","sources":["../../../src/adapters/cloudflare-kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEnD,qBAAa,mBAAoB,YAAW,cAAc;IAC5C,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAE7B,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IAK3D,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASvF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-kv.js","sourceRoot":"","sources":["../../../src/adapters/cloudflare-kv.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,mBAAmB;IACV;IAApB,YAAoB,EAAe;QAAf,OAAE,GAAF,EAAE,CAAa;IAAG,CAAC;IAEvC,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAsB,SAAS,EAAE,MAAM,CAAC,CAAA;QACzE,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,OAA4B,EAAE,UAAkB;QAC3E,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;QAC/D,CAAC;QACD,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;YACpD,aAAa,EAAE,UAAU;SAC1B,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC5B,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/adapters/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAOnD,qBAAa,aAAc,YAAW,cAAc;IAClD,OAAO,CAAC,KAAK,CAAmC;IAE1C,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IAU3D,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/adapters/memory.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,aAAa;IAChB,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAA;IAEhD,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QACvB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YAC5B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,OAA4B,EAAE,UAAkB;QAC3E,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE;YACxB,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI;SAC1C,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC9B,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../src/adapters/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEnD,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACnC;AAED,qBAAa,YAAa,YAAW,cAAc;IACrC,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,WAAW;IAEhC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IAM3D,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG/C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/adapters/redis.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,YAAY;IACH;IAApB,YAAoB,KAAkB;QAAlB,UAAK,GAAL,KAAK,CAAa;IAAG,CAAC;IAE1C,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAA;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAwB,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,OAA4B,EAAE,UAAkB;QAC3E,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;IAC9E,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEpC;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,CAAA;IAE3D;;;;;;OAMG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEvF;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import * as oauth from 'oauth4webapi';
2
+ import type { BezzieConfig } from './index';
3
+ export interface DiscoveryCache {
4
+ cachedAS: oauth.AuthorizationServer | null;
5
+ cacheExpiresAt: number;
6
+ jwksCache: oauth.JWKSCacheInput;
7
+ }
8
+ export declare function createDiscoveryCache(): DiscoveryCache;
9
+ export declare function getAuthorizationServer(config: BezzieConfig, cache: DiscoveryCache): Promise<oauth.AuthorizationServer>;
10
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAA;IAC1C,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,KAAK,CAAC,cAAc,CAAA;CAChC;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAapC"}
@@ -0,0 +1,19 @@
1
+ import * as oauth from 'oauth4webapi';
2
+ export function createDiscoveryCache() {
3
+ return { cachedAS: null, cacheExpiresAt: 0, jwksCache: {} };
4
+ }
5
+ export async function getAuthorizationServer(config, cache) {
6
+ if (cache.cachedAS && Date.now() < cache.cacheExpiresAt) {
7
+ return cache.cachedAS;
8
+ }
9
+ const issuer = new URL(config.issuer);
10
+ const response = await oauth.discoveryRequest(issuer);
11
+ const as = await oauth.processDiscoveryResponse(issuer, response);
12
+ const cachedAS = config.providerHints?.tokenEndpoint
13
+ ? { ...as, token_endpoint: config.providerHints.tokenEndpoint }
14
+ : as;
15
+ cache.cachedAS = cachedAS;
16
+ cache.cacheExpiresAt = Date.now() + 60 * 60 * 1000;
17
+ return cachedAS;
18
+ }
19
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AASrC,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAA;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAoB,EACpB,KAAqB;IAErB,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC,QAAQ,CAAA;IACvB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACrD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,EAAE,aAAa;QAClD,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,aAAa,CAAC,aAAa,EAAE;QAC/D,CAAC,CAAC,EAAE,CAAA;IACN,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;IACzB,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAClD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { Hono, type MiddlewareHandler } from 'hono';
2
2
  import { type Variables } from './middleware';
3
+ import { type DiscoveryCache } from './discovery';
3
4
  import { type SessionAdapter } from './session';
4
5
  /**
5
6
  * Configuration for Bezzie.
@@ -29,6 +30,14 @@ export interface BezzieConfig {
29
30
  * Base URL of your application (used for callback and redirects).
30
31
  */
31
32
  baseUrl: string;
33
+ /**
34
+ * Optional path to the login route (defaults to /auth/login).
35
+ */
36
+ loginPath?: string;
37
+ /**
38
+ * Whether to validate the access token (defaults to true).
39
+ */
40
+ validateAccessToken?: boolean;
32
41
  /**
33
42
  * Optional tweaks for specific providers.
34
43
  */
@@ -42,6 +51,31 @@ export interface BezzieConfig {
42
51
  */
43
52
  tokenEndpoint?: string;
44
53
  };
54
+ /**
55
+ * Session TTL in seconds.
56
+ * @default 60 * 60 * 24 * 30 (30 days)
57
+ */
58
+ sessionTtlSeconds?: number;
59
+ /**
60
+ * PKCE state TTL in seconds.
61
+ * @default 60 * 10 (10 minutes)
62
+ */
63
+ pkceStateTtlSeconds?: number;
64
+ /**
65
+ * Session cookie name.
66
+ * @default '__Host-session'
67
+ */
68
+ cookieName?: string;
69
+ /**
70
+ * OAuth scopes to request.
71
+ * @default ['openid', 'profile', 'email', 'offline_access']
72
+ */
73
+ scopes?: string[];
74
+ /**
75
+ * Buffer in seconds for refreshing the access token before it expires.
76
+ * @default 60
77
+ */
78
+ refreshBufferSeconds?: number;
45
79
  }
46
80
  /**
47
81
  * Common OIDC provider configurations.
@@ -93,6 +127,11 @@ export interface Bezzie {
93
127
  middleware: () => MiddlewareHandler<{
94
128
  Variables: Variables;
95
129
  }>;
130
+ /**
131
+ * Internal discovery cache.
132
+ * @internal
133
+ */
134
+ cache: DiscoveryCache;
96
135
  }
97
136
  /**
98
137
  * Creates a new Bezzie instance.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAEnD,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAEpE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAA;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,OAAO,EAAE,cAAc,CAAA;IAEvB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAE7B;;OAEG;IACH,aAAa,CAAC,EAAE;QACd;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,CAAA;QAElB;;WAEG;QACH,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IAED;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAE5B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IAEjB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB;;OAEG;oBACa,MAAM;;;;;;IAOtB;;OAEG;mBACY,MAAM;;;IAIrB;;OAEG;wBACiB,MAAM,SAAS,MAAM;;;IAIzC;;OAEG;;;;CAIJ,CAAA;AAED;;GAEG;AACH,iBAAS,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,cAAc,CAErD;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAA;IAElB;;OAEG;IACH,UAAU,EAAE,MAAM,iBAAiB,CAAC;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE,CAAC,CAAA;IAE7D;;;OAGG;IACH,KAAK,EAAE,cAAc,CAAA;CACtB;AAED;;;;;;GAMG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA0BlD;AAED,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAA;AACrC,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { authRoutes } from './routes';
2
2
  import { middleware } from './middleware';
3
+ import { createDiscoveryCache } from './discovery';
3
4
  import { CloudflareKVAdapter } from './session';
4
5
  /**
5
6
  * Common OIDC provider configurations.
@@ -59,13 +60,15 @@ function createBezzie(config) {
59
60
  try {
60
61
  new URL(config.issuer);
61
62
  }
62
- catch (e) {
63
+ catch {
63
64
  throw new Error('Bezzie: issuer must be a valid URL');
64
65
  }
65
- const router = authRoutes(config);
66
+ const cache = createDiscoveryCache();
67
+ const router = authRoutes(config, cache);
66
68
  return {
67
69
  routes: () => router,
68
- middleware: () => middleware(config),
70
+ middleware: () => middleware(config, cache),
71
+ cache,
69
72
  };
70
73
  }
71
74
  export { createBezzie, cloudflareKV };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,UAAU,EAAkB,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAuB,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAE,mBAAmB,EAAuB,MAAM,WAAW,CAAA;AA4FpE;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB;;OAEG;IACH,KAAK,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;QAC1B,MAAM,EAAE,WAAW,MAAM,EAAE;QAC3B,aAAa,EAAE;YACb,SAAS,EAAE,WAAW,MAAM,YAAY;SACzC;KACF,CAAC;IAEF;;OAEG;IACH,IAAI,EAAE,CAAC,MAAc,EAAE,EAAE,CAAC,CAAC;QACzB,MAAM,EAAE,WAAW,MAAM,iBAAiB;KAC3C,CAAC;IAEF;;OAEG;IACH,QAAQ,EAAE,CAAC,OAAe,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,GAAG,OAAO,WAAW,KAAK,EAAE;KACrC,CAAC;IAEF;;OAEG;IACH,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACb,MAAM,EAAE,6BAA6B;KACtC,CAAC;CACH,CAAA;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,EAAe;IACnC,OAAO,IAAI,mBAAmB,CAAC,EAAE,CAAC,CAAA;AACpC,CAAC;AAuBD;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,MAAoB;IACxC,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;IAC7E,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,GAAyB,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IACvD,CAAC;IAED,MAAM,KAAK,GAAG,oBAAoB,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAExC,OAAO;QACL,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM;QACpB,UAAU,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;QAC3C,KAAK;KACN,CAAA;AACH,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAA;AAGrC,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import type { MiddlewareHandler } from 'hono';
2
+ import { type DiscoveryCache } from './discovery';
2
3
  import type { Session } from './session';
3
4
  import type { BezzieConfig } from './index';
4
5
  /**
@@ -15,8 +16,7 @@ export type Variables = {
15
16
  */
16
17
  accessToken: string;
17
18
  };
18
- export declare function _resetDiscoveryCache(): void;
19
- export declare function middleware(config: BezzieConfig): MiddlewareHandler<{
19
+ export declare function middleware(config: BezzieConfig, cache: DiscoveryCache): MiddlewareHandler<{
20
20
  Variables: Variables;
21
21
  }>;
22
22
  //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAG7C,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IACrB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAGD,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,GAAG,iBAAiB,CAAC;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE,CAAC,CAqGnH"}
@@ -0,0 +1,95 @@
1
+ import { getCookie } from 'hono/cookie';
2
+ import * as oauth from 'oauth4webapi';
3
+ import { getAuthorizationServer } from './discovery';
4
+ export function middleware(config, cache) {
5
+ const sessionStore = config.adapter;
6
+ return async (c, next) => {
7
+ // 1. Read the sessionId cookie from the request
8
+ const sessionId = getCookie(c, config.cookieName ?? '__Host-session');
9
+ // 2. If no cookie → return 401
10
+ if (!sessionId) {
11
+ return c.text('Unauthorized', 401);
12
+ }
13
+ // 3. Look up the session in KV using SessionStore
14
+ let session = await sessionStore.get(sessionId);
15
+ // 4. If no session found or it's a PKCE state → return 401
16
+ if (!session || 'codeVerifier' in session) {
17
+ return c.text('Unauthorized', 401);
18
+ }
19
+ // 4.5 Check for absolute session expiry (90 days)
20
+ const MAX_SESSION_AGE = 90 * 24 * 60 * 60; // 90 days
21
+ if (Math.floor(Date.now() / 1000) - session.createdAt > MAX_SESSION_AGE) {
22
+ await sessionStore.delete(sessionId);
23
+ return c.redirect(config.loginPath ?? '/auth/login');
24
+ }
25
+ const as = await getAuthorizationServer(config, cache);
26
+ // 5. Check if the access token is expired (with configurable buffer)
27
+ if (session.expiresAt < (Date.now() / 1000) + (config.refreshBufferSeconds ?? 60)) {
28
+ if (session.refreshToken) {
29
+ try {
30
+ // 6. If expired → use oauth4webapi to perform a refresh token grant
31
+ const client = { client_id: config.clientId };
32
+ const clientAuth = oauth.ClientSecretPost(config.clientSecret);
33
+ const response = await oauth.refreshTokenGrantRequest(as, client, clientAuth, session.refreshToken);
34
+ try {
35
+ const result = await oauth.processRefreshTokenResponse(as, client, response);
36
+ // Update the session in KV with new tokens and new expiresAt
37
+ session.accessToken = result.access_token;
38
+ if (result.refresh_token) {
39
+ session.refreshToken = result.refresh_token;
40
+ }
41
+ session.expiresAt = Math.floor(Date.now() / 1000) + (result.expires_in || 3600);
42
+ await sessionStore.set(sessionId, session, config.sessionTtlSeconds ?? 30 * 24 * 60 * 60); // 30 days, matches initial session TTL
43
+ }
44
+ catch (err) {
45
+ if (err instanceof oauth.ResponseBodyError && err.error === 'invalid_grant') {
46
+ // Potential race condition: another request might have already refreshed this token
47
+ const refreshedSession = await sessionStore.get(sessionId);
48
+ if (refreshedSession &&
49
+ !('codeVerifier' in refreshedSession) &&
50
+ refreshedSession.accessToken !== session.accessToken) {
51
+ // Someone else already refreshed it! Use that session.
52
+ session = refreshedSession;
53
+ }
54
+ else {
55
+ // Truly failed
56
+ await sessionStore.delete(sessionId);
57
+ return c.text('Unauthorized', 401);
58
+ }
59
+ }
60
+ else {
61
+ await sessionStore.delete(sessionId);
62
+ return c.text('Unauthorized', 401);
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ await sessionStore.delete(sessionId);
68
+ return c.text('Unauthorized', 401);
69
+ }
70
+ }
71
+ }
72
+ // 8. Validate the JWT using JWKS (only if audience is set and validation is enabled)
73
+ if (config.validateAccessToken !== false && config.audience) {
74
+ try {
75
+ // We need a Request object that has the Authorization header for validateJwtAccessToken
76
+ const mockReq = new Request(c.req.raw.url, {
77
+ headers: {
78
+ Authorization: `Bearer ${session.accessToken}`,
79
+ },
80
+ });
81
+ await oauth.validateJwtAccessToken(as, mockReq, config.audience, { [oauth.jwksCache]: cache.jwksCache });
82
+ }
83
+ catch {
84
+ // 9. If JWT invalid → return 401
85
+ return c.text('Unauthorized', 401);
86
+ }
87
+ }
88
+ // 10. Attach the user and accessToken to Hono context
89
+ c.set('user', session.user);
90
+ c.set('accessToken', session.accessToken);
91
+ // 12. Call next()
92
+ await next();
93
+ };
94
+ }
95
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import { type DiscoveryCache } from './discovery';
3
+ import type { BezzieConfig } from './index';
4
+ export declare function authRoutes(config: BezzieConfig, cache: DiscoveryCache): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
5
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,8EAmKrE"}
@@ -1,25 +1,8 @@
1
1
  import { Hono } from 'hono';
2
2
  import { getCookie, setCookie, deleteCookie } from 'hono/cookie';
3
3
  import * as oauth from 'oauth4webapi';
4
- let cachedAS = null;
5
- let cacheExpiresAt = 0;
6
- async function getAuthorizationServer(config) {
7
- if (cachedAS && Date.now() < cacheExpiresAt)
8
- return cachedAS;
9
- const issuerUrl = new URL(config.issuer);
10
- const response = await oauth.discoveryRequest(issuerUrl);
11
- const as = await oauth.processDiscoveryResponse(issuerUrl, response);
12
- cachedAS = config.providerHints?.tokenEndpoint
13
- ? { ...as, token_endpoint: config.providerHints.tokenEndpoint }
14
- : as;
15
- cacheExpiresAt = Date.now() + 60 * 60 * 1000; // 1 hour
16
- return cachedAS;
17
- }
18
- export function _resetDiscoveryCache() {
19
- cachedAS = null;
20
- cacheExpiresAt = 0;
21
- }
22
- export function authRoutes(config) {
4
+ import { getAuthorizationServer } from './discovery';
5
+ export function authRoutes(config, cache) {
23
6
  const router = new Hono();
24
7
  const sessionStore = config.adapter;
25
8
  router.get('/login', async (c) => {
@@ -28,8 +11,8 @@ export function authRoutes(config) {
28
11
  const state = oauth.generateRandomState();
29
12
  const returnTo = c.req.query('returnTo');
30
13
  // Store state and codeVerifier in adapter
31
- await config.adapter.set(`pkce:${state}`, { codeVerifier: code_verifier, returnTo }, 600); // 10 minutes
32
- const as = await getAuthorizationServer(config);
14
+ await config.adapter.set(`pkce:${state}`, { codeVerifier: code_verifier, returnTo }, config.pkceStateTtlSeconds ?? 600); // 10 minutes
15
+ const as = await getAuthorizationServer(config, cache);
33
16
  if (!as.authorization_endpoint) {
34
17
  return c.text('Missing authorization_endpoint', 500);
35
18
  }
@@ -37,7 +20,7 @@ export function authRoutes(config) {
37
20
  authorizationUrl.searchParams.set('client_id', config.clientId);
38
21
  authorizationUrl.searchParams.set('response_type', 'code');
39
22
  authorizationUrl.searchParams.set('redirect_uri', `${config.baseUrl}/auth/callback`);
40
- authorizationUrl.searchParams.set('scope', 'openid profile email offline_access');
23
+ authorizationUrl.searchParams.set('scope', (config.scopes ?? ['openid', 'profile', 'email', 'offline_access']).join(' '));
41
24
  authorizationUrl.searchParams.set('state', state);
42
25
  authorizationUrl.searchParams.set('code_challenge', code_challenge);
43
26
  authorizationUrl.searchParams.set('code_challenge_method', 'S256');
@@ -62,24 +45,35 @@ export function authRoutes(config) {
62
45
  }
63
46
  const { codeVerifier, returnTo } = stored;
64
47
  await config.adapter.delete(`pkce:${state}`);
65
- const as = await getAuthorizationServer(config);
66
- const client = {
67
- client_id: config.clientId,
68
- client_secret: config.clientSecret,
69
- token_endpoint_auth_method: 'client_secret_post',
70
- };
71
- const response = await oauth.authorizationCodeGrantRequest(as, client, new URL(c.req.url).searchParams, `${config.baseUrl}/auth/callback`, codeVerifier);
72
- const result = await oauth.processAuthorizationCodeOpenIDResponse(as, client, response);
73
- if (oauth.isOAuth2Error(result)) {
74
- return c.text('OAuth 2.0 error', 400);
48
+ const as = await getAuthorizationServer(config, cache);
49
+ const client = { client_id: config.clientId };
50
+ const clientAuth = oauth.ClientSecretPost(config.clientSecret);
51
+ const response = await oauth.authorizationCodeGrantRequest(as, client, clientAuth, new URL(c.req.url).searchParams, `${config.baseUrl}/auth/callback`, codeVerifier);
52
+ let result;
53
+ try {
54
+ result = await oauth.processAuthorizationCodeResponse(as, client, response);
75
55
  }
76
- const { access_token, refresh_token, expires_in } = result;
56
+ catch (err) {
57
+ if (err instanceof oauth.ResponseBodyError) {
58
+ return c.text('OAuth 2.0 error', 400);
59
+ }
60
+ throw err;
61
+ }
62
+ const { access_token, refresh_token, expires_in, id_token } = result;
77
63
  const claims = oauth.getValidatedIdTokenClaims(result);
64
+ if (!claims) {
65
+ return c.json({ error: 'id_token missing from token response' }, 500);
66
+ }
67
+ if (!refresh_token) {
68
+ console.warn('Bezzie: refresh_token is missing from the token response. offline_access may not be enabled or supported by the provider.');
69
+ }
78
70
  const sessionId = crypto.randomUUID();
79
71
  const session = {
80
72
  accessToken: access_token,
81
- refreshToken: refresh_token || '',
73
+ refreshToken: refresh_token,
74
+ idToken: id_token,
82
75
  expiresAt: Math.floor(Date.now() / 1000) + (expires_in || 3600),
76
+ createdAt: Math.floor(Date.now() / 1000),
83
77
  user: {
84
78
  ...claims,
85
79
  sub: claims.sub,
@@ -87,38 +81,50 @@ export function authRoutes(config) {
87
81
  },
88
82
  };
89
83
  // TTL for session in KV. Set to 30 days as per bug fix 3.
90
- await sessionStore.set(sessionId, session, 30 * 24 * 60 * 60);
91
- setCookie(c, 'sessionId', sessionId, {
84
+ await sessionStore.set(sessionId, session, config.sessionTtlSeconds ?? 30 * 24 * 60 * 60);
85
+ setCookie(c, config.cookieName ?? '__Host-session', sessionId, {
92
86
  httpOnly: true,
93
87
  secure: true,
94
88
  sameSite: 'Strict',
95
89
  path: '/',
90
+ maxAge: config.sessionTtlSeconds ?? 30 * 24 * 60 * 60, // 30 days, matches KV session TTL
96
91
  });
97
92
  if (returnTo && returnTo.startsWith('/') && !returnTo.startsWith('//')) {
98
93
  return c.redirect(returnTo);
99
94
  }
100
95
  return c.redirect('/');
101
96
  });
102
- router.get('/logout', async (c) => {
103
- const sessionId = getCookie(c, 'sessionId');
97
+ router.post('/logout', async (c) => {
98
+ const sessionId = getCookie(c, config.cookieName ?? '__Host-session');
99
+ let idToken;
104
100
  if (sessionId) {
101
+ const session = await sessionStore.get(sessionId);
102
+ if (session && !('codeVerifier' in session)) {
103
+ idToken = session.idToken;
104
+ }
105
105
  await sessionStore.delete(sessionId);
106
106
  }
107
- deleteCookie(c, 'sessionId', {
107
+ deleteCookie(c, config.cookieName ?? '__Host-session', {
108
108
  path: '/',
109
109
  secure: true,
110
110
  });
111
- const as = await getAuthorizationServer(config);
111
+ const as = await getAuthorizationServer(config, cache);
112
112
  let logoutUrl;
113
113
  if (config.providerHints?.logoutUrl) {
114
114
  logoutUrl = new URL(config.providerHints.logoutUrl);
115
115
  logoutUrl.searchParams.set('client_id', config.clientId);
116
116
  logoutUrl.searchParams.set('returnTo', config.baseUrl);
117
+ if (idToken) {
118
+ logoutUrl.searchParams.set('id_token_hint', idToken);
119
+ }
117
120
  }
118
121
  else if (as.end_session_endpoint) {
119
122
  logoutUrl = new URL(as.end_session_endpoint);
120
123
  logoutUrl.searchParams.set('client_id', config.clientId);
121
124
  logoutUrl.searchParams.set('post_logout_redirect_uri', config.baseUrl);
125
+ if (idToken) {
126
+ logoutUrl.searchParams.set('id_token_hint', idToken);
127
+ }
122
128
  }
123
129
  else {
124
130
  // If no endpoint found, we just redirect to base URL
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"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"}
@@ -9,11 +9,19 @@ export interface Session {
9
9
  /**
10
10
  * OAuth refresh token.
11
11
  */
12
- refreshToken: string;
12
+ refreshToken?: string;
13
+ /**
14
+ * OAuth ID token.
15
+ */
16
+ idToken?: string;
13
17
  /**
14
18
  * Expiration time of the access token as a Unix timestamp (seconds).
15
19
  */
16
20
  expiresAt: number;
21
+ /**
22
+ * Creation time of the session as a Unix timestamp (seconds).
23
+ */
24
+ createdAt: number;
17
25
  /**
18
26
  * User information from the ID token or userinfo endpoint.
19
27
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE;QACJ;;WAEG;QACH,GAAG,EAAE,MAAM,CAAA;QACX;;WAEG;QACH,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,CAAA;CACF;AAED,cAAc,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAwCA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../test/index.test.ts"],"names":[],"mappings":""}