@technomoron/api-server-base 1.1.13 → 2.0.0-beta.2

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.
Files changed (115) hide show
  1. package/dist/cjs/api-server-base.cjs +181 -74
  2. package/dist/cjs/api-server-base.d.ts +66 -29
  3. package/dist/cjs/auth-api/auth-module.d.ts +96 -0
  4. package/dist/cjs/auth-api/auth-module.js +1032 -0
  5. package/dist/cjs/auth-api/compat-auth-storage.d.ts +55 -0
  6. package/dist/cjs/auth-api/compat-auth-storage.js +116 -0
  7. package/dist/cjs/auth-api/mem-auth-store.d.ts +66 -0
  8. package/dist/cjs/auth-api/mem-auth-store.js +135 -0
  9. package/dist/cjs/{auth-module.d.ts → auth-api/module.d.ts} +7 -7
  10. package/dist/cjs/{auth-module.cjs → auth-api/module.js} +1 -1
  11. package/dist/cjs/auth-api/sql-auth-store.d.ts +75 -0
  12. package/dist/cjs/auth-api/sql-auth-store.js +166 -0
  13. package/dist/cjs/auth-api/storage.d.ts +36 -0
  14. package/dist/cjs/{auth-storage.cjs → auth-api/storage.js} +2 -2
  15. package/dist/cjs/auth-api/types.d.ts +29 -0
  16. package/dist/cjs/auth-api/types.js +2 -0
  17. package/dist/cjs/index.cjs +41 -7
  18. package/dist/cjs/index.d.ts +29 -5
  19. package/dist/cjs/oauth/base.d.ts +10 -0
  20. package/dist/cjs/oauth/base.js +6 -0
  21. package/dist/cjs/oauth/memory.d.ts +16 -0
  22. package/dist/cjs/oauth/memory.js +99 -0
  23. package/dist/cjs/oauth/models.d.ts +45 -0
  24. package/dist/cjs/oauth/models.js +58 -0
  25. package/dist/cjs/oauth/sequelize.d.ts +68 -0
  26. package/dist/cjs/oauth/sequelize.js +210 -0
  27. package/dist/cjs/oauth/types.d.ts +50 -0
  28. package/dist/cjs/oauth/types.js +3 -0
  29. package/dist/cjs/passkey/base.d.ts +15 -0
  30. package/dist/cjs/passkey/base.js +6 -0
  31. package/dist/cjs/passkey/memory.d.ts +26 -0
  32. package/dist/cjs/passkey/memory.js +82 -0
  33. package/dist/cjs/passkey/models.d.ts +25 -0
  34. package/dist/cjs/passkey/models.js +115 -0
  35. package/dist/cjs/passkey/sequelize.d.ts +54 -0
  36. package/dist/cjs/passkey/sequelize.js +211 -0
  37. package/dist/cjs/passkey/service.d.ts +17 -0
  38. package/dist/cjs/passkey/service.js +221 -0
  39. package/dist/cjs/passkey/types.d.ts +75 -0
  40. package/dist/cjs/passkey/types.js +2 -0
  41. package/dist/cjs/token/base.d.ts +38 -0
  42. package/dist/cjs/token/base.js +114 -0
  43. package/dist/cjs/token/memory.d.ts +19 -0
  44. package/dist/cjs/token/memory.js +149 -0
  45. package/dist/cjs/token/sequelize.d.ts +58 -0
  46. package/dist/cjs/token/sequelize.js +404 -0
  47. package/dist/cjs/token/types.d.ts +27 -0
  48. package/dist/cjs/token/types.js +2 -0
  49. package/dist/cjs/user/base.d.ts +26 -0
  50. package/dist/cjs/user/base.js +45 -0
  51. package/dist/cjs/user/memory.d.ts +35 -0
  52. package/dist/cjs/user/memory.js +173 -0
  53. package/dist/cjs/user/sequelize.d.ts +41 -0
  54. package/dist/cjs/user/sequelize.js +182 -0
  55. package/dist/cjs/user/types.d.ts +11 -0
  56. package/dist/cjs/user/types.js +2 -0
  57. package/dist/esm/api-server-base.d.ts +66 -29
  58. package/dist/esm/api-server-base.js +179 -72
  59. package/dist/esm/auth-api/auth-module.d.ts +96 -0
  60. package/dist/esm/auth-api/auth-module.js +1030 -0
  61. package/dist/esm/auth-api/compat-auth-storage.d.ts +55 -0
  62. package/dist/esm/auth-api/compat-auth-storage.js +112 -0
  63. package/dist/esm/auth-api/mem-auth-store.d.ts +66 -0
  64. package/dist/esm/auth-api/mem-auth-store.js +131 -0
  65. package/dist/esm/{auth-module.d.ts → auth-api/module.d.ts} +7 -7
  66. package/dist/esm/{auth-module.js → auth-api/module.js} +1 -1
  67. package/dist/esm/auth-api/sql-auth-store.d.ts +75 -0
  68. package/dist/esm/auth-api/sql-auth-store.js +162 -0
  69. package/dist/esm/auth-api/storage.d.ts +36 -0
  70. package/dist/esm/{auth-storage.js → auth-api/storage.js} +2 -2
  71. package/dist/esm/auth-api/types.d.ts +29 -0
  72. package/dist/esm/auth-api/types.js +1 -0
  73. package/dist/esm/index.d.ts +29 -5
  74. package/dist/esm/index.js +19 -2
  75. package/dist/esm/oauth/base.d.ts +10 -0
  76. package/dist/esm/oauth/base.js +2 -0
  77. package/dist/esm/oauth/memory.d.ts +16 -0
  78. package/dist/esm/oauth/memory.js +92 -0
  79. package/dist/esm/oauth/models.d.ts +45 -0
  80. package/dist/esm/oauth/models.js +51 -0
  81. package/dist/esm/oauth/sequelize.d.ts +68 -0
  82. package/dist/esm/oauth/sequelize.js +199 -0
  83. package/dist/esm/oauth/types.d.ts +50 -0
  84. package/dist/esm/oauth/types.js +2 -0
  85. package/dist/esm/passkey/base.d.ts +15 -0
  86. package/dist/esm/passkey/base.js +2 -0
  87. package/dist/esm/passkey/memory.d.ts +26 -0
  88. package/dist/esm/passkey/memory.js +78 -0
  89. package/dist/esm/passkey/models.d.ts +25 -0
  90. package/dist/esm/passkey/models.js +108 -0
  91. package/dist/esm/passkey/sequelize.d.ts +54 -0
  92. package/dist/esm/passkey/sequelize.js +207 -0
  93. package/dist/esm/passkey/service.d.ts +17 -0
  94. package/dist/esm/passkey/service.js +217 -0
  95. package/dist/esm/passkey/types.d.ts +75 -0
  96. package/dist/esm/passkey/types.js +1 -0
  97. package/dist/esm/token/base.d.ts +38 -0
  98. package/dist/esm/token/base.js +107 -0
  99. package/dist/esm/token/memory.d.ts +19 -0
  100. package/dist/esm/token/memory.js +145 -0
  101. package/dist/esm/token/sequelize.d.ts +58 -0
  102. package/dist/esm/token/sequelize.js +400 -0
  103. package/dist/esm/token/types.d.ts +27 -0
  104. package/dist/esm/token/types.js +1 -0
  105. package/dist/esm/user/base.d.ts +26 -0
  106. package/dist/esm/user/base.js +38 -0
  107. package/dist/esm/user/memory.d.ts +35 -0
  108. package/dist/esm/user/memory.js +169 -0
  109. package/dist/esm/user/sequelize.d.ts +41 -0
  110. package/dist/esm/user/sequelize.js +176 -0
  111. package/dist/esm/user/types.d.ts +11 -0
  112. package/dist/esm/user/types.js +1 -0
  113. package/package.json +11 -3
  114. package/dist/cjs/auth-storage.d.ts +0 -133
  115. package/dist/esm/auth-storage.d.ts +0 -133
