bezzie 0.2.2 → 1.0.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.
- package/README.md +41 -16
- package/dist/adapters/cloudflare-kv.d.ts +5 -1
- package/dist/adapters/cloudflare-kv.d.ts.map +1 -1
- package/dist/adapters/cloudflare-kv.js +8 -1
- package/dist/adapters/cloudflare-kv.js.map +1 -1
- package/dist/adapters/memory.d.ts +17 -1
- package/dist/adapters/memory.d.ts.map +1 -1
- package/dist/adapters/memory.js +32 -1
- package/dist/adapters/memory.js.map +1 -1
- package/dist/adapters/redis.d.ts +38 -1
- package/dist/adapters/redis.d.ts.map +1 -1
- package/dist/adapters/redis.js +39 -0
- package/dist/adapters/redis.js.map +1 -1
- package/dist/adapters/types.d.ts +14 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/discovery.d.ts +13 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +5 -4
- package/dist/discovery.js.map +1 -1
- package/dist/errors.d.ts +28 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +31 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +109 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -14
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +65 -7
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +32 -10
- 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 +130 -22
- package/dist/routes.js.map +1 -1
- package/dist/session.d.ts +9 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/package.json +23 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Hono, type MiddlewareHandler } from 'hono';
|
|
2
|
-
import { middleware, optionalMiddleware, type
|
|
3
|
-
import {
|
|
4
|
-
import { type SessionAdapter } from './session';
|
|
2
|
+
import { middleware, optionalMiddleware, type AuthenticatedVariables, type OptionalVariables, type LoginHookContext, type RefreshHookContext, type LogoutHookContext, type HookErrorContext } from './middleware';
|
|
3
|
+
import type { SessionAdapter, SessionAdapterFactory } from './session';
|
|
5
4
|
/**
|
|
6
5
|
* Configuration for Bezzie.
|
|
7
6
|
*/
|
|
@@ -23,15 +22,44 @@ export interface BezzieConfig<TUser extends Record<string, unknown> = Record<str
|
|
|
23
22
|
*/
|
|
24
23
|
audience?: string;
|
|
25
24
|
/**
|
|
26
|
-
* Session adapter (e.g. `
|
|
25
|
+
* Session adapter factory (e.g. `cloudflareKVAdapter(env.SESSION_KV)`).
|
|
26
|
+
*
|
|
27
|
+
* The factory is called once during `createBezzie` with `TUser` inferred from
|
|
28
|
+
* the `createBezzie` type parameter, so callers don't need to specify `TUser`
|
|
29
|
+
* twice.
|
|
27
30
|
*/
|
|
28
|
-
adapter:
|
|
31
|
+
adapter: SessionAdapterFactory;
|
|
29
32
|
/**
|
|
30
33
|
* Base URL of your application (used for callback and redirects).
|
|
31
34
|
*/
|
|
32
35
|
baseUrl: string;
|
|
36
|
+
/**
|
|
37
|
+
* Custom route paths for Bezzie's internal auth routes.
|
|
38
|
+
*
|
|
39
|
+
* Note: the `callback` path used for the OAuth redirect URI defaults to
|
|
40
|
+
* `/auth/callback` to match the common pattern of mounting the Bezzie
|
|
41
|
+
* router under `/auth`.
|
|
42
|
+
*/
|
|
43
|
+
routes?: {
|
|
44
|
+
/**
|
|
45
|
+
* Path for the login route.
|
|
46
|
+
* @default '/login'
|
|
47
|
+
*/
|
|
48
|
+
login?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Path for the callback route.
|
|
51
|
+
* @default '/callback'
|
|
52
|
+
*/
|
|
53
|
+
callback?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Path for the logout route.
|
|
56
|
+
* @default '/logout'
|
|
57
|
+
*/
|
|
58
|
+
logout?: string;
|
|
59
|
+
};
|
|
33
60
|
/**
|
|
34
61
|
* Optional path to the login route (defaults to /auth/login).
|
|
62
|
+
* @deprecated Use `routes.login` instead.
|
|
35
63
|
*/
|
|
36
64
|
loginPath?: string;
|
|
37
65
|
/**
|
|
@@ -39,9 +67,9 @@ export interface BezzieConfig<TUser extends Record<string, unknown> = Record<str
|
|
|
39
67
|
*/
|
|
40
68
|
validateAccessToken?: boolean;
|
|
41
69
|
/**
|
|
42
|
-
*
|
|
70
|
+
* Hard overrides for specific provider values that cannot be derived from discovery.
|
|
43
71
|
*/
|
|
44
|
-
|
|
72
|
+
providerOverrides?: {
|
|
45
73
|
/**
|
|
46
74
|
* Custom logout URL if different from the default OIDC logout.
|
|
47
75
|
*/
|
|
@@ -68,7 +96,22 @@ export interface BezzieConfig<TUser extends Record<string, unknown> = Record<str
|
|
|
68
96
|
cookieName?: string;
|
|
69
97
|
/**
|
|
70
98
|
* OAuth scopes to request.
|
|
99
|
+
*
|
|
100
|
+
* Providing a value **replaces** the default list entirely — it does not
|
|
101
|
+
* extend it. If you set `scopes`, you must explicitly include every scope
|
|
102
|
+
* you need.
|
|
103
|
+
*
|
|
104
|
+
* In particular, include `'offline_access'` if you want Bezzie to be able
|
|
105
|
+
* to refresh access tokens; without it the provider will not issue a
|
|
106
|
+
* refresh token and sessions will terminate when the access token expires.
|
|
107
|
+
*
|
|
71
108
|
* @default ['openid', 'profile', 'email', 'offline_access']
|
|
109
|
+
* @example
|
|
110
|
+
* // Good — includes offline_access for refresh support:
|
|
111
|
+
* scopes: ['openid', 'profile', 'email', 'offline_access', 'read:things']
|
|
112
|
+
*
|
|
113
|
+
* // Bad — no refresh token will be issued:
|
|
114
|
+
* scopes: ['openid', 'read:things']
|
|
72
115
|
*/
|
|
73
116
|
scopes?: string[];
|
|
74
117
|
/**
|
|
@@ -76,7 +119,48 @@ export interface BezzieConfig<TUser extends Record<string, unknown> = Record<str
|
|
|
76
119
|
* @default 60
|
|
77
120
|
*/
|
|
78
121
|
refreshBufferSeconds?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Optional function to map and validate raw ID token claims to TUser.
|
|
124
|
+
* Called in /callback after the ID token is validated.
|
|
125
|
+
* If provided, its return value is used as session.user instead of the raw claims.
|
|
126
|
+
* If it throws, the login is aborted, the partial session is deleted, and a 500 is returned.
|
|
127
|
+
* Use this to validate claims with Zod or any other schema library.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* mapClaims: (claims) => MyUserSchema.parse(claims)
|
|
131
|
+
*/
|
|
132
|
+
mapClaims?: (claims: unknown) => TUser | Promise<TUser>;
|
|
133
|
+
/**
|
|
134
|
+
* Called at the end of /callback after the session is created.
|
|
135
|
+
* Awaited. If it throws, the login is aborted and the partial session is deleted.
|
|
136
|
+
* Use c.executionCtx?.waitUntil() for non-critical background work.
|
|
137
|
+
*/
|
|
138
|
+
onLogin?: (ctx: LoginHookContext<TUser>) => Promise<void> | void;
|
|
139
|
+
/**
|
|
140
|
+
* Called in middleware after a successful token refresh.
|
|
141
|
+
* Awaited, but errors are caught and routed to onError — the request continues.
|
|
142
|
+
*/
|
|
143
|
+
onRefresh?: (ctx: RefreshHookContext<TUser>) => Promise<void> | void;
|
|
144
|
+
/**
|
|
145
|
+
* Called at /logout after the session is deleted.
|
|
146
|
+
* Awaited, but errors are caught and routed to onError — logout always succeeds.
|
|
147
|
+
*/
|
|
148
|
+
onLogout?: (ctx: LogoutHookContext<TUser>) => Promise<void> | void;
|
|
149
|
+
/**
|
|
150
|
+
* Called when a non-fatal hook throws (onRefresh, onLogout).
|
|
151
|
+
* Defaults to console.error. onLogin errors still bubble.
|
|
152
|
+
*/
|
|
153
|
+
onError?: (err: unknown, ctx: HookErrorContext) => void;
|
|
79
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Resolved Bezzie configuration where the adapter factory has been invoked.
|
|
157
|
+
*
|
|
158
|
+
* Internal — routes and middleware use this so they can call `config.adapter.get(...)`
|
|
159
|
+
* etc. directly, rather than dealing with a factory function.
|
|
160
|
+
*/
|
|
161
|
+
export type ResolvedBezzieConfig<TUser extends Record<string, unknown> = Record<string, unknown>> = Omit<BezzieConfig<TUser>, 'adapter'> & {
|
|
162
|
+
adapter: SessionAdapter<TUser>;
|
|
163
|
+
};
|
|
80
164
|
/**
|
|
81
165
|
* Common OIDC provider configurations.
|
|
82
166
|
*/
|
|
@@ -84,35 +168,25 @@ export declare const providers: {
|
|
|
84
168
|
/**
|
|
85
169
|
* Auth0 provider configuration.
|
|
86
170
|
*/
|
|
87
|
-
auth0: (domain: string) =>
|
|
88
|
-
issuer: string;
|
|
89
|
-
providerHints: {
|
|
90
|
-
logoutUrl: string;
|
|
91
|
-
};
|
|
92
|
-
};
|
|
171
|
+
auth0: (domain: string) => Pick<BezzieConfig, "issuer" | "providerOverrides">;
|
|
93
172
|
/**
|
|
94
173
|
* Okta provider configuration.
|
|
95
174
|
*/
|
|
96
|
-
okta: (domain: string) =>
|
|
97
|
-
issuer: string;
|
|
98
|
-
};
|
|
175
|
+
okta: (domain: string) => Pick<BezzieConfig, "issuer">;
|
|
99
176
|
/**
|
|
100
177
|
* Keycloak provider configuration.
|
|
101
178
|
*/
|
|
102
|
-
keycloak: (baseUrl: string, realm: string) =>
|
|
103
|
-
issuer: string;
|
|
104
|
-
};
|
|
179
|
+
keycloak: (baseUrl: string, realm: string) => Pick<BezzieConfig, "issuer">;
|
|
105
180
|
/**
|
|
106
181
|
* Google provider configuration.
|
|
107
182
|
*/
|
|
108
|
-
google: () =>
|
|
109
|
-
issuer: string;
|
|
110
|
-
};
|
|
183
|
+
google: () => Pick<BezzieConfig, "issuer">;
|
|
111
184
|
};
|
|
112
185
|
/**
|
|
113
|
-
*
|
|
186
|
+
* Helper for consumers writing custom adapters — provides type inference for
|
|
187
|
+
* the factory function without any runtime behaviour.
|
|
114
188
|
*/
|
|
115
|
-
declare function
|
|
189
|
+
export declare function defineAdapter(factory: SessionAdapterFactory): SessionAdapterFactory;
|
|
116
190
|
/**
|
|
117
191
|
* The main Bezzie interface.
|
|
118
192
|
*/
|
|
@@ -125,30 +199,30 @@ export interface Bezzie<TUser extends Record<string, unknown> = Record<string, u
|
|
|
125
199
|
* Returns a Hono middleware that protects routes and manages sessions.
|
|
126
200
|
*/
|
|
127
201
|
middleware: () => MiddlewareHandler<{
|
|
128
|
-
Variables:
|
|
202
|
+
Variables: AuthenticatedVariables<TUser>;
|
|
129
203
|
}>;
|
|
130
204
|
/**
|
|
131
205
|
* Returns a Hono middleware that sets user context if a session exists but always calls next().
|
|
132
206
|
*/
|
|
133
207
|
optionalMiddleware: () => MiddlewareHandler<{
|
|
134
|
-
Variables:
|
|
208
|
+
Variables: OptionalVariables<TUser>;
|
|
135
209
|
}>;
|
|
136
|
-
/**
|
|
137
|
-
* Internal discovery cache.
|
|
138
|
-
* @internal
|
|
139
|
-
*/
|
|
140
|
-
cache: DiscoveryCache;
|
|
141
210
|
}
|
|
142
211
|
/**
|
|
143
212
|
* Creates a new Bezzie instance.
|
|
144
213
|
*
|
|
145
214
|
* @param config Bezzie configuration
|
|
146
215
|
* @returns Bezzie instance
|
|
147
|
-
* @throws {
|
|
216
|
+
* @throws {ConfigError} if required configuration is missing or invalid
|
|
148
217
|
*/
|
|
149
218
|
declare function createBezzie<TUser extends Record<string, unknown> = Record<string, unknown>>(config: BezzieConfig<TUser>): Bezzie<TUser>;
|
|
150
|
-
export { createBezzie,
|
|
151
|
-
export
|
|
152
|
-
export
|
|
219
|
+
export { createBezzie, middleware, optionalMiddleware };
|
|
220
|
+
export { cloudflareKVAdapter } from './adapters/cloudflare-kv';
|
|
221
|
+
export { redisAdapter } from './adapters/redis';
|
|
222
|
+
export { memoryAdapter } from './adapters/memory';
|
|
223
|
+
export type { Variables, AuthenticatedVariables, OptionalVariables, LoginHookContext, RefreshHookContext, LogoutHookContext, HookErrorContext, } from './middleware';
|
|
224
|
+
export type { SessionAdapter, SessionAdapterFactory, PKCEState, Session, StoredSession } from './session';
|
|
153
225
|
export { CloudflareKVAdapter, RedisAdapter, MemoryAdapter } from './session';
|
|
226
|
+
export { BezzieError, DiscoveryError, CallbackError, TokenExchangeError, RefreshError, SessionStoreError, ConfigError, } from './errors';
|
|
227
|
+
export type { BezzieErrorCode, BezzieErrorOptions } from './errors';
|
|
154
228
|
//# sourceMappingURL=index.d.ts.map
|
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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { authRoutes } from './routes';
|
|
2
|
-
import { middleware, optionalMiddleware } from './middleware';
|
|
2
|
+
import { middleware, optionalMiddleware, } from './middleware';
|
|
3
3
|
import { createDiscoveryCache } from './discovery';
|
|
4
|
-
import {
|
|
4
|
+
import { ConfigError } from './errors';
|
|
5
5
|
/**
|
|
6
6
|
* Common OIDC provider configurations.
|
|
7
7
|
*/
|
|
@@ -11,7 +11,7 @@ export const providers = {
|
|
|
11
11
|
*/
|
|
12
12
|
auth0: (domain) => ({
|
|
13
13
|
issuer: `https://${domain}`,
|
|
14
|
-
|
|
14
|
+
providerOverrides: {
|
|
15
15
|
logoutUrl: `https://${domain}/v2/logout`,
|
|
16
16
|
},
|
|
17
17
|
}),
|
|
@@ -35,43 +35,50 @@ export const providers = {
|
|
|
35
35
|
}),
|
|
36
36
|
};
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* Helper for consumers writing custom adapters — provides type inference for
|
|
39
|
+
* the factory function without any runtime behaviour.
|
|
39
40
|
*/
|
|
40
|
-
function
|
|
41
|
-
return
|
|
41
|
+
export function defineAdapter(factory) {
|
|
42
|
+
return factory;
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
44
45
|
* Creates a new Bezzie instance.
|
|
45
46
|
*
|
|
46
47
|
* @param config Bezzie configuration
|
|
47
48
|
* @returns Bezzie instance
|
|
48
|
-
* @throws {
|
|
49
|
+
* @throws {ConfigError} if required configuration is missing or invalid
|
|
49
50
|
*/
|
|
50
51
|
function createBezzie(config) {
|
|
51
52
|
const required = ['issuer', 'clientId', 'clientSecret', 'adapter', 'baseUrl'];
|
|
52
53
|
for (const key of required) {
|
|
53
54
|
if (!config[key]) {
|
|
54
|
-
throw new
|
|
55
|
+
throw new ConfigError('config_invalid', `Bezzie: missing required config: ${key}`);
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
if (!config.issuer.startsWith('https://')) {
|
|
58
|
-
throw new
|
|
59
|
+
throw new ConfigError('config_invalid', 'Bezzie: issuer must start with https://');
|
|
59
60
|
}
|
|
60
61
|
try {
|
|
61
62
|
new URL(config.issuer);
|
|
62
63
|
}
|
|
63
64
|
catch {
|
|
64
|
-
throw new
|
|
65
|
+
throw new ConfigError('config_invalid', 'Bezzie: issuer must be a valid URL');
|
|
65
66
|
}
|
|
67
|
+
const adapter = config.adapter();
|
|
68
|
+
const resolvedConfig = { ...config, adapter };
|
|
66
69
|
const cache = createDiscoveryCache();
|
|
67
|
-
const router = authRoutes(
|
|
70
|
+
const router = authRoutes(resolvedConfig, cache);
|
|
68
71
|
return {
|
|
69
72
|
routes: () => router,
|
|
70
|
-
middleware: () => middleware(
|
|
71
|
-
optionalMiddleware: () => optionalMiddleware(
|
|
73
|
+
middleware: () => middleware(resolvedConfig, cache),
|
|
74
|
+
optionalMiddleware: () => optionalMiddleware(resolvedConfig, cache),
|
|
72
75
|
cache,
|
|
73
76
|
};
|
|
74
77
|
}
|
|
75
|
-
export { createBezzie,
|
|
78
|
+
export { createBezzie, middleware, optionalMiddleware };
|
|
79
|
+
export { cloudflareKVAdapter } from './adapters/cloudflare-kv';
|
|
80
|
+
export { redisAdapter } from './adapters/redis';
|
|
81
|
+
export { memoryAdapter } from './adapters/memory';
|
|
76
82
|
export { CloudflareKVAdapter, RedisAdapter, MemoryAdapter } from './session';
|
|
83
|
+
export { BezzieError, DiscoveryError, CallbackError, TokenExchangeError, RefreshError, SessionStoreError, ConfigError, } from './errors';
|
|
77
84
|
//# sourceMappingURL=index.js.map
|
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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import type { MiddlewareHandler } from 'hono';
|
|
1
|
+
import type { MiddlewareHandler, Context } from 'hono';
|
|
2
2
|
import { type DiscoveryCache } from './discovery';
|
|
3
3
|
import type { Session } from './session';
|
|
4
|
-
import type {
|
|
4
|
+
import type { ResolvedBezzieConfig } from './index';
|
|
5
5
|
/**
|
|
6
6
|
* Hono context variables provided by Bezzie middleware.
|
|
7
7
|
* These are what downstream route handlers read from `c.var`.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Hono context variables guaranteed to be present in routes protected by `middleware()`.
|
|
11
|
+
*/
|
|
12
|
+
export type AuthenticatedVariables<TUser extends Record<string, unknown> = Record<string, unknown>> = {
|
|
10
13
|
/**
|
|
11
14
|
* The authenticated user's information.
|
|
12
15
|
*/
|
|
@@ -16,13 +19,68 @@ export type Variables<TUser extends Record<string, unknown> = Record<string, unk
|
|
|
16
19
|
*/
|
|
17
20
|
accessToken: string;
|
|
18
21
|
};
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Hono context variables that may be present in routes using `optionalMiddleware()`.
|
|
24
|
+
*/
|
|
25
|
+
export type OptionalVariables<TUser extends Record<string, unknown> = Record<string, unknown>> = {
|
|
26
|
+
/**
|
|
27
|
+
* The authenticated user's information, if a valid session exists.
|
|
28
|
+
*/
|
|
29
|
+
user?: Session<TUser>['user'];
|
|
30
|
+
/**
|
|
31
|
+
* The current OAuth access token, if a valid session exists.
|
|
32
|
+
*/
|
|
33
|
+
accessToken?: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Alias for `AuthenticatedVariables` — the common case for protected routes.
|
|
37
|
+
*/
|
|
38
|
+
export type Variables<TUser extends Record<string, unknown> = Record<string, unknown>> = AuthenticatedVariables<TUser>;
|
|
39
|
+
/**
|
|
40
|
+
* Context passed to the `onLogin` lifecycle hook.
|
|
41
|
+
*/
|
|
42
|
+
export interface LoginHookContext<TUser extends Record<string, unknown> = Record<string, unknown>> {
|
|
43
|
+
user: Session<TUser>['user'];
|
|
44
|
+
sessionId: string;
|
|
45
|
+
tokens: {
|
|
46
|
+
accessToken: string;
|
|
47
|
+
expiresAt: number;
|
|
48
|
+
};
|
|
49
|
+
isNewSession: boolean;
|
|
50
|
+
c: Context;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Context passed to the `onRefresh` lifecycle hook.
|
|
54
|
+
*/
|
|
55
|
+
export interface RefreshHookContext<TUser extends Record<string, unknown> = Record<string, unknown>> {
|
|
56
|
+
user: Session<TUser>['user'];
|
|
57
|
+
sessionId: string;
|
|
58
|
+
previousExpiresAt: number;
|
|
59
|
+
newExpiresAt: number;
|
|
60
|
+
c: Context;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Context passed to the `onLogout` lifecycle hook.
|
|
64
|
+
*/
|
|
65
|
+
export interface LogoutHookContext<TUser extends Record<string, unknown> = Record<string, unknown>> {
|
|
66
|
+
user: Session<TUser>['user'];
|
|
67
|
+
sessionId: string;
|
|
68
|
+
c: Context;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Context passed to the `onError` hook when a non-fatal lifecycle hook throws.
|
|
72
|
+
*/
|
|
73
|
+
export interface HookErrorContext {
|
|
74
|
+
hook: 'onLogin' | 'onRefresh' | 'onLogout';
|
|
75
|
+
c: Context;
|
|
76
|
+
}
|
|
77
|
+
export declare function middleware<TUser extends Record<string, unknown> = Record<string, unknown>>(config: ResolvedBezzieConfig<TUser>, cache: DiscoveryCache): MiddlewareHandler<{
|
|
78
|
+
Variables: AuthenticatedVariables<TUser>;
|
|
21
79
|
}>;
|
|
22
80
|
/**
|
|
23
81
|
* Middleware that sets user context if a session exists but always calls next().
|
|
24
82
|
*/
|
|
25
|
-
export declare function optionalMiddleware<TUser extends Record<string, unknown> = Record<string, unknown>>(config:
|
|
26
|
-
Variables:
|
|
83
|
+
export declare function optionalMiddleware<TUser extends Record<string, unknown> = Record<string, unknown>>(config: ResolvedBezzieConfig<TUser>, cache: DiscoveryCache): MiddlewareHandler<{
|
|
84
|
+
Variables: OptionalVariables<TUser>;
|
|
27
85
|
}>;
|
|
28
86
|
//# 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,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/middleware.js
CHANGED
|
@@ -10,7 +10,7 @@ async function authenticate(c, config, cache) {
|
|
|
10
10
|
return { type: 'unauthenticated' };
|
|
11
11
|
}
|
|
12
12
|
// 3. Look up the session in KV using SessionStore
|
|
13
|
-
let session = await sessionStore.get(sessionId);
|
|
13
|
+
let session = await sessionStore.get(`session:${sessionId}`);
|
|
14
14
|
// 4. If no session found or it's a PKCE state → unauthenticated
|
|
15
15
|
if (!session || session._type === 'pkce') {
|
|
16
16
|
return { type: 'unauthenticated' };
|
|
@@ -18,7 +18,7 @@ async function authenticate(c, config, cache) {
|
|
|
18
18
|
// 4.5 Check for absolute session expiry (90 days)
|
|
19
19
|
const MAX_SESSION_AGE = 90 * 24 * 60 * 60; // 90 days
|
|
20
20
|
if (Math.floor(Date.now() / 1000) - session.createdAt > MAX_SESSION_AGE) {
|
|
21
|
-
await sessionStore.delete(sessionId);
|
|
21
|
+
await sessionStore.delete(`session:${sessionId}`);
|
|
22
22
|
return { type: 'expired' };
|
|
23
23
|
}
|
|
24
24
|
const as = await getAuthorizationServer(config, cache);
|
|
@@ -29,21 +29,38 @@ async function authenticate(c, config, cache) {
|
|
|
29
29
|
// 6. If expired → use oauth4webapi to perform a refresh token grant
|
|
30
30
|
const client = { client_id: config.clientId };
|
|
31
31
|
const clientAuth = oauth.ClientSecretPost(config.clientSecret);
|
|
32
|
-
const response = await oauth.refreshTokenGrantRequest(as, client, clientAuth, session.refreshToken);
|
|
32
|
+
const response = await oauth.refreshTokenGrantRequest(as, client, clientAuth, session.refreshToken, { signal: AbortSignal.timeout(5000) });
|
|
33
33
|
try {
|
|
34
34
|
const result = await oauth.processRefreshTokenResponse(as, client, response);
|
|
35
|
+
// Capture previous expiresAt before overwriting, for onRefresh hook.
|
|
36
|
+
const previousExpiresAt = session.expiresAt;
|
|
35
37
|
// Update the session in KV with new tokens and new expiresAt
|
|
36
38
|
session.accessToken = result.access_token;
|
|
37
39
|
if (result.refresh_token) {
|
|
38
40
|
session.refreshToken = result.refresh_token;
|
|
39
41
|
}
|
|
40
42
|
session.expiresAt = Math.floor(Date.now() / 1000) + (result.expires_in || 3600);
|
|
41
|
-
await sessionStore.set(sessionId
|
|
43
|
+
await sessionStore.set(`session:${sessionId}`, session, config.sessionTtlSeconds ?? 30 * 24 * 60 * 60); // 30 days, matches initial session TTL
|
|
44
|
+
if (config.onRefresh) {
|
|
45
|
+
try {
|
|
46
|
+
await config.onRefresh({
|
|
47
|
+
user: session.user,
|
|
48
|
+
sessionId,
|
|
49
|
+
previousExpiresAt,
|
|
50
|
+
newExpiresAt: session.expiresAt,
|
|
51
|
+
c,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (hookErr) {
|
|
55
|
+
const handler = config.onError ?? ((e) => console.error('Bezzie: onRefresh hook threw:', e instanceof Error ? e.message : String(e)));
|
|
56
|
+
handler(hookErr, { hook: 'onRefresh', c });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
42
59
|
}
|
|
43
60
|
catch (err) {
|
|
44
61
|
if (err instanceof oauth.ResponseBodyError && err.error === 'invalid_grant') {
|
|
45
62
|
// Potential race condition: another request might have already refreshed this token
|
|
46
|
-
const refreshedSession = await sessionStore.get(sessionId);
|
|
63
|
+
const refreshedSession = await sessionStore.get(`session:${sessionId}`);
|
|
47
64
|
if (refreshedSession &&
|
|
48
65
|
refreshedSession._type === 'session' &&
|
|
49
66
|
refreshedSession.accessToken !== session.accessToken) {
|
|
@@ -52,18 +69,18 @@ async function authenticate(c, config, cache) {
|
|
|
52
69
|
}
|
|
53
70
|
else {
|
|
54
71
|
// Truly failed
|
|
55
|
-
await sessionStore.delete(sessionId);
|
|
72
|
+
await sessionStore.delete(`session:${sessionId}`);
|
|
56
73
|
return { type: 'unauthenticated' };
|
|
57
74
|
}
|
|
58
75
|
}
|
|
59
76
|
else {
|
|
60
|
-
await sessionStore.delete(sessionId);
|
|
77
|
+
await sessionStore.delete(`session:${sessionId}`);
|
|
61
78
|
return { type: 'unauthenticated' };
|
|
62
79
|
}
|
|
63
80
|
}
|
|
64
81
|
}
|
|
65
82
|
catch {
|
|
66
|
-
await sessionStore.delete(sessionId);
|
|
83
|
+
await sessionStore.delete(`session:${sessionId}`);
|
|
67
84
|
return { type: 'unauthenticated' };
|
|
68
85
|
}
|
|
69
86
|
}
|
|
@@ -77,12 +94,17 @@ async function authenticate(c, config, cache) {
|
|
|
77
94
|
Authorization: `Bearer ${session.accessToken}`,
|
|
78
95
|
},
|
|
79
96
|
});
|
|
97
|
+
// S10: validateJwtAccessToken verifies the JWT signature via JWKS and
|
|
98
|
+
// asserts the standard claims — `iss` matches the authorization server,
|
|
99
|
+
// `aud` matches `config.audience` (passed as the third argument, the
|
|
100
|
+
// expectedAudience parameter), and `exp`/`nbf`/`iat` are within bounds.
|
|
80
101
|
await oauth.validateJwtAccessToken(as, mockReq, config.audience, { [oauth.jwksCache]: cache.jwksCache });
|
|
81
102
|
}
|
|
82
|
-
catch {
|
|
103
|
+
catch (err) {
|
|
83
104
|
// 9. If JWT invalid → fallback to opaque token (pass through)
|
|
84
105
|
// This allows Bezzie to work with providers that issue opaque access tokens
|
|
85
106
|
// or if the JWT is not verifiable for some reason, but we still have a valid session.
|
|
107
|
+
console.warn('Bezzie: JWT access token validation failed (falling back to session trust):', err instanceof Error ? err.message : String(err));
|
|
86
108
|
}
|
|
87
109
|
}
|
|
88
110
|
return { type: 'authenticated', user: session.user, accessToken: session.accessToken };
|
|
@@ -94,7 +116,7 @@ export function middleware(config, cache) {
|
|
|
94
116
|
return c.text('Unauthorized', 401);
|
|
95
117
|
}
|
|
96
118
|
if (result.type === 'expired') {
|
|
97
|
-
return c.redirect(config.loginPath ?? '/auth/login');
|
|
119
|
+
return c.redirect(config.loginPath ?? config.routes?.login ?? '/auth/login');
|
|
98
120
|
}
|
|
99
121
|
// Attach the user and accessToken to Hono context
|
|
100
122
|
c.set('user', result.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;AACrC,OAAO,EAAE,sBAAsB,EAAuB,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/routes.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { type DiscoveryCache } from './discovery';
|
|
3
|
-
import type {
|
|
4
|
-
export declare function authRoutes<TUser extends Record<string, unknown> = Record<string, unknown>>(config:
|
|
3
|
+
import type { ResolvedBezzieConfig } from './index';
|
|
4
|
+
export declare function authRoutes<TUser extends Record<string, unknown> = Record<string, unknown>>(config: ResolvedBezzieConfig<TUser>, 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;AAG3B,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,aAAa,CAAA;AAEzE,OAAO,KAAK,EAAE,
|
|
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,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,wBAAgB,UAAU,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxF,MAAM,EAAE,oBAAoB,CAAC,KAAK,CAAC,EACnC,KAAK,EAAE,cAAc,8EAsUtB"}
|