rst-auth 0.1.0 → 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/CHANGELOG.md CHANGED
@@ -4,6 +4,8 @@ Notable changes to rst-auth are recorded here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ - Added optional `auth.accounts.register()` and `auth.accounts.login()` helpers that use an app-provided model and lookup callback while keeping database ownership in the app.
8
+ - Bumped package metadata to 0.2.0 for the expanded API; existing low-level password, token, and refresh APIs remain available.
7
9
  - Added a standalone HTML/CSS/JavaScript documentation site and GitHub Pages deployment workflow.
8
10
  - Added a browser-based auth flow demo to the Express example.
9
11
  - Added a TypeScript Express API example that is installed from an npm pack tarball.
package/README.md CHANGED
@@ -1,8 +1,71 @@
1
1
  # RST-Auth
2
2
 
3
- **[Documentation site](https://sayedrisat.github.io/rst-auth/)** · [GitHub repository](https://github.com/sayedrisat/rst-auth)
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/rst-auth"><img alt="npm version" src="https://img.shields.io/npm/v/rst-auth?color=4c8bf5&label=npm"></a>
5
+ <a href="https://github.com/sayedrisat/rst-auth/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/sayedrisat/rst-auth/ci.yml?branch=main&label=CI"></a>
6
+ <img alt="Node.js 22+" src="https://img.shields.io/badge/Node.js-22%2B-43853d">
7
+ <a href="LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://sayedrisat.github.io/rst-auth/">Documentation</a> ·
12
+ <a href="https://github.com/sayedrisat/rst-auth">GitHub</a> ·
13
+ <a href="https://www.npmjs.com/package/rst-auth">npm</a> ·
14
+ <a href="examples/express-api/">Runnable Express example</a>
15
+ </p>
16
+
17
+ > **Complex authentication. Simple methods. Full control. Open source.**
18
+
19
+ RST-Auth is a small set of authentication building blocks for Node.js. It handles reusable security mechanics; **your app keeps its users, database, routes, business rules, and API responses.**
20
+
21
+ | Your app owns | RST-Auth provides |
22
+ | ---------------------------------------------------- | ---------------------------------------------------------- |
23
+ | User records, DB queries, signup/login controllers | Password hashing and verification with `bcryptjs` |
24
+ | Roles, permissions, and business decisions | Signed access tokens and optional Express middleware |
25
+ | API response shapes, frontend, and account lifecycle | Stateful refresh rotation through your `RefreshTokenStore` |
26
+
27
+ > **Project status:** `0.1.0` alpha. The API may change. This project is not a security audit or a claim of production readiness.
28
+
29
+ ## Authentication flow
30
+
31
+ This overview shows where the package fits. The application connects its own user repository and persistent refresh-token store; RST-Auth does not query the user database.
32
+
33
+ ```mermaid
34
+ flowchart LR
35
+ client[Browser or API client]
36
+ app[Your app<br/>routes, controllers, policy]
37
+ auth[RST-Auth<br/>bcryptjs · jose · refresh service]
38
+ users[(Your user database)]
39
+ store[(Your atomic RefreshTokenStore)]
40
+
41
+ client -->|signup / login| app
42
+ app <-->|lookup user · save password hash| users
43
+ app -->|hash / verify · sign access token| auth
44
+ auth -->|opaque token hash · atomic consume| store
45
+ auth -->|access token + refresh token result| app
46
+ app -->|Bearer token or HttpOnly cookie| client
47
+ client -->|protected request| app
48
+ app -->|verify access token| auth
49
+ ```
50
+
51
+ During refresh, the store atomically consumes the presented token hash. A successful rotation issues a successor in the same family; replay revokes that family. See the [end-to-end flow in the docs](https://sayedrisat.github.io/rst-auth/#flow) for the walkthrough and token-delivery trade-offs.
52
+
53
+ <details>
54
+ <summary>Contents</summary>
4
55
 
5
- **Complex authentication. Simple methods. Full control. Open source.**
56
+ - [Overview and features](#overview)
57
+ - [Install](#install)
58
+ - [Minimal setup](#minimal-setup)
59
+ - [Passwords](#passwords)
60
+ - [Access tokens](#access-tokens)
61
+ - [Refresh tokens](#refresh-tokens)
62
+ - [Express middleware and validation](#express-middleware)
63
+ - [Configuration](#configuration-reference)
64
+ - [Database integration and limitations](#database-integration-model)
65
+ - [Testing and contributing](#testing)
66
+ - [Comparison](#comparison)
67
+
68
+ </details>
6
69
 
7
70
  ## Overview
8
71
 
@@ -75,6 +138,38 @@ if (!user) await auth.password.verifyDummy(password);
75
138
 
76
139
  Passwords above 72 UTF-8 bytes are rejected because bcrypt truncates longer inputs. The default work factor is 12; benchmark it on the deployment hardware because hashing and `createAuth()` startup work increase with the setting. See [passwords](docs/passwords.md).
77
140
 
141
+ ### Optional register/login helpers
142
+
143
+ If you want the toolkit to hash and verify passwords inside your normal controller flow, pass your existing model and the email lookup you already use. The toolkit does not pick a database, model, schema, route, or response format for you:
144
+
145
+ ```ts
146
+ const auth = createAuth({
147
+ accessToken: { key: new TextEncoder().encode(secret), expiresInSeconds: 900 },
148
+ refreshToken: {
149
+ store: refreshTokenStore, // Your persistent atomic store in deployed apps.
150
+ refreshTokenTtl: 7 * 24 * 60 * 60,
151
+ absoluteLifetime: 30 * 24 * 60 * 60,
152
+ },
153
+ accounts: {
154
+ model: User, // Must provide create(values).
155
+ findByEmail: (email) => User.findOne({ email }),
156
+ getSubject: (user) => String(user._id),
157
+ getAccessClaims: (user) => ({ role: user.role }),
158
+ },
159
+ });
160
+
161
+ // In your existing signup/login controllers:
162
+ const session = await auth.accounts.register({
163
+ email: req.body.email,
164
+ password: req.body.password,
165
+ profile: { name: req.body.name }, // Never pass client role/permission fields.
166
+ });
167
+ res.status(201).json({ user: session.user, accessToken: session.accessToken });
168
+ // Deliver session.refreshToken through an HttpOnly cookie or your chosen channel.
169
+ ```
170
+
171
+ `auth.accounts.login({ email, password })` performs the lookup, bcrypt check (including dummy work for an unknown email), previous-session revocation, and token issuance. These helpers require refresh support and a `RefreshTokenStore`; the in-memory store is only for tests/local work. See [account helpers](docs/accounts.md).
172
+
78
173
  ## Access tokens
79
174
 
80
175
  ```ts
@@ -172,7 +267,7 @@ The package ships declarations and strict public types. `req.auth` and `req.vali
172
267
 
173
268
  ## Database integration model
174
269
 
175
- The toolkit does not create a user table or issue database queries. Your repository/controller code stores password hashes and looks up users. Refresh support uses the `RefreshTokenStore` interface; implement it with your own persistence and atomic compare-and-swap operation, then run the `rst-auth/testing` conformance suite against it. See [installation](docs/installation.md#database-integration-model) and [refresh tokens](docs/refresh-tokens.md).
270
+ The toolkit does not choose a database or user schema. You can keep your own signup/login code using `auth.password`, or opt into `auth.accounts` and supply your model plus `findByEmail` callback. Refresh support still requires a persistent `RefreshTokenStore` with atomic compare-and-swap; run the `rst-auth/testing` conformance suite against it. See [account helpers](docs/accounts.md) and [refresh tokens](docs/refresh-tokens.md).
176
271
 
177
272
  ## Limitations
178
273
 
@@ -0,0 +1,41 @@
1
+ import type { AccessTokenService } from "./tokens.js";
2
+ import type { PasswordService } from "./password.js";
3
+ import type { RefreshTokenService } from "./refresh.js";
4
+ export interface AccountModelLike<User = unknown> {
5
+ create(values: Record<string, unknown>): PromiseLike<User> | User;
6
+ }
7
+ /**
8
+ * App-owned database adapter for the optional accounts helper. Pass the model
9
+ * and the query used to find an account; the package handles hash/verify and
10
+ * session issuance without taking ownership of the database.
11
+ */
12
+ export interface AccountAdapter<User = unknown> {
13
+ model: AccountModelLike<User>;
14
+ findByEmail(email: string): PromiseLike<User | null> | User | null;
15
+ getSubject?: (user: User) => string;
16
+ getAccessClaims?: (user: User) => Record<string, unknown>;
17
+ passwordHashField?: string;
18
+ /** Keep the original single-session behavior by revoking old families at login. */
19
+ revokePreviousSessionsOnLogin?: boolean;
20
+ }
21
+ export interface RegisterAccountInput {
22
+ email: string;
23
+ password: string;
24
+ profile?: Record<string, unknown>;
25
+ }
26
+ export interface LoginAccountInput {
27
+ email: string;
28
+ password: string;
29
+ }
30
+ export interface AccountSession {
31
+ user: unknown;
32
+ accessToken: string;
33
+ refreshToken: string;
34
+ }
35
+ export interface AccountService {
36
+ register(input: RegisterAccountInput): Promise<AccountSession>;
37
+ login(input: LoginAccountInput): Promise<AccountSession>;
38
+ }
39
+ export declare function validateAccountAdapter(adapter: unknown): asserts adapter is AccountAdapter;
40
+ export declare function createAccountService<User>(adapter: AccountAdapter<User>, password: PasswordService, tokens: AccessTokenService, refresh: RefreshTokenService): AccountService;
41
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../src/accounts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,WAAW,gBAAgB,CAAC,IAAI,GAAG,OAAO;IAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACnE;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc,CAAC,IAAI,GAAG,OAAO;IAC5C,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC9B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IACnE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mFAAmF;IACnF,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/D,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1D;AAgFD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,OAAO,IAAI,cAAc,CA6CnC;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EACvC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,EAC7B,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,mBAAmB,GAC3B,cAAc,CAkGhB"}
@@ -0,0 +1,169 @@
1
+ import { AuthError } from "./errors.js";
2
+ const PRIVILEGED_PROFILE_FIELDS = new Set([
3
+ "role",
4
+ "roles",
5
+ "permissions",
6
+ "scopes",
7
+ "isAdmin",
8
+ "admin",
9
+ ]);
10
+ function invalidInput(message) {
11
+ throw new AuthError("VALIDATION_ERROR", message);
12
+ }
13
+ function normalizedEmail(email) {
14
+ if (typeof email !== "string" || email.trim().length === 0) {
15
+ invalidInput("Email must be a non-empty string");
16
+ }
17
+ return email.trim();
18
+ }
19
+ function readField(user, field) {
20
+ if (typeof user !== "object" || user === null)
21
+ return undefined;
22
+ return user[field];
23
+ }
24
+ function plainUser(user) {
25
+ if (typeof user !== "object" || user === null) {
26
+ throw new AuthError("UNAUTHORIZED", "Account lookup returned no user");
27
+ }
28
+ const toObject = user.toObject;
29
+ const value = typeof toObject === "function" ? toObject.call(user) : user;
30
+ if (typeof value !== "object" || value === null) {
31
+ throw new AuthError("UNAUTHORIZED", "Account lookup returned no user");
32
+ }
33
+ return { ...value };
34
+ }
35
+ function publicUser(user, passwordHashField) {
36
+ const copy = plainUser(user);
37
+ delete copy[passwordHashField];
38
+ // Never expose legacy/raw session fields if a user schema still has them.
39
+ delete copy.refreshToken;
40
+ delete copy.refreshTokens;
41
+ delete copy.authRefreshTokens;
42
+ return copy;
43
+ }
44
+ function subjectFor(adapter, user) {
45
+ const value = adapter.getSubject?.(user) ??
46
+ readField(user, "_id") ??
47
+ readField(user, "id");
48
+ const subject = typeof value === "string"
49
+ ? value
50
+ : typeof value === "number" || typeof value === "bigint"
51
+ ? String(value)
52
+ : typeof value === "object" && value !== null
53
+ ? String(value)
54
+ : undefined;
55
+ if (typeof subject !== "string" || subject.length === 0) {
56
+ throw new AuthError("INVALID_CONFIGURATION", "Account adapter must provide a stable user subject");
57
+ }
58
+ return subject;
59
+ }
60
+ function accessClaimsFor(adapter, user) {
61
+ if (adapter.getAccessClaims)
62
+ return adapter.getAccessClaims(user);
63
+ const role = readField(user, "role");
64
+ return typeof role === "string" ? { role } : {};
65
+ }
66
+ export function validateAccountAdapter(adapter) {
67
+ if (!adapter || typeof adapter !== "object") {
68
+ throw new AuthError("INVALID_CONFIGURATION", "accounts must be an object");
69
+ }
70
+ const value = adapter;
71
+ if (!value.model || typeof value.model.create !== "function") {
72
+ throw new AuthError("INVALID_CONFIGURATION", "accounts.model must provide create()");
73
+ }
74
+ if (typeof value.findByEmail !== "function") {
75
+ throw new AuthError("INVALID_CONFIGURATION", "accounts.findByEmail must be a function");
76
+ }
77
+ if (value.getSubject !== undefined &&
78
+ typeof value.getSubject !== "function") {
79
+ throw new AuthError("INVALID_CONFIGURATION", "accounts.getSubject must be a function");
80
+ }
81
+ if (value.getAccessClaims !== undefined &&
82
+ typeof value.getAccessClaims !== "function") {
83
+ throw new AuthError("INVALID_CONFIGURATION", "accounts.getAccessClaims must be a function");
84
+ }
85
+ if (value.passwordHashField !== undefined &&
86
+ (typeof value.passwordHashField !== "string" ||
87
+ value.passwordHashField.length === 0)) {
88
+ throw new AuthError("INVALID_CONFIGURATION", "accounts.passwordHashField must be a non-empty string");
89
+ }
90
+ }
91
+ export function createAccountService(adapter, password, tokens, refresh) {
92
+ const passwordHashField = adapter.passwordHashField ?? "passwordHash";
93
+ const revokePreviousSessionsOnLogin = adapter.revokePreviousSessionsOnLogin ?? true;
94
+ async function createSession(user) {
95
+ const subject = subjectFor(adapter, user);
96
+ const accessToken = await tokens.generateAccessToken({
97
+ ...accessClaimsFor(adapter, user),
98
+ sub: subject,
99
+ });
100
+ const issuedRefresh = await refresh.issue({ subject });
101
+ return {
102
+ user: publicUser(user, passwordHashField),
103
+ accessToken,
104
+ refreshToken: issuedRefresh.refreshToken,
105
+ };
106
+ }
107
+ return {
108
+ async register({ email: rawEmail, password: rawPassword, profile = {} }) {
109
+ const email = normalizedEmail(rawEmail);
110
+ if (!profile || typeof profile !== "object" || Array.isArray(profile)) {
111
+ invalidInput("profile must be an object when provided");
112
+ }
113
+ const unsafeField = Object.keys(profile).find((key) => PRIVILEGED_PROFILE_FIELDS.has(key));
114
+ if (unsafeField) {
115
+ invalidInput(`Signup cannot set privileged field: ${unsafeField}`);
116
+ }
117
+ const existing = await adapter.findByEmail(email);
118
+ if (existing) {
119
+ throw new AuthError("ACCOUNT_EXISTS", "An account already exists for this email");
120
+ }
121
+ const passwordHash = await password.hash(rawPassword);
122
+ let user;
123
+ try {
124
+ user = await adapter.model.create({
125
+ ...profile,
126
+ email,
127
+ [passwordHashField]: passwordHash,
128
+ });
129
+ }
130
+ catch (cause) {
131
+ // A unique email index may win a concurrent signup race.
132
+ if (typeof cause === "object" &&
133
+ cause !== null &&
134
+ "code" in cause &&
135
+ cause.code === 11000) {
136
+ throw new AuthError("ACCOUNT_EXISTS", "An account already exists for this email", { cause });
137
+ }
138
+ throw cause;
139
+ }
140
+ return createSession(user);
141
+ },
142
+ async login({ email: rawEmail, password: rawPassword }) {
143
+ const email = normalizedEmail(rawEmail);
144
+ if (typeof rawPassword !== "string" || rawPassword.length === 0) {
145
+ invalidInput("Password must be a non-empty string");
146
+ }
147
+ const user = await adapter.findByEmail(email);
148
+ if (!user) {
149
+ await password.verifyDummy(rawPassword);
150
+ throw new AuthError("UNAUTHORIZED", "Invalid email or password", {
151
+ publicMessage: "Invalid email or password",
152
+ });
153
+ }
154
+ const storedHash = readField(user, passwordHashField);
155
+ const matches = await password.verify(rawPassword, typeof storedHash === "string" ? storedHash : "");
156
+ if (!matches) {
157
+ throw new AuthError("UNAUTHORIZED", "Invalid email or password", {
158
+ publicMessage: "Invalid email or password",
159
+ });
160
+ }
161
+ const subject = subjectFor(adapter, user);
162
+ if (revokePreviousSessionsOnLogin) {
163
+ await refresh.revokeAllForSubject(subject);
164
+ }
165
+ return createSession(user);
166
+ },
167
+ };
168
+ }
169
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../src/accounts.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { CompactJWSHeaderParameters, KeyInput } from "jose";
2
2
  import type { RefreshTokenStore } from "./refresh-store.js";
3
+ import { type AccountAdapter } from "./accounts.js";
3
4
  export declare const DEFAULT_BCRYPT_ROUNDS = 12;
4
5
  export declare const DEFAULT_ACCESS_TOKEN_TTL_SECONDS = 900;
5
6
  export declare const SUPPORTED_ALGORITHMS: readonly ["HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512", "EdDSA"];
@@ -7,7 +8,7 @@ export type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];
7
8
  export type RuntimeMode = "development" | "production";
8
9
  export type TokenKey = KeyInput;
9
10
  export type KeyResolver = (header: CompactJWSHeaderParameters) => TokenKey | Promise<TokenKey>;
10
- export interface AuthConfig {
11
+ export interface AuthConfig<User = unknown> {
11
12
  mode?: RuntimeMode;
12
13
  password?: {
13
14
  workFactor?: number;
@@ -30,8 +31,10 @@ export interface AuthConfig {
30
31
  refreshTokenTtl: number;
31
32
  absoluteLifetime: number;
32
33
  };
34
+ /** Optional high-level register/login helpers using the app's model/query. */
35
+ accounts?: AccountAdapter<User>;
33
36
  }
34
- export interface ValidatedAuthConfig {
37
+ export interface ValidatedAuthConfig<User = unknown> {
35
38
  mode: RuntimeMode;
36
39
  password: {
37
40
  workFactor: number;
@@ -53,7 +56,8 @@ export interface ValidatedAuthConfig {
53
56
  refreshTokenTtl: number;
54
57
  absoluteLifetime: number;
55
58
  };
59
+ accounts?: AccountAdapter<User>;
56
60
  }
57
61
  export declare function isReservedClaim(name: string): boolean;
58
- export declare function validateAuthConfig(config: AuthConfig): ValidatedAuthConfig;
62
+ export declare function validateAuthConfig<User = unknown>(config: AuthConfig<User>): ValidatedAuthConfig<User>;
59
63
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD,eAAO,MAAM,oBAAoB,gIAcvB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,YAAY,CAAC;AACvD,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAChC,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,0BAA0B,KAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,WAAW,EAAE;QACX,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAC/B,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;QAC3C,GAAG,EAAE,QAAQ,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;QACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,SAAS,CAAC,EAAE,CACV,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,OAAO,CAAC,EAAE,OAAO,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACjC,CAAC;IACF,sFAAsF;IACtF,YAAY,CAAC,EAAE;QACb,KAAK,EAAE,iBAAiB,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,WAAW,EAAE;QACX,SAAS,EAAE,kBAAkB,CAAC;QAC9B,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAC;QAC1C,GAAG,EAAE,QAAQ,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;QACtC,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,SAAS,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,CAAC;KACpD,CAAC;IACF,YAAY,CAAC,EAAE;QACb,KAAK,EAAE,iBAAiB,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAYD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAqBD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAqL1E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AuthError } from "./errors.js";
2
+ import { validateAccountAdapter } from "./accounts.js";
2
3
  export const DEFAULT_BCRYPT_ROUNDS = 12;
3
4
  export const DEFAULT_ACCESS_TOKEN_TTL_SECONDS = 900;
4
5
  const MAX_REFRESH_LIFETIME_SECONDS = 8_000_000_000_000;
@@ -145,6 +146,13 @@ export function validateAuthConfig(config) {
145
146
  absoluteLifetime: refreshConfig.absoluteLifetime,
146
147
  };
147
148
  }
149
+ if (config.accounts !== undefined) {
150
+ // Account helpers issue both tokens, so they require a configured store.
151
+ if (!refreshToken) {
152
+ invalid("accounts requires refreshToken.store to be configured");
153
+ }
154
+ validateAccountAdapter(config.accounts);
155
+ }
148
156
  const requiredClaims = [
149
157
  ...new Set([
150
158
  "sub",
@@ -182,6 +190,7 @@ export function validateAuthConfig(config) {
182
190
  : { isRevoked: tokenConfig.isRevoked }),
183
191
  },
184
192
  ...(refreshToken === undefined ? {} : { refreshToken }),
193
+ ...(config.accounts === undefined ? {} : { accounts: config.accounts }),
185
194
  };
186
195
  }
187
196
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const AUTH_ERROR_CODES: readonly ["TOKEN_MISSING", "TOKEN_INVALID", "TOKEN_EXPIRED", "REFRESH_TOKEN_INVALID", "REFRESH_TOKEN_REUSED", "SESSION_REVOKED", "UNAUTHORIZED", "FORBIDDEN", "VALIDATION_ERROR", "INVALID_CONFIGURATION"];
1
+ export declare const AUTH_ERROR_CODES: readonly ["TOKEN_MISSING", "TOKEN_INVALID", "TOKEN_EXPIRED", "REFRESH_TOKEN_INVALID", "REFRESH_TOKEN_REUSED", "SESSION_REVOKED", "ACCOUNT_EXISTS", "UNAUTHORIZED", "FORBIDDEN", "VALIDATION_ERROR", "INVALID_CONFIGURATION"];
2
2
  export type AuthErrorCode = (typeof AUTH_ERROR_CODES)[number];
3
3
  export interface AuthErrorOptions {
4
4
  publicMessage?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,4MAWnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AA4B9D,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,IAAI,EAAE,aAAa,EACnB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,gBAAqB;CASjC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAEzD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,8NAYnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AA8B9D,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAGtB,IAAI,EAAE,aAAa,EACnB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,gBAAqB;CASjC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAEzD"}
package/dist/errors.js CHANGED
@@ -5,6 +5,7 @@ export const AUTH_ERROR_CODES = [
5
5
  "REFRESH_TOKEN_INVALID",
6
6
  "REFRESH_TOKEN_REUSED",
7
7
  "SESSION_REVOKED",
8
+ "ACCOUNT_EXISTS",
8
9
  "UNAUTHORIZED",
9
10
  "FORBIDDEN",
10
11
  "VALIDATION_ERROR",
@@ -17,6 +18,7 @@ const HTTP_STATUS = {
17
18
  REFRESH_TOKEN_INVALID: 401,
18
19
  REFRESH_TOKEN_REUSED: 401,
19
20
  SESSION_REVOKED: 401,
21
+ ACCOUNT_EXISTS: 409,
20
22
  UNAUTHORIZED: 401,
21
23
  FORBIDDEN: 403,
22
24
  VALIDATION_ERROR: 400,
@@ -29,6 +31,7 @@ const PUBLIC_MESSAGES = {
29
31
  REFRESH_TOKEN_INVALID: "Refresh token is invalid",
30
32
  REFRESH_TOKEN_REUSED: "Refresh token is invalid",
31
33
  SESSION_REVOKED: "Authentication has been revoked",
34
+ ACCOUNT_EXISTS: "An account already exists",
32
35
  UNAUTHORIZED: "Authentication is required",
33
36
  FORBIDDEN: "You are not allowed to perform this action",
34
37
  VALIDATION_ERROR: "The request is invalid",
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,eAAe;IACf,eAAe;IACf,eAAe;IACf,uBAAuB;IACvB,sBAAsB;IACtB,iBAAiB;IACjB,cAAc;IACd,WAAW;IACX,kBAAkB;IAClB,uBAAuB;CACf,CAAC;AAIX,MAAM,WAAW,GAAkC;IACjD,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,qBAAqB,EAAE,GAAG;IAC1B,oBAAoB,EAAE,GAAG;IACzB,eAAe,EAAE,GAAG;IACpB,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,GAAG;IACd,gBAAgB,EAAE,GAAG;IACrB,qBAAqB,EAAE,GAAG;CAC3B,CAAC;AAEF,MAAM,eAAe,GAAkC;IACrD,aAAa,EAAE,4BAA4B;IAC3C,aAAa,EAAE,uBAAuB;IACtC,aAAa,EAAE,4BAA4B;IAC3C,qBAAqB,EAAE,0BAA0B;IACjD,oBAAoB,EAAE,0BAA0B;IAChD,eAAe,EAAE,iCAAiC;IAClD,YAAY,EAAE,4BAA4B;IAC1C,SAAS,EAAE,4CAA4C;IACvD,gBAAgB,EAAE,wBAAwB;IAC1C,qBAAqB,EAAE,+BAA+B;CACvD,CAAC;AAQF,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAgB;IACpB,gBAAgB,CAAS;IACzB,aAAa,CAAS;IACtB,MAAM,CAAS;IAExB,YACE,IAAmB,EACnB,gBAAwB,EACxB,UAA4B,EAAE;QAE9B,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,eAAe;IACf,eAAe;IACf,eAAe;IACf,uBAAuB;IACvB,sBAAsB;IACtB,iBAAiB;IACjB,gBAAgB;IAChB,cAAc;IACd,WAAW;IACX,kBAAkB;IAClB,uBAAuB;CACf,CAAC;AAIX,MAAM,WAAW,GAAkC;IACjD,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,aAAa,EAAE,GAAG;IAClB,qBAAqB,EAAE,GAAG;IAC1B,oBAAoB,EAAE,GAAG;IACzB,eAAe,EAAE,GAAG;IACpB,cAAc,EAAE,GAAG;IACnB,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,GAAG;IACd,gBAAgB,EAAE,GAAG;IACrB,qBAAqB,EAAE,GAAG;CAC3B,CAAC;AAEF,MAAM,eAAe,GAAkC;IACrD,aAAa,EAAE,4BAA4B;IAC3C,aAAa,EAAE,uBAAuB;IACtC,aAAa,EAAE,4BAA4B;IAC3C,qBAAqB,EAAE,0BAA0B;IACjD,oBAAoB,EAAE,0BAA0B;IAChD,eAAe,EAAE,iCAAiC;IAClD,cAAc,EAAE,2BAA2B;IAC3C,YAAY,EAAE,4BAA4B;IAC1C,SAAS,EAAE,4CAA4C;IACvD,gBAAgB,EAAE,wBAAwB;IAC1C,qBAAqB,EAAE,+BAA+B;CACvD,CAAC;AAQF,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAgB;IACpB,gBAAgB,CAAS;IACzB,aAAa,CAAS;IACtB,MAAM,CAAS;IAExB,YACE,IAAmB,EACnB,gBAAwB,EACxB,UAA4B,EAAE;QAE9B,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -4,17 +4,20 @@ import { createPasswordService } from "./password.js";
4
4
  import { createAccessTokenService } from "./tokens.js";
5
5
  import { type RefreshTokenService } from "./refresh.js";
6
6
  import { MemoryRefreshTokenStore } from "./memory-refresh-token-store.js";
7
+ import { type AccountService } from "./accounts.js";
7
8
  export interface Auth {
8
9
  password: ReturnType<typeof createPasswordService>;
9
10
  tokens: ReturnType<typeof createAccessTokenService>;
10
11
  refresh?: RefreshTokenService;
12
+ accounts?: AccountService;
11
13
  }
12
- export declare function createAuth(config: AuthConfig): Auth;
14
+ export declare function createAuth<User = unknown>(config: AuthConfig<User>): Auth;
13
15
  export { MemoryRefreshTokenStore };
14
16
  export { AuthError, AUTH_ERROR_CODES, getHttpStatus };
15
17
  export type { ConsumeResult, RefreshTokenRecord, RefreshTokenStatus, RefreshTokenStore, RevokeTokenResult, } from "./refresh-store.js";
16
18
  export type { IssuedRefreshToken, IssueRefreshTokenInput, RefreshTokenService, } from "./refresh.js";
17
19
  export type { AuthErrorCode, AuthErrorOptions } from "./errors.js";
20
+ export type { AccountAdapter, AccountModelLike, AccountService, AccountSession, LoginAccountInput, RegisterAccountInput, } from "./accounts.js";
18
21
  export type { AuthConfig, KeyResolver, RuntimeMode, SupportedAlgorithm, TokenKey, } from "./config.js";
19
22
  export type { AccessTokenClaims, AccessTokenService, VerifiedAccessClaims, } from "./tokens.js";
20
23
  export type { ValidationSchemaMap, ValidationTarget, ValidatorAdapter, } from "./validation.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,MAAM,WAAW,IAAI;IACnB,QAAQ,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IACnD,MAAM,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAUnD;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC;AACtD,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,WAAW,IAAI;IACnB,QAAQ,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IACnD,MAAM,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;IACpD,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAsBzE;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC;AACtD,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -4,15 +4,22 @@ import { createPasswordService } from "./password.js";
4
4
  import { createAccessTokenService } from "./tokens.js";
5
5
  import { createRefreshTokenService, } from "./refresh.js";
6
6
  import { MemoryRefreshTokenStore } from "./memory-refresh-token-store.js";
7
+ import { createAccountService } from "./accounts.js";
7
8
  export function createAuth(config) {
8
9
  const validatedConfig = validateAuthConfig(config);
9
10
  const refresh = validatedConfig.refreshToken
10
11
  ? createRefreshTokenService(validatedConfig.refreshToken)
11
12
  : undefined;
13
+ const password = createPasswordService(validatedConfig.password.workFactor);
14
+ const tokens = createAccessTokenService(validatedConfig.accessToken);
15
+ const accounts = validatedConfig.accounts && refresh
16
+ ? createAccountService(validatedConfig.accounts, password, tokens, refresh)
17
+ : undefined;
12
18
  return {
13
- password: createPasswordService(validatedConfig.password.workFactor),
14
- tokens: createAccessTokenService(validatedConfig.accessToken),
19
+ password,
20
+ tokens,
15
21
  ...(refresh === undefined ? {} : { refresh }),
22
+ ...(accounts === undefined ? {} : { accounts }),
16
23
  };
17
24
  }
18
25
  export { MemoryRefreshTokenStore };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,yBAAyB,GAE1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAQ1E,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,YAAY;QAC1C,CAAC,CAAC,yBAAyB,CAAC,eAAe,CAAC,YAAY,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IACd,OAAO;QACL,QAAQ,EAAE,qBAAqB,CAAC,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC;QACpE,MAAM,EAAE,wBAAwB,CAAC,eAAe,CAAC,WAAW,CAAC;QAC7D,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,yBAAyB,GAE1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAuB,MAAM,eAAe,CAAC;AAS1E,MAAM,UAAU,UAAU,CAAiB,MAAwB;IACjE,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,YAAY;QAC1C,CAAC,CAAC,yBAAyB,CAAC,eAAe,CAAC,YAAY,CAAC;QACzD,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,QAAQ,GAAG,qBAAqB,CAAC,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,wBAAwB,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IACrE,MAAM,QAAQ,GACZ,eAAe,CAAC,QAAQ,IAAI,OAAO;QACjC,CAAC,CAAC,oBAAoB,CAClB,eAAe,CAAC,QAAQ,EACxB,QAAQ,EACR,MAAM,EACN,OAAO,CACR;QACH,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO;QACL,QAAQ;QACR,MAAM;QACN,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;KAChD,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,68 @@
1
+ # Register and login helpers
2
+
3
+ `createAuth()` can expose `auth.accounts.register()` and `auth.accounts.login()` when you configure `accounts` and a refresh-token store. This is an optional shortcut for the repeated password and token work. Your app still owns the database, model schema, email query, routes, authorization policy, and HTTP response.
4
+
5
+ ## Configure your model and lookup
6
+
7
+ The model must have a `create(values)` method. Supply the lookup used by your database library. For example, with Mongoose:
8
+
9
+ ```ts
10
+ const auth = createAuth({
11
+ accessToken: {
12
+ key: new TextEncoder().encode(config.accessTokenSecret),
13
+ expiresInSeconds: config.accessTokenTtlSeconds,
14
+ issuer: "my-api",
15
+ audience: "my-client",
16
+ },
17
+ refreshToken: {
18
+ store: mongoRefreshTokenStore,
19
+ refreshTokenTtl: config.refreshTokenTtlSeconds,
20
+ absoluteLifetime: 30 * 24 * 60 * 60,
21
+ },
22
+ accounts: {
23
+ model: User,
24
+ findByEmail: (email) => User.findOne({ email }),
25
+ getSubject: (user) => String(user._id),
26
+ getAccessClaims: (user) => ({ role: user.role }),
27
+ },
28
+ });
29
+ ```
30
+
31
+ The app reads environment variables in its own config layer and passes the values above. `rst-auth` never reads `process.env`. `passwordHash` is the default persisted hash field; set `passwordHashField` if your schema uses another name.
32
+
33
+ ## Use it from existing controllers
34
+
35
+ ```ts
36
+ const session = await auth.accounts.register({
37
+ email: req.body.email,
38
+ password: req.body.password,
39
+ profile: { name: req.body.name },
40
+ });
41
+ res.status(201).json({
42
+ user: session.user,
43
+ accessToken: session.accessToken,
44
+ });
45
+ // Send session.refreshToken using an HttpOnly cookie or another deliberate channel.
46
+ ```
47
+
48
+ ```ts
49
+ const session = await auth.accounts.login({
50
+ email: req.body.email,
51
+ password: req.body.password,
52
+ });
53
+ res.json({ user: session.user, accessToken: session.accessToken });
54
+ ```
55
+
56
+ The helper rejects client-provided `role`, `roles`, `permissions`, `scopes`, `admin`, and `isAdmin` fields in `profile`. Assign privileges in trusted application code. The returned user omits the password hash and common legacy raw refresh-token fields. Select the exact response fields your app intends to expose.
57
+
58
+ For unknown users, login performs a dummy bcrypt comparison and returns the same `UNAUTHORIZED` error as a wrong password. A successful login revokes prior refresh families for that subject by default; set `revokePreviousSessionsOnLogin: false` when concurrent sessions are desired.
59
+
60
+ ## What the app still provides
61
+
62
+ - A model with a unique email constraint and a `create()` method.
63
+ - `findByEmail(email)` that returns the user record or `null`.
64
+ - A stable subject mapping, and any trusted claims needed by authorization.
65
+ - A persistent, atomic `RefreshTokenStore` for multi-process deployments. `MemoryRefreshTokenStore` is only for tests and local development.
66
+ - Request validation and response shaping, plus rate limits, lockout, email verification, password reset, and CSRF policy.
67
+
68
+ The helper is not a database adapter and does not make a Mongoose dependency part of the package. See [refresh tokens](refresh-tokens.md) for store requirements and [security](security.md) for application responsibilities.
package/docs/claims.md CHANGED
@@ -1,40 +1,42 @@
1
1
  # README claim-to-test map
2
2
 
3
- | README claim | Test |
4
- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
5
- | Password hashing and verification work, including wrong-password rejection | `test/password.test.ts` — “hashes and verifies passwords” |
6
- | Password input is non-empty and limited to 72 UTF-8 bytes | `test/password.test.ts` — “rejects empty and over-72-byte passwords by UTF-8 byte length” |
7
- | Malformed hashes fail safely and dummy verification is available | `test/password.test.ts` — “fails safely for malformed hashes and supports dummy verification” |
8
- | Errors expose stable codes, safe public messages, status mappings, custom public messages, and causes | `test/errors.test.ts` |
9
- | Config defaults, secret length, expiry, algorithm, work factor, and production requirements are validated | `test/config.test.ts` |
10
- | Access-token signatures and configured issuer, audience, and required claims are verified | `test/tokens.test.ts` — “generates and verifies signed tokens with configured claims” |
11
- | Algorithms are pinned and `none` or a header-selected alternative is rejected | `test/tokens.test.ts` — “pins the allowed algorithm and rejects none or header-selected alternatives” |
12
- | Caller input cannot override reserved claims | `test/tokens.test.ts` — “rejects caller overrides of reserved claims” |
13
- | Verification requires `exp` and `iat` | `test/tokens.test.ts` — “requires exp and iat on verified tokens” |
14
- | A refresh-typed token is rejected as an access token | `test/tokens.test.ts` — “rejects token-type confusion” |
15
- | Token expiration is enforced | `test/tokens.test.ts` — “uses fake time to enforce expiry” |
16
- | Verification supports async `kid` key resolution and a revocation callback | `test/tokens.test.ts` — “resolves verification keys asynchronously by kid and supports revocation hooks” |
17
- | Asymmetric signing and verification keys work with the configured algorithm | `test/tokens.test.ts` — “supports asymmetric signing and verification keys” |
18
- | Store-less configuration cannot enable stateless re-issuance as rotation, and partial config is rejected | `test/refresh.test.ts` — “refresh-stateless-not-rotation: refuses refresh without a configured store” |
19
- | Issued refresh tokens are opaque random values and only their SHA-256 hashes reach the store | `test/refresh.test.ts` — “issues opaque 256-bit tokens and stores only their SHA-256 hashes” |
20
- | The memory store is instance-local and cannot serve another store instance | `test/refresh.test.ts` — “documents the memory store's instance-local behavior” |
21
- | Rotation preserves the family, detects replay, and revokes family descendants | `test/refresh.test.ts` — “rotates into the same family and detects replay by revoking that family” |
22
- | Concurrent replay cannot return a successor after family revocation | `test/refresh.test.ts` — “does not return a rotation result when a concurrent replay revokes the family” |
23
- | Unknown, expired, and revoked refresh tokens cannot rotate | `test/refresh.test.ts` — “never rotates unknown, expired, or revoked values” |
24
- | Rotation is capped at the family's absolute lifetime | `test/refresh.test.ts` — “caps every rotation at the family's absolute lifetime” |
25
- | Rotation renews idle expiry without extending the family absolute lifetime | `test/refresh.test.ts` — “renews idle expiry on rotation without changing the family cap” |
26
- | Refresh and access tokens cannot be confused | `test/refresh.test.ts` — “rejects an access token as refresh and a refresh token as access” |
27
- | Refresh store rotation, replay, reuse revocation, expiry, revocation, and concurrent consume conform | `test/refresh-store-conformance.test.ts` — registered conformance cases |
28
- | Express 4 and 5 return safe 401s for absent, malformed, invalid, and expired access tokens | `test/express.integration.test.ts` — “distinguishes missing and malformed bearer headers and rejects invalid or expired tokens” |
29
- | Optional auth accepts absence but rejects present invalid tokens; valid identities and role checks work | `test/express.integration.test.ts` — “authenticates, supports optional auth, and enforces role access” |
30
- | Express passes the request to the revocation hook and supports application identity lookup | `test/express.integration.test.ts` — “passes the request to isRevoked and allows identity lookup” |
31
- | Zod validates body, params, and query into `req.validated` without mutating `req.body` | `test/express.integration.test.ts` — “validates body, params, and query without mutating Express request fields” |
32
- | Validation and unexpected errors support custom formatting without exposing private details | `test/express.integration.test.ts` — “supports a custom schema formatter and keeps unexpected errors private” |
33
- | Cookie and composed token extractors work; refresh cookies default to HttpOnly, Secure, and SameSite=Lax | `test/express.integration.test.ts` — “supports cookie and composed extractors, and sets secure refresh-cookie defaults” |
34
- | Query-string token extraction is not enabled by default, while explicit custom extraction remains possible | `test/express.integration.test.ts` — “allows a custom token extractor while preserving strict header parsing by default” |
35
- | The package is ESM, declares Node 22+, and maps every supported subpath to built files | `test/package.test.ts` — “declares ESM, Node 22+, and built targets for every documented subpath” |
36
- | The example assigns roles server-side and rejects a client-supplied signup role | `examples/express-api/test/app.test.ts` — “no-role-from-client: rejects a client role and creates no account” |
37
- | The example demonstrates app-owned persistence/controllers, password hashing, token routes, and role checks | `examples/express-api/test/app.test.ts` — “uses application-owned controllers, hashing, and repository roles” |
38
- | Cookie delivery sets safe cookie flags, and example error responses avoid credential leakage | `examples/express-api/test/app.test.ts` — cookie defaults and “maps login failures without returning password hashes or secrets” |
39
- | Core configuration does not read environment variables | `test/package.test.ts` — “keeps environment reads out of the injected core configuration layer” |
40
- | The bcrypt work factor is configurable and defaults to 12 | `test/password.test.ts` — “uses the configured bcrypt work factor and defaults to 12” |
3
+ | README claim | Test |
4
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
5
+ | Password hashing and verification work, including wrong-password rejection | `test/password.test.ts` — “hashes and verifies passwords” |
6
+ | Password input is non-empty and limited to 72 UTF-8 bytes | `test/password.test.ts` — “rejects empty and over-72-byte passwords by UTF-8 byte length” |
7
+ | Malformed hashes fail safely and dummy verification is available | `test/password.test.ts` — “fails safely for malformed hashes and supports dummy verification” |
8
+ | Errors expose stable codes, safe public messages, status mappings, custom public messages, and causes | `test/errors.test.ts` |
9
+ | Config defaults, secret length, expiry, algorithm, work factor, and production requirements are validated | `test/config.test.ts` |
10
+ | Access-token signatures and configured issuer, audience, and required claims are verified | `test/tokens.test.ts` — “generates and verifies signed tokens with configured claims” |
11
+ | Algorithms are pinned and `none` or a header-selected alternative is rejected | `test/tokens.test.ts` — “pins the allowed algorithm and rejects none or header-selected alternatives” |
12
+ | Caller input cannot override reserved claims | `test/tokens.test.ts` — “rejects caller overrides of reserved claims” |
13
+ | Verification requires `exp` and `iat` | `test/tokens.test.ts` — “requires exp and iat on verified tokens” |
14
+ | A refresh-typed token is rejected as an access token | `test/tokens.test.ts` — “rejects token-type confusion” |
15
+ | Token expiration is enforced | `test/tokens.test.ts` — “uses fake time to enforce expiry” |
16
+ | Verification supports async `kid` key resolution and a revocation callback | `test/tokens.test.ts` — “resolves verification keys asynchronously by kid and supports revocation hooks” |
17
+ | Asymmetric signing and verification keys work with the configured algorithm | `test/tokens.test.ts` — “supports asymmetric signing and verification keys” |
18
+ | Store-less configuration cannot enable stateless re-issuance as rotation, and partial config is rejected | `test/refresh.test.ts` — “refresh-stateless-not-rotation: refuses refresh without a configured store” |
19
+ | Issued refresh tokens are opaque random values and only their SHA-256 hashes reach the store | `test/refresh.test.ts` — “issues opaque 256-bit tokens and stores only their SHA-256 hashes” |
20
+ | The memory store is instance-local and cannot serve another store instance | `test/refresh.test.ts` — “documents the memory store's instance-local behavior” |
21
+ | Rotation preserves the family, detects replay, and revokes family descendants | `test/refresh.test.ts` — “rotates into the same family and detects replay by revoking that family” |
22
+ | Concurrent replay cannot return a successor after family revocation | `test/refresh.test.ts` — “does not return a rotation result when a concurrent replay revokes the family” |
23
+ | Unknown, expired, and revoked refresh tokens cannot rotate | `test/refresh.test.ts` — “never rotates unknown, expired, or revoked values” |
24
+ | Rotation is capped at the family's absolute lifetime | `test/refresh.test.ts` — “caps every rotation at the family's absolute lifetime” |
25
+ | Rotation renews idle expiry without extending the family absolute lifetime | `test/refresh.test.ts` — “renews idle expiry on rotation without changing the family cap” |
26
+ | Refresh and access tokens cannot be confused | `test/refresh.test.ts` — “rejects an access token as refresh and a refresh token as access” |
27
+ | Refresh store rotation, replay, reuse revocation, expiry, revocation, and concurrent consume conform | `test/refresh-store-conformance.test.ts` — registered conformance cases |
28
+ | Express 4 and 5 return safe 401s for absent, malformed, invalid, and expired access tokens | `test/express.integration.test.ts` — “distinguishes missing and malformed bearer headers and rejects invalid or expired tokens” |
29
+ | Optional auth accepts absence but rejects present invalid tokens; valid identities and role checks work | `test/express.integration.test.ts` — “authenticates, supports optional auth, and enforces role access” |
30
+ | Express passes the request to the revocation hook and supports application identity lookup | `test/express.integration.test.ts` — “passes the request to isRevoked and allows identity lookup” |
31
+ | Optional account helpers hash on signup, verify on login, equalize missing-user work, omit hashes from returned user data, and reject client privilege fields | `test/accounts.test.ts` — high-level account helper cases |
32
+ | Account helpers reject duplicate accounts and require refresh storage | `test/accounts.test.ts` — duplicate-account and missing-store cases |
33
+ | Zod validates body, params, and query into `req.validated` without mutating `req.body` | `test/express.integration.test.ts` — “validates body, params, and query without mutating Express request fields” |
34
+ | Validation and unexpected errors support custom formatting without exposing private details | `test/express.integration.test.ts` — “supports a custom schema formatter and keeps unexpected errors private” |
35
+ | Cookie and composed token extractors work; refresh cookies default to HttpOnly, Secure, and SameSite=Lax | `test/express.integration.test.ts` — “supports cookie and composed extractors, and sets secure refresh-cookie defaults” |
36
+ | Query-string token extraction is not enabled by default, while explicit custom extraction remains possible | `test/express.integration.test.ts` — “allows a custom token extractor while preserving strict header parsing by default” |
37
+ | The package is ESM, declares Node 22+, and maps every supported subpath to built files | `test/package.test.ts` — “declares ESM, Node 22+, and built targets for every documented subpath” |
38
+ | The example assigns roles server-side and rejects a client-supplied signup role | `examples/express-api/test/app.test.ts` — “no-role-from-client: rejects a client role and creates no account” |
39
+ | The example demonstrates app-owned persistence/controllers, password hashing, token routes, and role checks | `examples/express-api/test/app.test.ts` — “uses application-owned controllers, hashing, and repository roles” |
40
+ | Cookie delivery sets safe cookie flags, and example error responses avoid credential leakage | `examples/express-api/test/app.test.ts` — cookie defaults and “maps login failures without returning password hashes or secrets” |
41
+ | Core configuration does not read environment variables | `test/package.test.ts` — “keeps environment reads out of the injected core configuration layer” |
42
+ | The bcrypt work factor is configurable and defaults to 12 | `test/password.test.ts` — “uses the configured bcrypt work factor and defaults to 12” |
@@ -20,6 +20,12 @@ const auth = createAuth({
20
20
  refreshTokenTtl: 60 * 60 * 24 * 7,
21
21
  absoluteLifetime: 60 * 60 * 24 * 30,
22
22
  },
23
+ accounts: {
24
+ model: User,
25
+ findByEmail: (email) => User.findOne({ email }),
26
+ getSubject: (user) => String(user._id),
27
+ getAccessClaims: (user) => ({ role: user.role }),
28
+ },
23
29
  });
24
30
  ```
25
31
 
@@ -27,4 +33,6 @@ HMAC keys are `Uint8Array` values of at least 32 bytes. Asymmetric algorithms re
27
33
 
28
34
  The default bcrypt work factor is 12 and the default access-token expiry is 900 seconds. Work factor must be an integer from 4 to 31. Refresh support is disabled when `refreshToken` is omitted; enabling it requires a store, idle TTL, and absolute family lifetime, each a positive safe integer in seconds.
29
35
 
36
+ `accounts` is optional. When provided, it enables `auth.accounts.register()` and `auth.accounts.login()` and requires refresh support. Pass your own model with `create(values)` and your own `findByEmail(email)` lookup. Optional `getSubject` and `getAccessClaims` callbacks map your user record into token identity and trusted claims. The library does not select or import a database package. See [account helpers](accounts.md).
37
+
30
38
  `isRevoked(claims, context?)` can check application state during verification. Express passes the current request as `context`; direct calls can pass a context themselves. The hook makes verification stateful and adds its latency and availability to protected requests.
@@ -34,6 +34,6 @@ Read secrets in the application's configuration layer and pass them into `create
34
34
 
35
35
  ## Database integration model
36
36
 
37
- The application owns user records, unique email constraints, queries, transactions, and user status rules. The package accepts a `RefreshTokenStore` when refresh support is enabled. Production implementations should store token hashes and make consume/revocation operations atomic and shared across application instances. The example app uses an in-memory user repository and refresh store only to demonstrate the controller boundaries; neither is suitable for deployed state.
37
+ The application owns user records, unique email constraints, queries, transactions, and user status rules. For repeated password/token work, optionally configure `accounts` with your model and a `findByEmail` callback; this adds `auth.accounts.register()` and `auth.accounts.login()` without choosing your database or routes. The package accepts a `RefreshTokenStore` when refresh support is enabled. Production implementations should store token hashes and make consume/revocation operations atomic and shared across application instances. The example app uses an in-memory user repository and refresh store only to demonstrate the controller boundaries; neither is suitable for deployed state.
38
38
 
39
39
  Use `rst-auth/testing` to register the refresh-store conformance suite with your test runner. A passing suite does not replace reviewing the backend's transactional and consistency guarantees.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rst-auth",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A modular authentication toolkit for Node.js applications",
5
5
  "license": "MIT",
6
6
  "type": "module",