@gauts/auth 0.1.3 → 0.2.1
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 +103 -59
- package/SECURITY.md +1 -3
- package/dist/adapters/hono/index.d.ts +12 -6
- package/dist/adapters/hono/index.d.ts.map +1 -1
- package/dist/adapters/hono/index.js +72 -17
- package/dist/adapters/hono/index.js.map +1 -1
- package/dist/adapters/redis/index.d.ts +5 -1
- package/dist/adapters/redis/index.d.ts.map +1 -1
- package/dist/adapters/redis/index.js +16 -7
- package/dist/adapters/redis/index.js.map +1 -1
- package/dist/auth.d.ts +3 -3
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +21 -15
- package/dist/auth.js.map +1 -1
- package/dist/client/index.d.ts +8 -6
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -11
- package/dist/client/index.js.map +1 -1
- package/dist/config.d.ts +10 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +118 -19
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +7 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/password/index.d.ts +4 -1
- package/dist/password/index.d.ts.map +1 -1
- package/dist/password/index.js +16 -9
- package/dist/password/index.js.map +1 -1
- package/dist/session/schema.d.ts.map +1 -1
- package/dist/session/schema.js +19 -10
- package/dist/session/schema.js.map +1 -1
- package/dist/session/service.d.ts +3 -3
- package/dist/session/service.d.ts.map +1 -1
- package/dist/session/service.js +128 -67
- package/dist/session/service.js.map +1 -1
- package/dist/session/token.d.ts.map +1 -1
- package/dist/session/token.js +6 -2
- package/dist/session/token.js.map +1 -1
- package/dist/session/types.d.ts +52 -25
- package/dist/session/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,16 +4,14 @@ Reusable password and opaque server-side session authentication for Node.js appl
|
|
|
4
4
|
|
|
5
5
|
`@gauts/auth` validates sessions through Redis and records session history through an application-owned database adapter. It does not create endpoints, database models, users, or application authorization rules.
|
|
6
6
|
|
|
7
|
-
The package is under active development and has not been published yet.
|
|
8
|
-
|
|
9
7
|
## Design
|
|
10
8
|
|
|
11
9
|
- Argon2id by default, with explicit bcrypt support.
|
|
12
10
|
- One stable 256-bit opaque browser token per session.
|
|
13
|
-
- SHA-256 token hashes in Redis and the
|
|
11
|
+
- SHA-256 token hashes in Redis and the session records database.
|
|
14
12
|
- Redis-authoritative authentication with no database fallback.
|
|
15
13
|
- Sliding inactivity expiration without an absolute lifetime.
|
|
16
|
-
-
|
|
14
|
+
- Configurable client validation, using the complete User-Agent by default.
|
|
17
15
|
- Framework integrations through explicit package exports.
|
|
18
16
|
|
|
19
17
|
## Installation
|
|
@@ -22,21 +20,23 @@ The package is under active development and has not been published yet.
|
|
|
22
20
|
npm install @gauts/auth redis hono
|
|
23
21
|
```
|
|
24
22
|
|
|
25
|
-
The package is not on npm yet. During local development, use the tarball produced by `npm pack`.
|
|
26
|
-
|
|
27
23
|
## Setup
|
|
28
24
|
|
|
29
25
|
```ts
|
|
30
|
-
import { createAuth, type
|
|
26
|
+
import { createAuth, type SessionRecords } from "@gauts/auth";
|
|
31
27
|
import { createHonoAdapter } from "@gauts/auth/hono";
|
|
32
28
|
import { createRedisStore } from "@gauts/auth/redis";
|
|
33
29
|
|
|
34
|
-
const
|
|
30
|
+
const records: SessionRecords = {
|
|
35
31
|
create: (session) => db.sessions.create(session),
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
find: ({ accountId, sessionId }) =>
|
|
33
|
+
db.sessions.find({ accountId, sessionId }),
|
|
34
|
+
findActive: ({ accountId, now }) =>
|
|
35
|
+
db.sessions.findActive({ accountId, now }),
|
|
36
|
+
revoke: ({ revokedAt, sessionIds }) =>
|
|
37
|
+
db.sessions.revoke({ revokedAt, sessionIds }),
|
|
38
|
+
updateExpiry: ({ expiresAt, sessionId, updatedAt }) =>
|
|
39
|
+
db.sessions.updateExpiry({ expiresAt, sessionId, updatedAt }),
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
type AccountSession = {
|
|
@@ -45,33 +45,56 @@ type AccountSession = {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const auth = createAuth<AccountSession>({
|
|
48
|
-
redis: createRedisStore(redis, { prefix: "my-app:auth" }),
|
|
49
|
-
|
|
48
|
+
redis: createRedisStore({ client: redis, config: { prefix: "my-app:auth" } }),
|
|
49
|
+
records,
|
|
50
50
|
session: {
|
|
51
51
|
ttl: 60 * 60 * 24 * 7,
|
|
52
|
-
|
|
52
|
+
renewInterval: 60 * 60 * 24,
|
|
53
53
|
max: 10,
|
|
54
|
+
validation: ["userAgent"],
|
|
54
55
|
},
|
|
55
56
|
});
|
|
56
57
|
|
|
57
58
|
const hono = createHonoAdapter({
|
|
58
59
|
auth,
|
|
59
|
-
|
|
60
|
-
ip: getTrustedClientIp(c),
|
|
61
|
-
userAgent: c.req.header("user-agent") ?? null,
|
|
62
|
-
}),
|
|
60
|
+
getIp: (c) => getTrustedClientIp(c),
|
|
63
61
|
});
|
|
64
62
|
```
|
|
65
63
|
|
|
66
64
|
The application must obtain the client IP according to its own trusted-proxy configuration. The package canonicalizes the supplied IPv4 or IPv6 value but never decides which forwarding headers are trusted.
|
|
67
65
|
|
|
66
|
+
## Client information
|
|
67
|
+
|
|
68
|
+
The application supplies `getIp` because only its deployment knows which proxies and forwarding
|
|
69
|
+
headers are trusted. The Hono adapter reads User-Agent and platform directly from the request.
|
|
70
|
+
|
|
71
|
+
The resulting client information has this shape:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
type SessionClientInput = {
|
|
75
|
+
ip?: string | null;
|
|
76
|
+
userAgent?: string | null;
|
|
77
|
+
platform?: string | null;
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- `validation` selects which client fields are compared on authenticated requests.
|
|
82
|
+
- `userAgent` is compared by default.
|
|
83
|
+
- `ip` and `platform` are always stored as session metadata, even when they are not compared.
|
|
84
|
+
- IPv4, IPv4-mapped IPv6, and IPv6 values are canonicalized by the package.
|
|
85
|
+
- Platform is unquoted, trimmed, and limited to 255 characters.
|
|
86
|
+
- User-Agent is stored and compared in full without truncation.
|
|
87
|
+
|
|
88
|
+
`getIp` runs during session creation and on every authenticated request. It should only resolve the
|
|
89
|
+
trusted request IP and must not perform unrelated account or database work.
|
|
90
|
+
|
|
68
91
|
## Passwords
|
|
69
92
|
|
|
70
93
|
Argon2id is the default:
|
|
71
94
|
|
|
72
95
|
```ts
|
|
73
96
|
const hash = await auth.password.hash(password);
|
|
74
|
-
const valid = await auth.password.verify(password, hash);
|
|
97
|
+
const valid = await auth.password.verify({ password, storedHash: hash });
|
|
75
98
|
```
|
|
76
99
|
|
|
77
100
|
Applications whose database contains bcrypt hashes select bcrypt explicitly:
|
|
@@ -81,8 +104,8 @@ const auth = createAuth({
|
|
|
81
104
|
password: {
|
|
82
105
|
algorithm: "bcrypt",
|
|
83
106
|
},
|
|
84
|
-
redis: createRedisStore(redis),
|
|
85
|
-
|
|
107
|
+
redis: createRedisStore({ client: redis }),
|
|
108
|
+
records,
|
|
86
109
|
});
|
|
87
110
|
```
|
|
88
111
|
|
|
@@ -107,22 +130,26 @@ app.post("/auth/login", async (c) => {
|
|
|
107
130
|
const { email, password } = await c.req.json();
|
|
108
131
|
const account = await findAccount(email);
|
|
109
132
|
|
|
110
|
-
if (
|
|
133
|
+
if (
|
|
134
|
+
!account ||
|
|
135
|
+
!(await auth.password.verify({
|
|
136
|
+
password,
|
|
137
|
+
storedHash: account.passwordHash,
|
|
138
|
+
}))
|
|
139
|
+
) {
|
|
111
140
|
return c.json({ error: "Invalid credentials." }, 401);
|
|
112
141
|
}
|
|
113
142
|
|
|
114
|
-
const
|
|
115
|
-
|
|
143
|
+
const session = await hono.createSession({
|
|
144
|
+
accountId: account.id,
|
|
145
|
+
context: c,
|
|
116
146
|
data: {
|
|
117
147
|
email: account.email,
|
|
118
148
|
role: account.role,
|
|
119
149
|
},
|
|
120
|
-
client: await getClient(c),
|
|
121
150
|
});
|
|
122
151
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return c.json({ account: created.session.data });
|
|
152
|
+
return c.json({ account: session.data });
|
|
126
153
|
});
|
|
127
154
|
```
|
|
128
155
|
|
|
@@ -132,14 +159,14 @@ Applications must apply their own login rate limiting and account-enumeration pr
|
|
|
132
159
|
|
|
133
160
|
```ts
|
|
134
161
|
app.get("/account", hono.requireSession, async (c) => {
|
|
135
|
-
const session = c.get("
|
|
136
|
-
const account = await findAccountById(session.
|
|
162
|
+
const session = c.get("session");
|
|
163
|
+
const account = await findAccountById(session.accountId);
|
|
137
164
|
|
|
138
165
|
return c.json({ account });
|
|
139
166
|
});
|
|
140
167
|
```
|
|
141
168
|
|
|
142
|
-
The middleware reads the cookie, resolves Redis, compares
|
|
169
|
+
The middleware reads the cookie, resolves Redis, compares the configured client fields, renews expiry when due, and places the typed session in the Hono context. It does not load application data from the database.
|
|
143
170
|
|
|
144
171
|
Applications that need to populate additional Hono context variables can resolve through the same adapter without duplicating its cookie behavior:
|
|
145
172
|
|
|
@@ -156,54 +183,54 @@ const requireAccount = async (c, next) => {
|
|
|
156
183
|
|
|
157
184
|
```ts
|
|
158
185
|
app.post("/auth/logout", async (c) => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (token) {
|
|
162
|
-
await auth.session.revokeToken(token);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
hono.clearSession(c);
|
|
186
|
+
await hono.revokeSession(c);
|
|
166
187
|
return c.body(null, 204);
|
|
167
188
|
});
|
|
168
189
|
```
|
|
169
190
|
|
|
191
|
+
The adapter clears the cookie only after backend revocation succeeds. Infrastructure errors are
|
|
192
|
+
propagated so the application can return its own service-error response.
|
|
193
|
+
|
|
170
194
|
## Active sessions
|
|
171
195
|
|
|
172
196
|
```ts
|
|
173
197
|
const sessions = await auth.session.list(accountId);
|
|
174
198
|
|
|
175
199
|
await auth.session.revoke({
|
|
176
|
-
|
|
200
|
+
accountId,
|
|
177
201
|
sessionId,
|
|
178
202
|
});
|
|
179
203
|
|
|
180
|
-
await auth.session.
|
|
204
|
+
await auth.session.revokeAccount(accountId);
|
|
181
205
|
```
|
|
182
206
|
|
|
183
|
-
The
|
|
207
|
+
The records database supplies session history. Redis is checked in a batch before a session is reported as active. Token hashes are never returned by `list`.
|
|
184
208
|
|
|
185
209
|
## Synchronizing session data
|
|
186
210
|
|
|
187
211
|
When cached session claims change:
|
|
188
212
|
|
|
189
213
|
```ts
|
|
190
|
-
await auth.session.sync(
|
|
191
|
-
|
|
192
|
-
|
|
214
|
+
await auth.session.sync({
|
|
215
|
+
accountId,
|
|
216
|
+
data: {
|
|
217
|
+
email: account.email,
|
|
218
|
+
role: account.role,
|
|
219
|
+
},
|
|
193
220
|
});
|
|
194
221
|
```
|
|
195
222
|
|
|
196
223
|
Synchronization preserves the existing token and Redis TTL.
|
|
197
224
|
|
|
198
|
-
## Session
|
|
225
|
+
## Session records contract
|
|
199
226
|
|
|
200
|
-
Each consuming application maps `
|
|
227
|
+
Each consuming application maps `SessionRecords` to its database. The durable record contains:
|
|
201
228
|
|
|
202
229
|
- Session ID.
|
|
203
|
-
-
|
|
230
|
+
- Account ID and relation owned by the application.
|
|
204
231
|
- SHA-256 token hash.
|
|
205
232
|
- Canonical IP.
|
|
206
|
-
-
|
|
233
|
+
- Platform metadata.
|
|
207
234
|
- Complete User-Agent.
|
|
208
235
|
- Creation, current expiry, update, and revocation timestamps.
|
|
209
236
|
|
|
@@ -216,8 +243,9 @@ Defaults:
|
|
|
216
243
|
```ts
|
|
217
244
|
session: {
|
|
218
245
|
ttl: 7 * 24 * 60 * 60,
|
|
219
|
-
|
|
246
|
+
renewInterval: 24 * 60 * 60,
|
|
220
247
|
max: 10,
|
|
248
|
+
validation: ["userAgent"],
|
|
221
249
|
}
|
|
222
250
|
```
|
|
223
251
|
|
|
@@ -225,24 +253,42 @@ session: {
|
|
|
225
253
|
- Active sessions renew at most once every 24 hours.
|
|
226
254
|
- Renewal keeps the same browser token.
|
|
227
255
|
- There is no absolute session lifetime.
|
|
256
|
+
- Every successful `resolve` call counts as HTTP activity and renews the session when due.
|
|
228
257
|
|
|
229
|
-
Consumers that
|
|
258
|
+
Consumers that cannot deliver `Set-Cookie`, such as WebSocket handshakes, validate without renewing:
|
|
230
259
|
|
|
231
260
|
```ts
|
|
232
|
-
await auth.session.
|
|
261
|
+
const session = await auth.session.validate({
|
|
233
262
|
client,
|
|
234
|
-
renew: false,
|
|
235
263
|
token,
|
|
236
264
|
});
|
|
237
265
|
```
|
|
238
266
|
|
|
239
|
-
|
|
267
|
+
`validate` performs the same Redis, expiry, payload, and configured client-field checks as `resolve`. A client mismatch still revokes the backend session. It does not update `touchedAt`, Redis TTL, or the database expiry.
|
|
268
|
+
|
|
269
|
+
## Client validation
|
|
240
270
|
|
|
241
|
-
|
|
271
|
+
The default compares only the complete User-Agent:
|
|
242
272
|
|
|
243
|
-
|
|
273
|
+
```ts
|
|
274
|
+
session: {
|
|
275
|
+
validation: ["userAgent"],
|
|
276
|
+
}
|
|
277
|
+
```
|
|
244
278
|
|
|
245
|
-
|
|
279
|
+
Applications can choose any combination of `ip`, `userAgent`, and `platform`:
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
session: {
|
|
283
|
+
validation: ["ip", "userAgent", "platform"],
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
An empty array disables client-field comparison and validates only the session token. Unknown or duplicate fields are rejected during startup.
|
|
288
|
+
|
|
289
|
+
If a configured field differs, the package deletes the Redis session first and marks its database record as revoked. Clearing the response cookie is client cleanup; Redis deletion is what removes access.
|
|
290
|
+
|
|
291
|
+
Exact IP validation is opt-in because VPN, mobile, and other networks can change a legitimate user's public IP. Platform validation is also opt-in because the client-hint header may be absent. Client-field validation is defense in depth and does not replace TLS, secure cookies, CSRF protection, XSS prevention, or re-authentication for sensitive actions.
|
|
246
292
|
|
|
247
293
|
## Package exports
|
|
248
294
|
|
|
@@ -251,5 +297,3 @@ Strict IP binding can log out legitimate users whose public IP changes. It is de
|
|
|
251
297
|
@gauts/auth/redis createRedisStore
|
|
252
298
|
@gauts/auth/hono createHonoAdapter
|
|
253
299
|
```
|
|
254
|
-
|
|
255
|
-
See [`PLAN.md`](./PLAN.md) for the implementation phases and complete security decisions.
|
package/SECURITY.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { Context, Env, MiddlewareHandler } from "hono";
|
|
2
2
|
import type { Auth } from "../../auth.js";
|
|
3
|
-
import type {
|
|
4
|
-
import type { CreatedSession, Session } from "../../session/types.js";
|
|
3
|
+
import type { Session } from "../../session/types.js";
|
|
5
4
|
export type HonoAuthVariables<TData extends object> = {
|
|
6
|
-
|
|
5
|
+
session: Session<TData>;
|
|
7
6
|
};
|
|
8
7
|
export type HonoAuthEnv<TData extends object> = Env & {
|
|
9
8
|
Variables: HonoAuthVariables<TData>;
|
|
@@ -18,14 +17,21 @@ export type HonoCookieConfig = {
|
|
|
18
17
|
export type HonoAdapterConfig<TData extends object> = {
|
|
19
18
|
auth: Auth<TData>;
|
|
20
19
|
cookie?: HonoCookieConfig;
|
|
21
|
-
|
|
20
|
+
getIp: (c: Context) => Promise<string | null | undefined> | string | null | undefined;
|
|
21
|
+
};
|
|
22
|
+
type CreateSessionInput<TData extends object> = {
|
|
23
|
+
accountId: string;
|
|
24
|
+
context: Context;
|
|
25
|
+
data: TData;
|
|
22
26
|
};
|
|
23
27
|
export type HonoAdapter<TData extends object> = {
|
|
24
28
|
clearSession(c: Context): void;
|
|
29
|
+
createSession(input: CreateSessionInput<TData>): Promise<Session<TData>>;
|
|
25
30
|
getToken(c: Context): string | null;
|
|
26
31
|
requireSession: MiddlewareHandler<HonoAuthEnv<TData>>;
|
|
27
32
|
resolveSession(c: Context): Promise<Session<TData>>;
|
|
28
|
-
|
|
33
|
+
revokeSession(c: Context): Promise<string[]>;
|
|
29
34
|
};
|
|
30
|
-
export declare const createHonoAdapter: <TData extends object>({ auth, cookie,
|
|
35
|
+
export declare const createHonoAdapter: <TData extends object>({ auth, cookie, getIp, }: HonoAdapterConfig<TData>) => HonoAdapter<TData>;
|
|
36
|
+
export {};
|
|
31
37
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/hono/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/hono/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAE5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,MAAM,IAAI;IACpD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,KAAK,SAAS,MAAM,IAAI,GAAG,GAAG;IACpD,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,MAAM,IAAI;IACpD,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,KAAK,EAAE,CACL,CAAC,EAAE,OAAO,KACP,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACrE,CAAC;AAEF,KAAK,kBAAkB,CAAC,KAAK,SAAS,MAAM,IAAI;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,KAAK,SAAS,MAAM,IAAI;IAC9C,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,aAAa,CAAC,KAAK,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,cAAc,EAAE,iBAAiB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC9C,CAAC;AA4DF,eAAO,MAAM,iBAAiB,GAAI,KAAK,SAAS,MAAM,EAAE,0BAIrD,iBAAiB,CAAC,KAAK,CAAC,KAAG,WAAW,CAAC,KAAK,CAkI9C,CAAC"}
|
|
@@ -7,19 +7,35 @@ const resolveCookie = (config = {}) => {
|
|
|
7
7
|
const sameSite = config.sameSite ?? "Lax";
|
|
8
8
|
const secure = config.secure ?? true;
|
|
9
9
|
if (!COOKIE_NAME_PATTERN.test(name)) {
|
|
10
|
-
throw createError(
|
|
10
|
+
throw createError({
|
|
11
|
+
code: "AUTH_CONFIG_INVALID",
|
|
12
|
+
message: "Session cookie name is invalid.",
|
|
13
|
+
});
|
|
11
14
|
}
|
|
12
15
|
if (!path.startsWith("/")) {
|
|
13
|
-
throw createError(
|
|
16
|
+
throw createError({
|
|
17
|
+
code: "AUTH_CONFIG_INVALID",
|
|
18
|
+
message: "Session cookie path must start with /.",
|
|
19
|
+
});
|
|
14
20
|
}
|
|
15
|
-
if (name.startsWith("__Host-") &&
|
|
16
|
-
|
|
21
|
+
if (name.startsWith("__Host-") &&
|
|
22
|
+
(!secure || path !== "/" || config.domain)) {
|
|
23
|
+
throw createError({
|
|
24
|
+
code: "AUTH_CONFIG_INVALID",
|
|
25
|
+
message: "__Host- cookies require secure=true, path=/, and no domain.",
|
|
26
|
+
});
|
|
17
27
|
}
|
|
18
28
|
if (name.startsWith("__Secure-") && !secure) {
|
|
19
|
-
throw createError(
|
|
29
|
+
throw createError({
|
|
30
|
+
code: "AUTH_CONFIG_INVALID",
|
|
31
|
+
message: "__Secure- cookies require secure=true.",
|
|
32
|
+
});
|
|
20
33
|
}
|
|
21
34
|
if (sameSite === "None" && !secure) {
|
|
22
|
-
throw createError(
|
|
35
|
+
throw createError({
|
|
36
|
+
code: "AUTH_CONFIG_INVALID",
|
|
37
|
+
message: "SameSite=None cookies require secure=true.",
|
|
38
|
+
});
|
|
23
39
|
}
|
|
24
40
|
return {
|
|
25
41
|
name,
|
|
@@ -32,14 +48,25 @@ const resolveCookie = (config = {}) => {
|
|
|
32
48
|
},
|
|
33
49
|
};
|
|
34
50
|
};
|
|
35
|
-
export const createHonoAdapter = ({ auth, cookie,
|
|
51
|
+
export const createHonoAdapter = ({ auth, cookie, getIp, }) => {
|
|
52
|
+
if (typeof getIp !== "function") {
|
|
53
|
+
throw createError({
|
|
54
|
+
code: "AUTH_CONFIG_INVALID",
|
|
55
|
+
message: "Hono getIp must be a function.",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
36
58
|
const resolved = resolveCookie(cookie);
|
|
59
|
+
const getSessionClient = async (c) => ({
|
|
60
|
+
ip: (await getIp(c)) ?? null,
|
|
61
|
+
platform: c.req.header("sec-ch-ua-platform") ?? null,
|
|
62
|
+
userAgent: c.req.header("user-agent") ?? null,
|
|
63
|
+
});
|
|
37
64
|
const getToken = (c) => {
|
|
38
65
|
const token = getCookie(c, resolved.name)?.trim();
|
|
39
66
|
return token?.length ? token : null;
|
|
40
67
|
};
|
|
41
|
-
const setToken = (
|
|
42
|
-
setCookie(
|
|
68
|
+
const setToken = ({ context, expiresAt, token, }) => {
|
|
69
|
+
setCookie(context, resolved.name, token, {
|
|
43
70
|
...resolved.options,
|
|
44
71
|
expires: expiresAt,
|
|
45
72
|
});
|
|
@@ -47,15 +74,31 @@ export const createHonoAdapter = ({ auth, cookie, getClient, }) => {
|
|
|
47
74
|
const clearSession = (c) => {
|
|
48
75
|
deleteCookie(c, resolved.name, resolved.options);
|
|
49
76
|
};
|
|
77
|
+
const createSession = async ({ accountId, context, data, }) => {
|
|
78
|
+
const created = await auth.session.create({
|
|
79
|
+
accountId,
|
|
80
|
+
client: await getSessionClient(context),
|
|
81
|
+
data,
|
|
82
|
+
});
|
|
83
|
+
setToken({
|
|
84
|
+
context,
|
|
85
|
+
expiresAt: created.session.expiresAt,
|
|
86
|
+
token: created.token,
|
|
87
|
+
});
|
|
88
|
+
return created.session;
|
|
89
|
+
};
|
|
50
90
|
const resolveSession = async (c) => {
|
|
51
91
|
const token = getToken(c);
|
|
52
92
|
if (!token) {
|
|
53
|
-
throw createError(
|
|
93
|
+
throw createError({
|
|
94
|
+
code: "SESSION_INVALID",
|
|
95
|
+
message: "Authentication required.",
|
|
96
|
+
});
|
|
54
97
|
}
|
|
55
98
|
let resolvedSession;
|
|
56
99
|
try {
|
|
57
100
|
resolvedSession = await auth.session.resolve({
|
|
58
|
-
client: await
|
|
101
|
+
client: await getSessionClient(c),
|
|
59
102
|
token,
|
|
60
103
|
});
|
|
61
104
|
}
|
|
@@ -67,25 +110,37 @@ export const createHonoAdapter = ({ auth, cookie, getClient, }) => {
|
|
|
67
110
|
}
|
|
68
111
|
if (!resolvedSession) {
|
|
69
112
|
clearSession(c);
|
|
70
|
-
throw createError(
|
|
113
|
+
throw createError({
|
|
114
|
+
code: "SESSION_INVALID",
|
|
115
|
+
message: "Authentication required.",
|
|
116
|
+
});
|
|
71
117
|
}
|
|
72
118
|
if (resolvedSession.renewed) {
|
|
73
|
-
setToken(
|
|
119
|
+
setToken({
|
|
120
|
+
context: c,
|
|
121
|
+
expiresAt: resolvedSession.session.expiresAt,
|
|
122
|
+
token,
|
|
123
|
+
});
|
|
74
124
|
}
|
|
75
125
|
return resolvedSession.session;
|
|
76
126
|
};
|
|
77
127
|
const requireSession = async (c, next) => {
|
|
78
|
-
c.set("
|
|
128
|
+
c.set("session", await resolveSession(c));
|
|
79
129
|
await next();
|
|
80
130
|
};
|
|
131
|
+
const revokeSession = async (c) => {
|
|
132
|
+
const token = getToken(c);
|
|
133
|
+
const revoked = token ? await auth.session.revokeToken(token) : [];
|
|
134
|
+
clearSession(c);
|
|
135
|
+
return revoked;
|
|
136
|
+
};
|
|
81
137
|
return {
|
|
82
138
|
clearSession,
|
|
139
|
+
createSession,
|
|
83
140
|
getToken,
|
|
84
141
|
requireSession,
|
|
85
142
|
resolveSession,
|
|
86
|
-
|
|
87
|
-
setToken(c, created.token, created.session.expiresAt);
|
|
88
|
-
},
|
|
143
|
+
revokeSession,
|
|
89
144
|
};
|
|
90
145
|
};
|
|
91
146
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/hono/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/hono/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,5 +3,9 @@ import type { RedisSessionStore } from "../../session/types.js";
|
|
|
3
3
|
export type RedisStoreConfig = {
|
|
4
4
|
prefix?: string;
|
|
5
5
|
};
|
|
6
|
-
export
|
|
6
|
+
export type RedisStoreInput = {
|
|
7
|
+
client: RedisClientType;
|
|
8
|
+
config?: RedisStoreConfig;
|
|
9
|
+
};
|
|
10
|
+
export declare const createRedisStore: ({ client, config, }: RedisStoreInput) => RedisSessionStore;
|
|
7
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/redis/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/redis/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,CAAC;AAgBF,eAAO,MAAM,gBAAgB,GAAI,qBAG9B,eAAe,KAAG,iBA8DpB,CAAC"}
|
|
@@ -3,16 +3,22 @@ const getPrefix = (input) => {
|
|
|
3
3
|
const candidate = input?.trim();
|
|
4
4
|
const prefix = candidate?.length ? candidate : "gauts:auth";
|
|
5
5
|
if (prefix.length > 128 || !/^[A-Za-z0-9:_-]+$/.test(prefix)) {
|
|
6
|
-
throw createError(
|
|
6
|
+
throw createError({
|
|
7
|
+
code: "AUTH_CONFIG_INVALID",
|
|
8
|
+
message: "Redis key prefix is invalid.",
|
|
9
|
+
});
|
|
7
10
|
}
|
|
8
11
|
return prefix.replace(/:+$/g, "");
|
|
9
12
|
};
|
|
10
|
-
export const createRedisStore = (client, config = {}) => {
|
|
13
|
+
export const createRedisStore = ({ client, config = {}, }) => {
|
|
11
14
|
const prefix = getPrefix(config.prefix);
|
|
12
15
|
const getKey = (tokenHash) => `${prefix}:session:${tokenHash}`;
|
|
13
16
|
return {
|
|
14
|
-
create: async (tokenHash,
|
|
15
|
-
const result = await client.set(getKey(tokenHash), value, {
|
|
17
|
+
create: async ({ tokenHash, ttl, value }) => {
|
|
18
|
+
const result = await client.set(getKey(tokenHash), value, {
|
|
19
|
+
EX: ttl,
|
|
20
|
+
NX: true,
|
|
21
|
+
});
|
|
16
22
|
if (result !== "OK") {
|
|
17
23
|
throw new Error("Redis session key already exists.");
|
|
18
24
|
}
|
|
@@ -25,11 +31,14 @@ export const createRedisStore = (client, config = {}) => {
|
|
|
25
31
|
? []
|
|
26
32
|
: client.mGet(tokenHashes.map((tokenHash) => getKey(tokenHash)));
|
|
27
33
|
},
|
|
28
|
-
update: async (tokenHash,
|
|
29
|
-
const result = await client.set(getKey(tokenHash), value, {
|
|
34
|
+
update: async ({ tokenHash, ttl, value }) => {
|
|
35
|
+
const result = await client.set(getKey(tokenHash), value, {
|
|
36
|
+
EX: ttl,
|
|
37
|
+
XX: true,
|
|
38
|
+
});
|
|
30
39
|
return result === "OK";
|
|
31
40
|
},
|
|
32
|
-
keep: async (tokenHash, value) => {
|
|
41
|
+
keep: async ({ tokenHash, value }) => {
|
|
33
42
|
const result = await client.set(getKey(tokenHash), value, {
|
|
34
43
|
KEEPTTL: true,
|
|
35
44
|
XX: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/redis/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/redis/index.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { PasswordConfig, SessionConfig } from "./config.js";
|
|
2
2
|
import { type PasswordService } from "./password/index.js";
|
|
3
|
-
import type { RedisSessionStore,
|
|
3
|
+
import type { RedisSessionStore, SessionRecords, SessionService } from "./session/types.js";
|
|
4
4
|
export type AuthConfig = {
|
|
5
5
|
password?: PasswordConfig;
|
|
6
6
|
session?: SessionConfig;
|
|
7
7
|
};
|
|
8
8
|
export type AuthDeps = AuthConfig & {
|
|
9
|
-
|
|
9
|
+
records: SessionRecords;
|
|
10
10
|
redis: RedisSessionStore;
|
|
11
11
|
};
|
|
12
12
|
export type Auth<TData extends object> = {
|
|
13
13
|
password: PasswordService;
|
|
14
14
|
session: SessionService<TData>;
|
|
15
15
|
};
|
|
16
|
-
export declare const createAuth: <TData extends object = Record<string, unknown>>({
|
|
16
|
+
export declare const createAuth: <TData extends object = Record<string, unknown>>({ password, records, redis, session, }: AuthDeps) => Auth<TData>;
|
|
17
17
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACf,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG;IAClC,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,MAAM,IAAI;IACvC,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;CAChC,CAAC;AA8BF,eAAO,MAAM,UAAU,GAAI,KAAK,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,wCAKxE,QAAQ,KAAG,IAAI,CAAC,KAAK,CAoBvB,CAAC"}
|