@gauts/auth 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -62
- 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 +12 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +119 -18
- 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 +94 -45
- 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 +49 -23
- 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,11 +104,21 @@ 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
|
|
|
112
|
+
New bcrypt hashes reject passwords above 72 bytes. Applications with historical hashes created from longer bcrypt input can opt into a larger verification-only boundary without permitting new truncated hashes:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
password: {
|
|
116
|
+
algorithm: "bcrypt",
|
|
117
|
+
maxBytes: 72,
|
|
118
|
+
verifyMaxBytes: 1024,
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
89
122
|
The configured algorithm is used for both hashing and verification. The package does not detect, convert, migrate, or fall back to another algorithm.
|
|
90
123
|
|
|
91
124
|
## Login
|
|
@@ -97,22 +130,26 @@ app.post("/auth/login", async (c) => {
|
|
|
97
130
|
const { email, password } = await c.req.json();
|
|
98
131
|
const account = await findAccount(email);
|
|
99
132
|
|
|
100
|
-
if (
|
|
133
|
+
if (
|
|
134
|
+
!account ||
|
|
135
|
+
!(await auth.password.verify({
|
|
136
|
+
password,
|
|
137
|
+
storedHash: account.passwordHash,
|
|
138
|
+
}))
|
|
139
|
+
) {
|
|
101
140
|
return c.json({ error: "Invalid credentials." }, 401);
|
|
102
141
|
}
|
|
103
142
|
|
|
104
|
-
const
|
|
105
|
-
|
|
143
|
+
const session = await hono.createSession({
|
|
144
|
+
accountId: account.id,
|
|
145
|
+
context: c,
|
|
106
146
|
data: {
|
|
107
147
|
email: account.email,
|
|
108
148
|
role: account.role,
|
|
109
149
|
},
|
|
110
|
-
client: await getClient(c),
|
|
111
150
|
});
|
|
112
151
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return c.json({ account: created.session.data });
|
|
152
|
+
return c.json({ account: session.data });
|
|
116
153
|
});
|
|
117
154
|
```
|
|
118
155
|
|
|
@@ -122,14 +159,14 @@ Applications must apply their own login rate limiting and account-enumeration pr
|
|
|
122
159
|
|
|
123
160
|
```ts
|
|
124
161
|
app.get("/account", hono.requireSession, async (c) => {
|
|
125
|
-
const session = c.get("
|
|
126
|
-
const account = await findAccountById(session.
|
|
162
|
+
const session = c.get("session");
|
|
163
|
+
const account = await findAccountById(session.accountId);
|
|
127
164
|
|
|
128
165
|
return c.json({ account });
|
|
129
166
|
});
|
|
130
167
|
```
|
|
131
168
|
|
|
132
|
-
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.
|
|
133
170
|
|
|
134
171
|
Applications that need to populate additional Hono context variables can resolve through the same adapter without duplicating its cookie behavior:
|
|
135
172
|
|
|
@@ -146,54 +183,54 @@ const requireAccount = async (c, next) => {
|
|
|
146
183
|
|
|
147
184
|
```ts
|
|
148
185
|
app.post("/auth/logout", async (c) => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (token) {
|
|
152
|
-
await auth.session.revokeToken(token);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
hono.clearSession(c);
|
|
186
|
+
await hono.revokeSession(c);
|
|
156
187
|
return c.body(null, 204);
|
|
157
188
|
});
|
|
158
189
|
```
|
|
159
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
|
+
|
|
160
194
|
## Active sessions
|
|
161
195
|
|
|
162
196
|
```ts
|
|
163
197
|
const sessions = await auth.session.list(accountId);
|
|
164
198
|
|
|
165
199
|
await auth.session.revoke({
|
|
166
|
-
|
|
200
|
+
accountId,
|
|
167
201
|
sessionId,
|
|
168
202
|
});
|
|
169
203
|
|
|
170
|
-
await auth.session.
|
|
204
|
+
await auth.session.revokeAccount(accountId);
|
|
171
205
|
```
|
|
172
206
|
|
|
173
|
-
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`.
|
|
174
208
|
|
|
175
209
|
## Synchronizing session data
|
|
176
210
|
|
|
177
211
|
When cached session claims change:
|
|
178
212
|
|
|
179
213
|
```ts
|
|
180
|
-
await auth.session.sync(
|
|
181
|
-
|
|
182
|
-
|
|
214
|
+
await auth.session.sync({
|
|
215
|
+
accountId,
|
|
216
|
+
data: {
|
|
217
|
+
email: account.email,
|
|
218
|
+
role: account.role,
|
|
219
|
+
},
|
|
183
220
|
});
|
|
184
221
|
```
|
|
185
222
|
|
|
186
223
|
Synchronization preserves the existing token and Redis TTL.
|
|
187
224
|
|
|
188
|
-
## Session
|
|
225
|
+
## Session records contract
|
|
189
226
|
|
|
190
|
-
Each consuming application maps `
|
|
227
|
+
Each consuming application maps `SessionRecords` to its database. The durable record contains:
|
|
191
228
|
|
|
192
229
|
- Session ID.
|
|
193
|
-
-
|
|
230
|
+
- Account ID and relation owned by the application.
|
|
194
231
|
- SHA-256 token hash.
|
|
195
232
|
- Canonical IP.
|
|
196
|
-
-
|
|
233
|
+
- Platform metadata.
|
|
197
234
|
- Complete User-Agent.
|
|
198
235
|
- Creation, current expiry, update, and revocation timestamps.
|
|
199
236
|
|
|
@@ -206,8 +243,9 @@ Defaults:
|
|
|
206
243
|
```ts
|
|
207
244
|
session: {
|
|
208
245
|
ttl: 7 * 24 * 60 * 60,
|
|
209
|
-
|
|
246
|
+
renewInterval: 24 * 60 * 60,
|
|
210
247
|
max: 10,
|
|
248
|
+
validation: ["userAgent"],
|
|
211
249
|
}
|
|
212
250
|
```
|
|
213
251
|
|
|
@@ -215,24 +253,31 @@ session: {
|
|
|
215
253
|
- Active sessions renew at most once every 24 hours.
|
|
216
254
|
- Renewal keeps the same browser token.
|
|
217
255
|
- There is no absolute session lifetime.
|
|
256
|
+
- Every successful `resolve` call counts as activity and renews the session when due.
|
|
218
257
|
|
|
219
|
-
|
|
258
|
+
## Client validation
|
|
259
|
+
|
|
260
|
+
The default compares only the complete User-Agent:
|
|
220
261
|
|
|
221
262
|
```ts
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
token,
|
|
226
|
-
});
|
|
263
|
+
session: {
|
|
264
|
+
validation: ["userAgent"],
|
|
265
|
+
}
|
|
227
266
|
```
|
|
228
267
|
|
|
229
|
-
|
|
268
|
+
Applications can choose any combination of `ip`, `userAgent`, and `platform`:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
session: {
|
|
272
|
+
validation: ["ip", "userAgent", "platform"],
|
|
273
|
+
}
|
|
274
|
+
```
|
|
230
275
|
|
|
231
|
-
|
|
276
|
+
An empty array disables client-field comparison and validates only the session token. Unknown or duplicate fields are rejected during startup.
|
|
232
277
|
|
|
233
|
-
If
|
|
278
|
+
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.
|
|
234
279
|
|
|
235
|
-
|
|
280
|
+
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.
|
|
236
281
|
|
|
237
282
|
## Package exports
|
|
238
283
|
|
|
@@ -241,5 +286,3 @@ Strict IP binding can log out legitimate users whose public IP changes. It is de
|
|
|
241
286
|
@gauts/auth/redis createRedisStore
|
|
242
287
|
@gauts/auth/hono createHonoAdapter
|
|
243
288
|
```
|
|
244
|
-
|
|
245
|
-
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":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAY9C,MAAM,SAAS,GAAG,CAAC,KAAc,EAAU,EAAE;IAC3C,MAAM,SAAS,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IAE5D,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,WAAW,CAAC;YAChB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,8BAA8B;SACxC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,MAAM,EACN,MAAM,GAAG,EAAE,GACK,EAAqB,EAAE;IACvC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,MAAM,YAAY,SAAS,EAAE,CAAC;IAEvE,OAAO;QACL,MAAM,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;YAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE;gBACxD,EAAE,EAAE,GAAG;gBACP,EAAE,EAAE,IAAI;aACT,CAAC,CAAC;YAEH,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;YACvB,OAAO,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACvC,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC7B,OAAO,WAAW,CAAC,MAAM,KAAK,CAAC;gBAC7B,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;YAC1C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE;gBACxD,EAAE,EAAE,GAAG;gBACP,EAAE,EAAE,IAAI;aACT,CAAC,CAAC;YAEH,OAAO,MAAM,KAAK,IAAI,CAAC;QACzB,CAAC;QAED,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;YACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE;gBACxD,OAAO,EAAE,IAAI;gBACb,EAAE,EAAE,IAAI;aACT,CAAC,CAAC;YAEH,OAAO,MAAM,KAAK,IAAI,CAAC;QACzB,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC5B,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC5B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC7B,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAClD,CAAC;YAEF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
|
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"}
|