najm-auth 2.0.10 → 2.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -2
- package/dist/index.d.ts +85 -4
- package/dist/index.js +313 -16
- package/dist/schema/pg.d.ts +328 -1
- package/dist/schema/pg.js +14 -0
- package/dist/schema/sqlite.d.ts +364 -1
- package/dist/schema/sqlite.js +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ export const products = sqliteTable('products', {
|
|
|
45
45
|
|
|
46
46
|
// Combined schema (always include authSchema)
|
|
47
47
|
export const schema = {
|
|
48
|
-
...authSchema, // users,
|
|
48
|
+
...authSchema, // includes users, tokens, and credentialSetupSessions
|
|
49
49
|
products,
|
|
50
50
|
};
|
|
51
51
|
|
|
@@ -727,7 +727,46 @@ async resetPassword(token: string, newPassword: string) {
|
|
|
727
727
|
}
|
|
728
728
|
```
|
|
729
729
|
|
|
730
|
-
###
|
|
730
|
+
### Purpose-Bound Credential Setup
|
|
731
|
+
|
|
732
|
+
Use `CredentialSetupService` when valid credentials should open only a
|
|
733
|
+
short-lived setup flow, not a complete application session. The default auth
|
|
734
|
+
schema includes the durable `credential_setup_sessions` table for PostgreSQL
|
|
735
|
+
and SQLite; generate and apply a consumer migration after upgrading.
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
import { AuthService, CredentialSetupService } from 'najm-auth';
|
|
739
|
+
|
|
740
|
+
const options = {
|
|
741
|
+
purpose: 'password-setup',
|
|
742
|
+
cookieName: 'my-app.password-setup',
|
|
743
|
+
ttlMs: 10 * 60 * 1000,
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
// Verify the password without minting access/refresh tokens.
|
|
747
|
+
const user = await authService.verifyCredentials({ identifier, password });
|
|
748
|
+
|
|
749
|
+
if (await appRequiresPasswordSetup(user.id)) {
|
|
750
|
+
// Revokes normal sessions and writes only an HttpOnly, SameSite=Strict,
|
|
751
|
+
// browser-session cookie. The database stores only its SHA-256 hash.
|
|
752
|
+
return credentialSetup.begin(user.id, options);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
return authService.establishSession(user);
|
|
756
|
+
|
|
757
|
+
// Complete an app-owned mutation in the same transaction as one-time
|
|
758
|
+
// consumption. If the callback fails, token consumption rolls back.
|
|
759
|
+
await credentialSetup.consume(options, async ({ userId }) => {
|
|
760
|
+
await replaceApplicationCredential(userId, newCredential);
|
|
761
|
+
});
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
Setup tokens are bound to a server-owned purpose, expire automatically, are
|
|
765
|
+
replaced when the same user starts that purpose again, and can be cancelled or
|
|
766
|
+
consumed exactly once. `require()` validates the current setup cookie without
|
|
767
|
+
consuming it; `cancel()` revokes it and clears the cookie.
|
|
768
|
+
|
|
769
|
+
### Session Management
|
|
731
770
|
|
|
732
771
|
- Sessions are multi-device: the token table stores one refresh row per login session (keyed by a unique `tokenFamily`), so a user can stay logged in on several devices at once. Logout and rotation are scoped to the current session; password change/reset revoke every session
|
|
733
772
|
- A stale refresh token presented after the 120-second rotation grace window revokes only that session's family as reuse protection
|
package/dist/index.d.ts
CHANGED
|
@@ -6,11 +6,12 @@ import { EmailPluginConfig, EmailService } from 'najm-email';
|
|
|
6
6
|
import { I18nService } from 'najm-i18n';
|
|
7
7
|
import { TDb, SeedEntry } from 'najm-database';
|
|
8
8
|
import { User, NewUser, RoleEntity, NewRoleEntity, Permission, NewPermission, RolePermission } from './schema/pg.js';
|
|
9
|
-
export { NewOAuthAccount, NewRolePermission, NewToken, OAuthAccount, Token, authSchema, baseFields, oauthAccountsTable, permissionsTable, rolePermissionsTable, rolesTable, tokenStatusEnum, tokenTypeEnum, tokensTable, userStatusEnum, usersTable } from './schema/pg.js';
|
|
9
|
+
export { CredentialSetupSession, NewCredentialSetupSession, NewOAuthAccount, NewRolePermission, NewToken, OAuthAccount, Token, authSchema, baseFields, credentialSetupSessionsTable, oauthAccountsTable, permissionsTable, rolePermissionsTable, rolesTable, tokenStatusEnum, tokenTypeEnum, tokensTable, userStatusEnum, usersTable } from './schema/pg.js';
|
|
10
10
|
import { CacheService } from 'najm-cache';
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import { Context } from 'hono';
|
|
13
13
|
import { GuardResult } from 'najm-guard';
|
|
14
|
+
import { CookieService } from 'najm-cookies';
|
|
14
15
|
import 'drizzle-orm';
|
|
15
16
|
import 'drizzle-orm/pg-core';
|
|
16
17
|
|
|
@@ -130,6 +131,8 @@ interface AuthConfig {
|
|
|
130
131
|
interface AuthSchema {
|
|
131
132
|
users: any;
|
|
132
133
|
tokens: any;
|
|
134
|
+
/** Durable one-time browser sessions used by CredentialSetupService. */
|
|
135
|
+
credentialSetupSessions?: any;
|
|
133
136
|
roles: any;
|
|
134
137
|
permissions: any;
|
|
135
138
|
rolePermissions: any;
|
|
@@ -545,7 +548,7 @@ declare class UserRepository {
|
|
|
545
548
|
private schema;
|
|
546
549
|
private get users();
|
|
547
550
|
private get roles();
|
|
548
|
-
/** Shared query helper */
|
|
551
|
+
/** Shared query helper, scoped to the current database/transaction identity. */
|
|
549
552
|
private queryHelper?;
|
|
550
553
|
private get q();
|
|
551
554
|
getAll(limit?: number, offset?: number): Promise<UserWithPermissions[]>;
|
|
@@ -847,7 +850,7 @@ declare class TokenRepository {
|
|
|
847
850
|
private schema;
|
|
848
851
|
private get tokens();
|
|
849
852
|
private get users();
|
|
850
|
-
/** Shared query helper */
|
|
853
|
+
/** Shared query helper, scoped to the current database/transaction identity. */
|
|
851
854
|
private queryHelper?;
|
|
852
855
|
private get q();
|
|
853
856
|
/**
|
|
@@ -1263,6 +1266,16 @@ declare class AuthService {
|
|
|
1263
1266
|
loginUser(body: LoginDto): Promise<TokenPair & {
|
|
1264
1267
|
user: SanitizedUser;
|
|
1265
1268
|
}>;
|
|
1269
|
+
/**
|
|
1270
|
+
* Verify credentials and account policy without minting access/refresh
|
|
1271
|
+
* tokens or writing normal auth cookies. Sensitive onboarding flows can use
|
|
1272
|
+
* this before issuing a purpose-bound CredentialSetupService session.
|
|
1273
|
+
*/
|
|
1274
|
+
verifyCredentials(body: LoginDto): Promise<SanitizedUser>;
|
|
1275
|
+
/** Establish a complete normal auth session for an already verified user. */
|
|
1276
|
+
establishSession(user: SanitizedUser): Promise<TokenPair & {
|
|
1277
|
+
user: SanitizedUser;
|
|
1278
|
+
}>;
|
|
1266
1279
|
refreshTokens(): Promise<TokenPair>;
|
|
1267
1280
|
/**
|
|
1268
1281
|
* Reissue the short-lived signed session snapshot from a fully validated
|
|
@@ -2195,6 +2208,74 @@ declare class UserController {
|
|
|
2195
2208
|
removeRole(params: UserIdInParam): Promise<SanitizedUser>;
|
|
2196
2209
|
}
|
|
2197
2210
|
|
|
2211
|
+
type NewSetupSession = {
|
|
2212
|
+
userId: string;
|
|
2213
|
+
purpose: string;
|
|
2214
|
+
tokenHash: string;
|
|
2215
|
+
expiresAt: string;
|
|
2216
|
+
};
|
|
2217
|
+
declare class CredentialSetupRepository {
|
|
2218
|
+
private db;
|
|
2219
|
+
private schema;
|
|
2220
|
+
private get sessions();
|
|
2221
|
+
replaceActive(data: NewSetupSession): Promise<any>;
|
|
2222
|
+
findActive(tokenHash: string, purpose: string): Promise<any>;
|
|
2223
|
+
consume(tokenHash: string, purpose: string): Promise<any>;
|
|
2224
|
+
revoke(tokenHash: string, purpose: string): Promise<any>;
|
|
2225
|
+
deleteExpired(): Promise<any>;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
interface CredentialSetupOptions {
|
|
2229
|
+
/** Stable server-owned purpose, for example `password-setup`. */
|
|
2230
|
+
purpose: string;
|
|
2231
|
+
/** HttpOnly browser-session cookie name (default: `najm.credential-setup`). */
|
|
2232
|
+
cookieName?: string;
|
|
2233
|
+
/** Session lifetime in milliseconds (default: 10 minutes, maximum: 24 hours). */
|
|
2234
|
+
ttlMs?: number;
|
|
2235
|
+
/** Cookie path (default: `/`). */
|
|
2236
|
+
cookiePath?: string;
|
|
2237
|
+
}
|
|
2238
|
+
interface CredentialSetupSessionInfo {
|
|
2239
|
+
userId: string;
|
|
2240
|
+
purpose: string;
|
|
2241
|
+
expiresAt: string;
|
|
2242
|
+
}
|
|
2243
|
+
interface CredentialSetupStarted {
|
|
2244
|
+
purpose: string;
|
|
2245
|
+
expiresAt: string;
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
declare class CredentialSetupService {
|
|
2249
|
+
private readonly repository;
|
|
2250
|
+
private readonly tokens;
|
|
2251
|
+
private readonly authCookies;
|
|
2252
|
+
private readonly cookies;
|
|
2253
|
+
constructor(repository: CredentialSetupRepository, tokens: TokenService, authCookies: CookieManager, cookies: CookieService);
|
|
2254
|
+
/**
|
|
2255
|
+
* Revoke normal auth sessions and issue a single-purpose, short-lived,
|
|
2256
|
+
* browser-session cookie. No access or refresh token is minted.
|
|
2257
|
+
*/
|
|
2258
|
+
begin(userId: string, options: CredentialSetupOptions): Promise<CredentialSetupStarted>;
|
|
2259
|
+
/** Validate and return the current active setup session without consuming it. */
|
|
2260
|
+
require(options: CredentialSetupOptions): Promise<CredentialSetupSessionInfo>;
|
|
2261
|
+
/**
|
|
2262
|
+
* Atomically consume the setup session and execute the application-owned
|
|
2263
|
+
* credential mutation in the same database transaction. If the callback
|
|
2264
|
+
* fails, consumption rolls back and the browser may safely retry.
|
|
2265
|
+
*/
|
|
2266
|
+
consume<T>(options: CredentialSetupOptions, complete: (session: CredentialSetupSessionInfo) => Promise<T> | T): Promise<T>;
|
|
2267
|
+
cancel(options: CredentialSetupOptions): Promise<{
|
|
2268
|
+
cancelled: true;
|
|
2269
|
+
}>;
|
|
2270
|
+
pruneExpired(): Promise<void>;
|
|
2271
|
+
private resolveOptions;
|
|
2272
|
+
private hashToken;
|
|
2273
|
+
private setCookie;
|
|
2274
|
+
private clearCookie;
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
declare const CREDENTIAL_SETUP_MODULE: readonly [typeof CredentialSetupRepository, typeof CredentialSetupService];
|
|
2278
|
+
|
|
2198
2279
|
declare const USER_STATUS: readonly ["active", "inactive", "pending"];
|
|
2199
2280
|
declare const TOKEN_STATUS: readonly ["active", "revoked", "expired"];
|
|
2200
2281
|
declare const TOKEN_TYPE: readonly ["access", "refresh"];
|
|
@@ -2336,4 +2417,4 @@ declare const authSeed: (config: AuthSeedConfig) => Record<string, SeedEntry>;
|
|
|
2336
2417
|
*/
|
|
2337
2418
|
declare function seedAuthData(config: SeedAuthDataConfig): Promise<SeedAuthDataResult>;
|
|
2338
2419
|
|
|
2339
|
-
export { AUTH_CONFIG, en as AUTH_EN, AUTH_LOCALES, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthPluginConfig, AuthQueries, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, AuthSessionService, type AuthUser, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type DefineRolesOptions, type EmailParam, EncryptionService, type GoogleOAuthConfig, type InviteUserDto, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, NewPermission, NewRoleEntity, NewUser, type OAuthConfig, type OAuthProvider, Owned, type OwnedMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, type ProvisionUserInput, ROLES, ROLE_GROUPS, type RefreshTokenDto, type RegisterDto, type ResetPasswordDto, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type RunAsUser, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, type SessionCookieData, TOKEN_STATUS, TOKEN_TYPE, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, type UserListQuery, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authIdentityRateLimitKey, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createPermissionDto, createRoleDto, createTokenDto, createUserDto, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, inviteUserDto, isAdmin, isAdministrator, isAuth, isEmailIdentifier, isEmpty, isFile, isPath, join, languageParam, loginDto, normalizeAuthIdentifier, own, parseSchema, permissionIdParam, pickProps, refreshTokenDto, registerDto, resetPasswordDto, revokeTokenDto, roleIdParam, runAsUser, seedAuthData, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, userListQuery, verifyTokenDto, where };
|
|
2420
|
+
export { AUTH_CONFIG, en as AUTH_EN, AUTH_LOCALES, AUTH_MODULE, AUTH_PERMISSIONS, AUTH_ROLE, AUTH_SCHEMA, AUTH_SUPPORTED_LANGUAGES, AUTH_USER, type AssignPermissionDto, type AssignRoleDto, type AssignRoleParams, type AuthConfig, AuthController, AuthGuard, type AuthPluginConfig, AuthQueries, AuthResolver, type AuthSchema, type AuthSeedConfig, AuthService, AuthSessionService, type AuthUser, CREDENTIAL_SETUP_MODULE, Can, CanCreate, CanDelete, CanList, CanRead, CanUpdate, type ChainableGuard, type ChangePasswordDto, type CheckPermissionDto, type ConfiguredOwnership, type ConfirmResetPasswordDto, CookieManager, type CreatePermissionDto, type CreateRoleDto, type CreateTokenDto, type CreateUserDto, type CredentialSetupOptions, CredentialSetupRepository, CredentialSetupService, type CredentialSetupSessionInfo, type CredentialSetupStarted, type DefineRolesOptions, type EmailParam, EncryptionService, type GoogleOAuthConfig, type InviteUserDto, type JwtConfig, type JwtPayload, type LanguageParam, type LoginDto, NewPermission, NewRoleEntity, NewUser, type OAuthConfig, type OAuthProvider, Owned, type OwnedMethods, type OwnershipConfig, type OwnershipProvider, type OwnershipRule, OwnershipToken, type OwnershipTokenOptions, Permission, PermissionController, PermissionGuard, type PermissionIdParam, PermissionRepository, PermissionService, PermissionValidator, Policy, type ProvisionUserInput, ROLES, ROLE_GROUPS, type RefreshTokenDto, type RegisterDto, type ResetPasswordDto, type ResourceAccessor, type ResourceGuards, type ResourceGuardsOptions, type RevokeTokenDto, Role, RoleController, RoleEntity, RoleGuard, type RoleIdParam, type RoleInput, RolePermission, RoleRepository, RoleService, type RoleType, RoleValidator, type RunAsUser, type SanitizedUser, ScopeContext, type ScopeResult, type SeedAuthDataConfig, type SeedAuthDataResult, type SeedUserConfig, type SessionCookieData, TOKEN_STATUS, TOKEN_TYPE, type TokenIdParam, type TokenPair, TokenRepository, TokenService, USER_STATUS, type UpdatePermissionDto, type UpdateRoleDto, type UpdateTokenDto, type UpdateUserDto, User, UserController, type UserIdInParam, type UserIdParam, type UserListQuery, UserRepository, UserService, UserValidator, type UserWithPermissions, type VerifyTokenDto, assignPermissionDto, assignRoleDto, assignRoleParams, auth$1 as auth, authIdentityRateLimitKey, authSeed, avatarsPath, calculateAge, calculateYearsOfExperience, changePasswordDto, checkPermissionDto, clean, configureOwnership, confirmResetPasswordDto, createPermissionDto, createRoleDto, createTokenDto, createUserDto, defineRoles, emailParam, formatDate, getAuthLocale, getAvatarFile, inviteUserDto, isAdmin, isAdministrator, isAuth, isEmailIdentifier, isEmpty, isFile, isPath, join, languageParam, loginDto, normalizeAuthIdentifier, own, parseSchema, permissionIdParam, pickProps, refreshTokenDto, registerDto, resetPasswordDto, revokeTokenDto, roleIdParam, runAsUser, seedAuthData, tokenIdParam, updatePermissionDto, updateRoleDto, updateTokenDto, updateUserDto, userIdInParam, userIdParam, userListQuery, verifyTokenDto, where };
|