@@ -0,0 +1,41 @@
1
+ import { CreationOptional, Model, type InferAttributes, type InferCreationAttributes, type ModelStatic, type Sequelize } from 'sequelize';
2
+ import { UserStore } from './base.js';
3
+ import type { CreateUserInput, PublicUserMapper, UpdateUserInput } from './types.js';
4
+ import type { AuthIdentifier } from '../auth-api/types.js';
5
+ export declare class AuthUserModel extends Model<InferAttributes<AuthUserModel>, InferCreationAttributes<AuthUserModel>> implements InferAttributes<AuthUserModel> {
6
+ user_id: CreationOptional<number>;
7
+ login: string;
8
+ email: string;
9
+ password: string;
10
+ }
11
+ export type AuthUserAttributes = InferAttributes<AuthUserModel>;
12
+ export type AuthUserCreationAttributes = InferCreationAttributes<AuthUserModel>;
13
+ export declare function initAuthUserModel(sequelize: Sequelize): typeof AuthUserModel;
14
+ export type GenericUserModel = Model<Record<string, unknown>, Record<string, unknown>>;
15
+ export type GenericUserModelStatic = ModelStatic<GenericUserModel>;
16
+ export interface SequelizeUserStoreOptions<UserAttributes extends AuthUserAttributes = AuthUserAttributes, PublicUserShape extends Omit<UserAttributes, 'password'> = Omit<UserAttributes, 'password'>> {
17
+ bcryptRounds?: number;
18
+ bcryptPepper?: string;
19
+ sequelize: Sequelize;
20
+ userModel?: GenericUserModelStatic;
21
+ userModelFactory?: (sequelize: Sequelize) => GenericUserModelStatic;
22
+ recordMapper?: (model: GenericUserModel) => UserAttributes;
23
+ toPublic?: PublicUserMapper<UserAttributes, PublicUserShape>;
24
+ }
25
+ export declare class SequelizeUserStore<UserAttributes extends AuthUserAttributes = AuthUserAttributes, PublicUserShape extends Omit<UserAttributes, 'password'> = Omit<UserAttributes, 'password'>> extends UserStore<UserAttributes, PublicUserShape> {
26
+ readonly Users: GenericUserModelStatic;
27
+ private readonly recordMapper;
28
+ constructor(options: SequelizeUserStoreOptions<UserAttributes, PublicUserShape>);
29
+ findUser(identifier: AuthIdentifier | string): Promise<UserAttributes | null>;
30
+ findById(id: AuthIdentifier): Promise<UserAttributes | null>;
31
+ findByLoginOrEmail(loginOrEmail: string): Promise<UserAttributes | null>;
32
+ createUser(input: CreateUserInput): Promise<UserAttributes>;
33
+ upsertUser(input: CreateUserInput): Promise<UserAttributes>;
34
+ updateUser(id: AuthIdentifier, patch: UpdateUserInput): Promise<UserAttributes>;
35
+ setPasswordHash(id: AuthIdentifier, hash: string): Promise<void>;
36
+ getPasswordHash(user: UserAttributes): string | null;
37
+ getUserId(user: UserAttributes): AuthIdentifier;
38
+ protected toUserRecord(model: GenericUserModel): UserAttributes;
39
+ private static mapModelToUser;
40
+ private normalizeUserId;
41
+ }
@@ -0,0 +1,176 @@
1
+ import { DataTypes, Model, Op } from 'sequelize';
2
+ import { UserStore } from './base.js';
3
+ const DIALECTS_SUPPORTING_UNSIGNED = new Set(['mysql', 'mariadb']);
4
+ function integerIdType(sequelize) {
5
+ return DIALECTS_SUPPORTING_UNSIGNED.has(sequelize.getDialect()) ? DataTypes.INTEGER.UNSIGNED : DataTypes.INTEGER;
6
+ }
7
+ function userTableOptions(sequelize) {
8
+ const opts = {
9
+ sequelize,
10
+ tableName: 'users',
11
+ timestamps: false
12
+ };
13
+ if (DIALECTS_SUPPORTING_UNSIGNED.has(sequelize.getDialect())) {
14
+ opts.charset = 'utf8mb4';
15
+ opts.collate = 'utf8mb4_unicode_ci';
16
+ }
17
+ return opts;
18
+ }
19
+ export class AuthUserModel extends Model {
20
+ }
21
+ export function initAuthUserModel(sequelize) {
22
+ const idType = integerIdType(sequelize);
23
+ AuthUserModel.init({
24
+ user_id: {
25
+ type: idType,
26
+ autoIncrement: true,
27
+ allowNull: false,
28
+ primaryKey: true
29
+ },
30
+ login: {
31
+ type: DataTypes.STRING(64),
32
+ allowNull: false,
33
+ unique: true
34
+ },
35
+ email: {
36
+ type: DataTypes.STRING(100),
37
+ allowNull: false,
38
+ unique: true
39
+ },
40
+ password: {
41
+ type: DataTypes.STRING(255),
42
+ allowNull: false
43
+ }
44
+ }, {
45
+ ...userTableOptions(sequelize)
46
+ });
47
+ return AuthUserModel;
48
+ }
49
+ export class SequelizeUserStore extends UserStore {
50
+ constructor(options) {
51
+ super({
52
+ toPublic: options.toPublic,
53
+ bcryptRounds: options.bcryptRounds,
54
+ bcryptPepper: options.bcryptPepper
55
+ });
56
+ if (!options?.sequelize) {
57
+ throw new Error('SequelizeUserStore requires a configured Sequelize instance');
58
+ }
59
+ this.Users = options.userModel
60
+ ? options.userModel
61
+ : (options.userModelFactory ?? initAuthUserModel)(options.sequelize);
62
+ this.recordMapper =
63
+ options.recordMapper ??
64
+ ((model) => SequelizeUserStore.mapModelToUser(model));
65
+ }
66
+ async findUser(identifier) {
67
+ const where = [];
68
+ try {
69
+ where.push({ user_id: this.normalizeUserId(identifier) });
70
+ }
71
+ catch {
72
+ // ignore
73
+ }
74
+ if (typeof identifier === 'string') {
75
+ where.push({ login: identifier });
76
+ where.push({ email: identifier });
77
+ }
78
+ if (where.length === 0) {
79
+ return null;
80
+ }
81
+ const model = await this.Users.findOne({ where: { [Op.or]: where } });
82
+ return model ? this.toUserRecord(model) : null;
83
+ }
84
+ async findById(id) {
85
+ try {
86
+ const model = await this.Users.findByPk(this.normalizeUserId(id));
87
+ return model ? this.toUserRecord(model) : null;
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ async findByLoginOrEmail(loginOrEmail) {
94
+ const model = await this.Users.findOne({
95
+ where: { [Op.or]: [{ login: loginOrEmail }, { email: loginOrEmail }] }
96
+ });
97
+ return model ? this.toUserRecord(model) : null;
98
+ }
99
+ async createUser(input) {
100
+ const normalized = this.normalizeUserInput(input);
101
+ const { password, ...rest } = normalized;
102
+ const defaults = {
103
+ ...rest,
104
+ password: password ? await this.hashPassword(password) : ''
105
+ };
106
+ const providedId = input.user_id;
107
+ if (providedId !== undefined && providedId !== null && Number.isFinite(providedId)) {
108
+ defaults.user_id = Number(providedId);
109
+ }
110
+ const [model] = await this.Users.findOrCreate({
111
+ where: { login: rest.login },
112
+ defaults: defaults
113
+ });
114
+ return this.toUserRecord(model);
115
+ }
116
+ async upsertUser(input) {
117
+ const normalized = this.normalizeUserInput(input);
118
+ const providedId = input.user_id;
119
+ if (providedId !== undefined) {
120
+ const model = await this.Users.findByPk(Number(providedId));
121
+ if (!model) {
122
+ throw new Error(`User ${String(providedId)} not found`);
123
+ }
124
+ const next = { ...normalized };
125
+ if (normalized.password) {
126
+ next.password = await this.hashPassword(normalized.password);
127
+ }
128
+ await model.set(next);
129
+ await model.save();
130
+ return this.toUserRecord(model);
131
+ }
132
+ return this.createUser(input);
133
+ }
134
+ async updateUser(id, patch) {
135
+ const model = await this.Users.findByPk(this.normalizeUserId(id));
136
+ if (!model) {
137
+ throw new Error(`User ${String(id)} not found`);
138
+ }
139
+ const updates = { ...patch };
140
+ if (patch.password) {
141
+ updates.password = await this.hashPassword(patch.password);
142
+ }
143
+ await model.set(updates);
144
+ await model.save();
145
+ return this.toUserRecord(model);
146
+ }
147
+ async setPasswordHash(id, hash) {
148
+ await this.Users.update({ password: hash }, { where: { user_id: this.normalizeUserId(id) } });
149
+ }
150
+ getPasswordHash(user) {
151
+ return user.password;
152
+ }
153
+ getUserId(user) {
154
+ return user.user_id;
155
+ }
156
+ toUserRecord(model) {
157
+ return this.recordMapper(model);
158
+ }
159
+ static mapModelToUser(model) {
160
+ return {
161
+ user_id: model.get('user_id'),
162
+ login: model.get('login'),
163
+ email: model.get('email'),
164
+ password: model.get('password')
165
+ };
166
+ }
167
+ normalizeUserId(identifier) {
168
+ if (typeof identifier === 'number' && Number.isFinite(identifier)) {
169
+ return identifier;
170
+ }
171
+ if (typeof identifier === 'string' && /^\d+$/.test(identifier)) {
172
+ return Number(identifier);
173
+ }
174
+ throw new Error(`Unable to normalise user identifier: ${identifier}`);
175
+ }
176
+ }
@@ -0,0 +1,11 @@
1
+ export interface BcryptHasherOptions {
2
+ rounds?: number;
3
+ pepper?: string;
4
+ }
5
+ export type CreateUserInput = Record<string, unknown> & {
6
+ login: string;
7
+ email: string;
8
+ password?: string;
9
+ };
10
+ export type UpdateUserInput = Partial<CreateUserInput>;
11
+ export type PublicUserMapper<User, PublicUser> = (user: User) => PublicUser;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/api-server-base",
3
- "version": "1.1.13",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "Api Server Skeleton / Base Class",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.cjs",
@@ -39,18 +39,25 @@
39
39
  "pretty": "prettier --write \"**/*.{js,jsx,ts,tsx,vue,json,css,scss,md}\""
40
40
  },
41
41
  "dependencies": {
42
+ "@simplewebauthn/server": "^13.2.2",
42
43
  "@types/cookie-parser": "^1.4.9",
43
44
  "@types/cors": "^2.8.19",
44
45
  "@types/express": "^4.17.23",
45
46
  "@types/jsonwebtoken": "^9.0.10",
46
47
  "@types/multer": "^1.4.13",
48
+ "bcryptjs": "^2.4.3",
47
49
  "cookie-parser": "^1.4.7",
48
50
  "cors": "^2.8.5",
49
51
  "express": "^4.21.2",
50
52
  "jsonwebtoken": "^9.0.2",
51
- "multer": "^2.0.2"
53
+ "multer": "^2.0.2",
54
+ "mysql2": "^3.15.3",
55
+ "pg": "^8.16.3",
56
+ "sequelize": "^6.37.7",
57
+ "sqlite3": "^5.1.7"
52
58
  },
53
59
  "devDependencies": {
60
+ "@types/bcryptjs": "^2.4.6",
54
61
  "@types/express-serve-static-core": "^5.1.0",
55
62
  "@types/supertest": "^6.0.3",
56
63
  "@typescript-eslint/eslint-plugin": "^8.46.1",
@@ -67,7 +74,8 @@
67
74
  },
68
75
  "pnpm": {
69
76
  "onlyBuiltDependencies": [
70
- "esbuild"
77
+ "esbuild",
78
+ "sqlite3"
71
79
  ]
72
80
  },
73
81
  "files": [
@@ -1,133 +0,0 @@
1
- export type AuthIdentifier = string | number;
2
- export interface AuthTokenMetadata {
3
- ruid?: AuthIdentifier;
4
- clientId?: string;
5
- domain?: string;
6
- fingerprint?: string;
7
- label?: string;
8
- browser?: string;
9
- device?: string;
10
- ip?: string;
11
- os?: string;
12
- scope?: string | string[];
13
- loginType?: string;
14
- refreshTtlSeconds?: number;
15
- sessionCookie?: boolean;
16
- revokeSessions?: 'device' | 'domain' | 'client' | 'user';
17
- }
18
- export interface AuthTokenData extends AuthTokenMetadata {
19
- access: string;
20
- expires?: Date;
21
- issuedAt?: Date;
22
- lastSeenAt?: Date;
23
- refresh: string;
24
- userId: AuthIdentifier;
25
- }
26
- export interface AuthTokenQuery extends AuthTokenMetadata {
27
- accessToken?: string;
28
- refreshToken?: string;
29
- userId?: AuthIdentifier;
30
- }
31
- export interface AuthTokenPair {
32
- accessToken: string;
33
- refreshToken: string;
34
- }
35
- export interface AuthTokenPayload extends AuthTokenMetadata {
36
- exp?: number;
37
- iat?: number;
38
- uid: AuthIdentifier;
39
- }
40
- export interface PasskeyChallengeParams extends AuthTokenMetadata {
41
- action: 'register' | 'authenticate';
42
- login?: string;
43
- userAgent?: string;
44
- userId?: AuthIdentifier;
45
- }
46
- export interface PasskeyChallenge extends Record<string, unknown> {
47
- challenge: string;
48
- expiresAt?: string | number | Date;
49
- userId?: AuthIdentifier;
50
- }
51
- export interface PasskeyVerificationParams extends AuthTokenMetadata {
52
- expectedChallenge: string;
53
- login?: string;
54
- response: Record<string, unknown>;
55
- userId?: AuthIdentifier;
56
- }
57
- export interface PasskeyVerificationResult extends Record<string, unknown> {
58
- login?: string;
59
- tokens?: AuthTokenPair;
60
- userId?: AuthIdentifier;
61
- verified: boolean;
62
- }
63
- export interface OAuthClient {
64
- clientId: string;
65
- clientSecret: string;
66
- firstParty?: boolean;
67
- metadata?: Record<string, unknown>;
68
- name?: string;
69
- redirectUris: string[];
70
- scope?: string[];
71
- }
72
- export interface AuthCodeData {
73
- code: string;
74
- clientId: string;
75
- codeChallenge?: string;
76
- codeChallengeMethod?: 'plain' | 'S256';
77
- expiresAt: Date;
78
- metadata?: Record<string, unknown>;
79
- redirectUri: string;
80
- scope: string[];
81
- userId: AuthIdentifier;
82
- }
83
- export type AuthCodeRequest = Omit<AuthCodeData, 'code' | 'expiresAt'> & {
84
- code?: string;
85
- expiresInSeconds?: number;
86
- };
87
- export interface AuthStorage<UserRow, SafeUser> {
88
- getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
89
- getUserPasswordHash(user: UserRow): string;
90
- getUserId(user: UserRow): AuthIdentifier;
91
- filterUser(user: UserRow): SafeUser;
92
- verifyPassword(password: string, hash: string): Promise<boolean>;
93
- storeToken(data: AuthTokenData): Promise<void>;
94
- getToken(query: AuthTokenQuery): Promise<AuthTokenData | null>;
95
- deleteToken(query: AuthTokenQuery): Promise<number>;
96
- updateToken?(updates: Partial<AuthTokenData> & {
97
- refreshToken: string;
98
- }): Promise<boolean>;
99
- createPasskeyChallenge?(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
100
- verifyPasskeyResponse?(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
101
- getClient?(clientId: string): Promise<OAuthClient | null>;
102
- verifyClientSecret?(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
103
- createAuthCode?(request: AuthCodeRequest): Promise<AuthCodeData>;
104
- consumeAuthCode?(code: string, clientId: string): Promise<AuthCodeData | null>;
105
- canImpersonate?(params: {
106
- realUserId: AuthIdentifier;
107
- effectiveUserId: AuthIdentifier;
108
- }): Promise<boolean>;
109
- }
110
- export declare class BaseAuthStorage<UserRow = unknown, SafeUser = unknown> implements AuthStorage<UserRow, SafeUser> {
111
- getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
112
- getUserPasswordHash(user: UserRow): string;
113
- getUserId(user: UserRow): AuthIdentifier;
114
- filterUser(user: UserRow): SafeUser;
115
- verifyPassword(password: string, hash: string): Promise<boolean>;
116
- storeToken(data: AuthTokenData): Promise<void>;
117
- getToken(query: AuthTokenQuery): Promise<AuthTokenData | null>;
118
- deleteToken(query: AuthTokenQuery): Promise<number>;
119
- updateToken(updates: Partial<AuthTokenData> & {
120
- refreshToken: string;
121
- }): Promise<boolean>;
122
- createPasskeyChallenge(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
123
- verifyPasskeyResponse(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
124
- getClient(clientId: string): Promise<OAuthClient | null>;
125
- verifyClientSecret(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
126
- createAuthCode(request: AuthCodeRequest): Promise<AuthCodeData>;
127
- consumeAuthCode(code: string, clientId: string): Promise<AuthCodeData | null>;
128
- canImpersonate(params: {
129
- realUserId: AuthIdentifier;
130
- effectiveUserId: AuthIdentifier;
131
- }): Promise<boolean>;
132
- }
133
- export declare const nullAuthStorage: AuthStorage<unknown, unknown>;
@@ -1,133 +0,0 @@
1
- export type AuthIdentifier = string | number;
2
- export interface AuthTokenMetadata {
3
- ruid?: AuthIdentifier;
4
- clientId?: string;
5
- domain?: string;
6
- fingerprint?: string;
7
- label?: string;
8
- browser?: string;
9
- device?: string;
10
- ip?: string;
11
- os?: string;
12
- scope?: string | string[];
13
- loginType?: string;
14
- refreshTtlSeconds?: number;
15
- sessionCookie?: boolean;
16
- revokeSessions?: 'device' | 'domain' | 'client' | 'user';
17
- }
18
- export interface AuthTokenData extends AuthTokenMetadata {
19
- access: string;
20
- expires?: Date;
21
- issuedAt?: Date;
22
- lastSeenAt?: Date;
23
- refresh: string;
24
- userId: AuthIdentifier;
25
- }
26
- export interface AuthTokenQuery extends AuthTokenMetadata {
27
- accessToken?: string;
28
- refreshToken?: string;
29
- userId?: AuthIdentifier;
30
- }
31
- export interface AuthTokenPair {
32
- accessToken: string;
33
- refreshToken: string;
34
- }
35
- export interface AuthTokenPayload extends AuthTokenMetadata {
36
- exp?: number;
37
- iat?: number;
38
- uid: AuthIdentifier;
39
- }
40
- export interface PasskeyChallengeParams extends AuthTokenMetadata {
41
- action: 'register' | 'authenticate';
42
- login?: string;
43
- userAgent?: string;
44
- userId?: AuthIdentifier;
45
- }
46
- export interface PasskeyChallenge extends Record<string, unknown> {
47
- challenge: string;
48
- expiresAt?: string | number | Date;
49
- userId?: AuthIdentifier;
50
- }
51
- export interface PasskeyVerificationParams extends AuthTokenMetadata {
52
- expectedChallenge: string;
53
- login?: string;
54
- response: Record<string, unknown>;
55
- userId?: AuthIdentifier;
56
- }
57
- export interface PasskeyVerificationResult extends Record<string, unknown> {
58
- login?: string;
59
- tokens?: AuthTokenPair;
60
- userId?: AuthIdentifier;
61
- verified: boolean;
62
- }
63
- export interface OAuthClient {
64
- clientId: string;
65
- clientSecret: string;
66
- firstParty?: boolean;
67
- metadata?: Record<string, unknown>;
68
- name?: string;
69
- redirectUris: string[];
70
- scope?: string[];
71
- }
72
- export interface AuthCodeData {
73
- code: string;
74
- clientId: string;
75
- codeChallenge?: string;
76
- codeChallengeMethod?: 'plain' | 'S256';
77
- expiresAt: Date;
78
- metadata?: Record<string, unknown>;
79
- redirectUri: string;
80
- scope: string[];
81
- userId: AuthIdentifier;
82
- }
83
- export type AuthCodeRequest = Omit<AuthCodeData, 'code' | 'expiresAt'> & {
84
- code?: string;
85
- expiresInSeconds?: number;
86
- };
87
- export interface AuthStorage<UserRow, SafeUser> {
88
- getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
89
- getUserPasswordHash(user: UserRow): string;
90
- getUserId(user: UserRow): AuthIdentifier;
91
- filterUser(user: UserRow): SafeUser;
92
- verifyPassword(password: string, hash: string): Promise<boolean>;
93
- storeToken(data: AuthTokenData): Promise<void>;
94
- getToken(query: AuthTokenQuery): Promise<AuthTokenData | null>;
95
- deleteToken(query: AuthTokenQuery): Promise<number>;
96
- updateToken?(updates: Partial<AuthTokenData> & {
97
- refreshToken: string;
98
- }): Promise<boolean>;
99
- createPasskeyChallenge?(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
100
- verifyPasskeyResponse?(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
101
- getClient?(clientId: string): Promise<OAuthClient | null>;
102
- verifyClientSecret?(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
103
- createAuthCode?(request: AuthCodeRequest): Promise<AuthCodeData>;
104
- consumeAuthCode?(code: string, clientId: string): Promise<AuthCodeData | null>;
105
- canImpersonate?(params: {
106
- realUserId: AuthIdentifier;
107
- effectiveUserId: AuthIdentifier;
108
- }): Promise<boolean>;
109
- }
110
- export declare class BaseAuthStorage<UserRow = unknown, SafeUser = unknown> implements AuthStorage<UserRow, SafeUser> {
111
- getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
112
- getUserPasswordHash(user: UserRow): string;
113
- getUserId(user: UserRow): AuthIdentifier;
114
- filterUser(user: UserRow): SafeUser;
115
- verifyPassword(password: string, hash: string): Promise<boolean>;
116
- storeToken(data: AuthTokenData): Promise<void>;
117
- getToken(query: AuthTokenQuery): Promise<AuthTokenData | null>;
118
- deleteToken(query: AuthTokenQuery): Promise<number>;
119
- updateToken(updates: Partial<AuthTokenData> & {
120
- refreshToken: string;
121
- }): Promise<boolean>;
122
- createPasskeyChallenge(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
123
- verifyPasskeyResponse(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
124
- getClient(clientId: string): Promise<OAuthClient | null>;
125
- verifyClientSecret(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
126
- createAuthCode(request: AuthCodeRequest): Promise<AuthCodeData>;
127
- consumeAuthCode(code: string, clientId: string): Promise<AuthCodeData | null>;
128
- canImpersonate(params: {
129
- realUserId: AuthIdentifier;
130
- effectiveUserId: AuthIdentifier;
131
- }): Promise<boolean>;
132
- }
133
- export declare const nullAuthStorage: AuthStorage<unknown, unknown>;