bezzie 0.1.1 → 0.1.5
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.
- package/README.md +45 -1
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +19 -0
- package/dist/discovery.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +70 -56
- package/dist/middleware.js.map +1 -1
- package/dist/routes.d.ts +2 -2
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +46 -40
- package/dist/routes.js.map +1 -1
- package/dist/session.d.ts +9 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/package.json +15 -11
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
|
+
[](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
|
-
| `
|
|
94
|
+
| `POST /auth/logout` | Clears session, clears cookie, redirects to provider logout. |
|
|
51
95
|
|
|
52
96
|
---
|
|
53
97
|
|
|
@@ -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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -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.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -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
|
|
63
|
+
catch {
|
|
63
64
|
throw new Error('Bezzie: issuer must be a valid URL');
|
|
64
65
|
}
|
|
65
|
-
const
|
|
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 };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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;
|
|
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"}
|
package/dist/middleware.d.ts
CHANGED
|
@@ -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
|
|
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
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +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,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;
|
|
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"}
|
package/dist/middleware.js
CHANGED
|
@@ -1,75 +1,89 @@
|
|
|
1
1
|
import { getCookie } from 'hono/cookie';
|
|
2
2
|
import * as oauth from 'oauth4webapi';
|
|
3
|
-
|
|
4
|
-
|
|
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 middleware(config) {
|
|
3
|
+
import { getAuthorizationServer } from './discovery';
|
|
4
|
+
export function middleware(config, cache) {
|
|
23
5
|
const sessionStore = config.adapter;
|
|
24
6
|
return async (c, next) => {
|
|
25
7
|
// 1. Read the sessionId cookie from the request
|
|
26
|
-
const sessionId = getCookie(c, '
|
|
8
|
+
const sessionId = getCookie(c, config.cookieName ?? '__Host-session');
|
|
27
9
|
// 2. If no cookie → return 401
|
|
28
10
|
if (!sessionId) {
|
|
29
11
|
return c.text('Unauthorized', 401);
|
|
30
12
|
}
|
|
31
13
|
// 3. Look up the session in KV using SessionStore
|
|
32
|
-
|
|
14
|
+
let session = await sessionStore.get(sessionId);
|
|
33
15
|
// 4. If no session found or it's a PKCE state → return 401
|
|
34
16
|
if (!session || 'codeVerifier' in session) {
|
|
35
17
|
return c.text('Unauthorized', 401);
|
|
36
18
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
client_id: config.clientId,
|
|
43
|
-
client_secret: config.clientSecret,
|
|
44
|
-
token_endpoint_auth_method: 'client_secret_post',
|
|
45
|
-
};
|
|
46
|
-
const response = await oauth.refreshTokenGrantRequest(as, client, session.refreshToken);
|
|
47
|
-
const result = await oauth.processRefreshTokenResponse(as, client, response);
|
|
48
|
-
if (oauth.isOAuth2Error(result)) {
|
|
49
|
-
await sessionStore.delete(sessionId);
|
|
50
|
-
return c.text('Unauthorized', 401);
|
|
51
|
-
}
|
|
52
|
-
// Update the session in KV with new tokens and new expiresAt
|
|
53
|
-
session.accessToken = result.access_token;
|
|
54
|
-
if (result.refresh_token) {
|
|
55
|
-
session.refreshToken = result.refresh_token;
|
|
56
|
-
}
|
|
57
|
-
session.expiresAt = Math.floor(Date.now() / 1000) + (result.expires_in || 3600);
|
|
58
|
-
await sessionStore.set(sessionId, session, 30 * 24 * 60 * 60); // 30 days, matches initial session TTL
|
|
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');
|
|
59
24
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
+
}
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
+
}
|
|
73
87
|
}
|
|
74
88
|
// 10. Attach the user and accessToken to Hono context
|
|
75
89
|
c.set('user', session.user);
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,sBAAsB,EAAuB,MAAM,aAAa,CAAA;AAoBzE,MAAM,UAAU,UAAU,CAAC,MAAoB,EAAE,KAAqB;IACpE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAA;IAEnC,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,gDAAgD;QAChD,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,IAAI,gBAAgB,CAAC,CAAA;QAErE,+BAA+B;QAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QACpC,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAE/C,2DAA2D;QAC3D,IAAI,CAAC,OAAO,IAAI,cAAc,IAAI,OAAO,EAAE,CAAC;YAC1C,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;QACpC,CAAC;QAED,kDAAkD;QAClD,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA,CAAC,UAAU;QACpD,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,eAAe,EAAE,CAAC;YACxE,MAAM,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;YACpC,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,IAAI,aAAa,CAAC,CAAA;QACtD,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAEtD,qEAAqE;QACrE,IAAI,OAAO,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,EAAE,CAAC;YAClF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,oEAAoE;oBACpE,MAAM,MAAM,GAAiB,EAAE,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAA;oBAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;oBAE9D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;oBAEnG,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,2BAA2B,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;wBAC5E,6DAA6D;wBAC7D,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,YAAY,CAAA;wBACzC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;4BACzB,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,aAAa,CAAA;wBAC7C,CAAC;wBACD,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAA;wBAE/E,MAAM,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,iBAAiB,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA,CAAC,uCAAuC;oBACnI,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,IAAI,GAAG,YAAY,KAAK,CAAC,iBAAiB,IAAI,GAAG,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;4BAC5E,oFAAoF;4BACpF,MAAM,gBAAgB,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;4BAC1D,IACE,gBAAgB;gCAChB,CAAC,CAAC,cAAc,IAAI,gBAAgB,CAAC;gCACrC,gBAAgB,CAAC,WAAW,KAAK,OAAO,CAAC,WAAW,EACpD,CAAC;gCACD,uDAAuD;gCACvD,OAAO,GAAG,gBAAgB,CAAA;4BAC5B,CAAC;iCAAM,CAAC;gCACN,eAAe;gCACf,MAAM,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;gCACpC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;4BACpC,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,MAAM,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;4BACpC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;wBACpC,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;oBACpC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAED,qFAAqF;QACrF,IAAI,MAAM,CAAC,mBAAmB,KAAK,KAAK,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC5D,IAAI,CAAC;gBACH,wFAAwF;gBACxF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE;oBACzC,OAAO,EAAE;wBACP,aAAa,EAAE,UAAU,OAAO,CAAC,WAAW,EAAE;qBAC/C;iBACF,CAAC,CAAA;gBAEF,MAAM,KAAK,CAAC,sBAAsB,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;YAC1G,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;gBACjC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;YACpC,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;QAEzC,kBAAkB;QAClB,MAAM,IAAI,EAAE,CAAA;IACd,CAAC,CAAA;AACH,CAAC"}
|
package/dist/routes.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
+
import { type DiscoveryCache } from './discovery';
|
|
2
3
|
import type { BezzieConfig } from './index';
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function authRoutes(config: BezzieConfig): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
4
|
+
export declare function authRoutes(config: BezzieConfig, cache: DiscoveryCache): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
5
5
|
//# sourceMappingURL=routes.d.ts.map
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;
|
|
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"}
|
package/dist/routes.js
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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, '
|
|
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.
|
|
103
|
-
const sessionId = getCookie(c, '
|
|
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, '
|
|
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
|
package/dist/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/session.d.ts
CHANGED
|
@@ -9,11 +9,19 @@ export interface Session {
|
|
|
9
9
|
/**
|
|
10
10
|
* OAuth refresh token.
|
|
11
11
|
*/
|
|
12
|
-
refreshToken
|
|
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
|
*/
|
package/dist/session.d.ts.map
CHANGED
|
@@ -1 +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,EAAE,MAAM,CAAA;
|
|
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"}
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAwCA,cAAc,YAAY,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bezzie",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "BFF OAuth 2.0 auth library for Cloudflare Workers",
|
|
6
|
+
"keywords": ["hono", "cloudflare-workers", "oauth", "oidc", "auth", "bff", "session", "jwt", "pkce"],
|
|
5
7
|
"main": "dist/index.js",
|
|
6
8
|
"types": "dist/index.d.ts",
|
|
7
9
|
"exports": {
|
|
@@ -22,25 +24,27 @@
|
|
|
22
24
|
"dev": "wrangler dev",
|
|
23
25
|
"build": "tsc",
|
|
24
26
|
"test": "vitest run",
|
|
25
|
-
"lint": "eslint src test
|
|
27
|
+
"lint": "eslint src test",
|
|
26
28
|
"format": "prettier --write src test",
|
|
27
29
|
"prepublishOnly": "npm run build && npm test && npm run lint"
|
|
28
30
|
},
|
|
29
31
|
"dependencies": {
|
|
30
|
-
"oauth4webapi": "^
|
|
32
|
+
"oauth4webapi": "^3.8.5"
|
|
31
33
|
},
|
|
32
34
|
"peerDependencies": {
|
|
33
35
|
"hono": "^4.0.0"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
|
-
"@cloudflare/vitest-pool-workers": "^0.
|
|
37
|
-
"@cloudflare/workers-types": "^4.
|
|
38
|
-
"@
|
|
39
|
-
"@typescript-eslint/
|
|
40
|
-
"eslint": "^8.0.0",
|
|
38
|
+
"@cloudflare/vitest-pool-workers": "^0.14.1",
|
|
39
|
+
"@cloudflare/workers-types": "^4.20260317.1",
|
|
40
|
+
"@eslint/js": "^9.0.0",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
42
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
43
|
+
"eslint": "^10.1.0",
|
|
41
44
|
"prettier": "^3.0.0",
|
|
42
|
-
"typescript": "^
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
+
"typescript": "^6.0.2",
|
|
46
|
+
"typescript-eslint": "^8.0.0",
|
|
47
|
+
"vitest": "^4.1.1",
|
|
48
|
+
"wrangler": "^4.77.0"
|
|
45
49
|
}
|
|
46
50
|
}
|