@technomoron/apicore-server 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cjs/api-module.cjs +34 -0
- package/dist/cjs/api-module.d.ts +45 -0
- package/dist/cjs/apicore-server.cjs +1561 -0
- package/dist/cjs/apicore-server.d.ts +288 -0
- package/dist/cjs/auth-api/auth-module.cjs +1248 -0
- package/dist/cjs/auth-api/auth-module.d.ts +116 -0
- package/dist/cjs/auth-api/compat-auth-storage.cjs +128 -0
- package/dist/cjs/auth-api/compat-auth-storage.d.ts +57 -0
- package/dist/cjs/auth-api/mem-auth-store.cjs +121 -0
- package/dist/cjs/auth-api/mem-auth-store.d.ts +68 -0
- package/dist/cjs/auth-api/module.cjs +25 -0
- package/dist/cjs/auth-api/module.d.ts +20 -0
- package/dist/cjs/auth-api/schemas.cjs +171 -0
- package/dist/cjs/auth-api/schemas.d.ts +21 -0
- package/dist/cjs/auth-api/sql-auth-store.cjs +179 -0
- package/dist/cjs/auth-api/sql-auth-store.d.ts +87 -0
- package/dist/cjs/auth-api/storage.cjs +102 -0
- package/dist/cjs/auth-api/storage.d.ts +38 -0
- package/dist/cjs/auth-api/types.cjs +2 -0
- package/dist/cjs/auth-api/types.d.ts +34 -0
- package/dist/cjs/auth-api/user-id.cjs +47 -0
- package/dist/cjs/auth-api/user-id.d.ts +5 -0
- package/dist/cjs/auth-cookie-options.cjs +66 -0
- package/dist/cjs/auth-cookie-options.d.ts +13 -0
- package/dist/cjs/base/client-info.cjs +285 -0
- package/dist/cjs/base/client-info.d.ts +27 -0
- package/dist/cjs/base/error-utils.cjs +50 -0
- package/dist/cjs/base/error-utils.d.ts +16 -0
- package/dist/cjs/base/request-utils.cjs +27 -0
- package/dist/cjs/base/request-utils.d.ts +8 -0
- package/dist/cjs/index.cjs +51 -0
- package/dist/cjs/index.d.ts +34 -0
- package/dist/cjs/limiter/auth-rate-limiter.cjs +35 -0
- package/dist/cjs/limiter/auth-rate-limiter.d.ts +12 -0
- package/dist/cjs/limiter/fixed-window.cjs +41 -0
- package/dist/cjs/limiter/fixed-window.d.ts +11 -0
- package/dist/cjs/oauth/base.cjs +7 -0
- package/dist/cjs/oauth/base.d.ts +17 -0
- package/dist/cjs/oauth/memory.cjs +135 -0
- package/dist/cjs/oauth/memory.d.ts +22 -0
- package/dist/cjs/oauth/models.cjs +47 -0
- package/dist/cjs/oauth/models.d.ts +50 -0
- package/dist/cjs/oauth/sequelize.cjs +159 -0
- package/dist/cjs/oauth/sequelize.d.ts +30 -0
- package/dist/cjs/oauth/types.cjs +3 -0
- package/dist/cjs/oauth/types.d.ts +51 -0
- package/dist/cjs/passkey/base.cjs +7 -0
- package/dist/cjs/passkey/base.d.ts +28 -0
- package/dist/cjs/passkey/config.cjs +26 -0
- package/dist/cjs/passkey/config.d.ts +2 -0
- package/dist/cjs/passkey/memory.cjs +123 -0
- package/dist/cjs/passkey/memory.d.ts +34 -0
- package/dist/cjs/passkey/models.cjs +142 -0
- package/dist/cjs/passkey/models.d.ts +34 -0
- package/dist/cjs/passkey/sequelize.cjs +126 -0
- package/dist/cjs/passkey/sequelize.d.ts +42 -0
- package/dist/cjs/passkey/service.cjs +413 -0
- package/dist/cjs/passkey/service.d.ts +21 -0
- package/dist/cjs/passkey/types.cjs +2 -0
- package/dist/cjs/passkey/types.d.ts +84 -0
- package/dist/cjs/sequelize-utils.cjs +56 -0
- package/dist/cjs/sequelize-utils.d.ts +8 -0
- package/dist/cjs/token/base.cjs +120 -0
- package/dist/cjs/token/base.d.ts +46 -0
- package/dist/cjs/token/memory.cjs +234 -0
- package/dist/cjs/token/memory.d.ts +29 -0
- package/dist/cjs/token/sequelize.cjs +400 -0
- package/dist/cjs/token/sequelize.d.ts +58 -0
- package/dist/cjs/token/types.cjs +2 -0
- package/dist/cjs/token/types.d.ts +34 -0
- package/dist/cjs/upload/memory.cjs +92 -0
- package/dist/cjs/upload/memory.d.ts +17 -0
- package/dist/cjs/upload/tus-module.cjs +270 -0
- package/dist/cjs/upload/tus-module.d.ts +38 -0
- package/dist/cjs/upload/types.cjs +2 -0
- package/dist/cjs/upload/types.d.ts +28 -0
- package/dist/cjs/user/base.cjs +53 -0
- package/dist/cjs/user/base.d.ts +36 -0
- package/dist/cjs/user/memory.cjs +194 -0
- package/dist/cjs/user/memory.d.ts +37 -0
- package/dist/cjs/user/sequelize.cjs +194 -0
- package/dist/cjs/user/sequelize.d.ts +46 -0
- package/dist/cjs/user/types.cjs +2 -0
- package/dist/cjs/user/types.d.ts +11 -0
- package/dist/esm/api-module.d.ts +45 -0
- package/dist/esm/api-module.js +30 -0
- package/dist/esm/apicore-server.d.ts +288 -0
- package/dist/esm/apicore-server.js +1552 -0
- package/dist/esm/auth-api/auth-module.d.ts +116 -0
- package/dist/esm/auth-api/auth-module.js +1246 -0
- package/dist/esm/auth-api/compat-auth-storage.d.ts +57 -0
- package/dist/esm/auth-api/compat-auth-storage.js +124 -0
- package/dist/esm/auth-api/mem-auth-store.d.ts +68 -0
- package/dist/esm/auth-api/mem-auth-store.js +117 -0
- package/dist/esm/auth-api/module.d.ts +20 -0
- package/dist/esm/auth-api/module.js +21 -0
- package/dist/esm/auth-api/schemas.d.ts +21 -0
- package/dist/esm/auth-api/schemas.js +168 -0
- package/dist/esm/auth-api/sql-auth-store.d.ts +87 -0
- package/dist/esm/auth-api/sql-auth-store.js +175 -0
- package/dist/esm/auth-api/storage.d.ts +38 -0
- package/dist/esm/auth-api/storage.js +98 -0
- package/dist/esm/auth-api/types.d.ts +34 -0
- package/dist/esm/auth-api/types.js +1 -0
- package/dist/esm/auth-api/user-id.d.ts +5 -0
- package/dist/esm/auth-api/user-id.js +41 -0
- package/dist/esm/auth-cookie-options.d.ts +13 -0
- package/dist/esm/auth-cookie-options.js +63 -0
- package/dist/esm/base/client-info.d.ts +27 -0
- package/dist/esm/base/client-info.js +282 -0
- package/dist/esm/base/error-utils.d.ts +16 -0
- package/dist/esm/base/error-utils.js +44 -0
- package/dist/esm/base/request-utils.d.ts +8 -0
- package/dist/esm/base/request-utils.js +23 -0
- package/dist/esm/index.d.ts +34 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/limiter/auth-rate-limiter.d.ts +12 -0
- package/dist/esm/limiter/auth-rate-limiter.js +32 -0
- package/dist/esm/limiter/fixed-window.d.ts +11 -0
- package/dist/esm/limiter/fixed-window.js +37 -0
- package/dist/esm/oauth/base.d.ts +17 -0
- package/dist/esm/oauth/base.js +3 -0
- package/dist/esm/oauth/memory.d.ts +22 -0
- package/dist/esm/oauth/memory.js +128 -0
- package/dist/esm/oauth/models.d.ts +50 -0
- package/dist/esm/oauth/models.js +38 -0
- package/dist/esm/oauth/sequelize.d.ts +30 -0
- package/dist/esm/oauth/sequelize.js +148 -0
- package/dist/esm/oauth/types.d.ts +51 -0
- package/dist/esm/oauth/types.js +2 -0
- package/dist/esm/passkey/base.d.ts +28 -0
- package/dist/esm/passkey/base.js +3 -0
- package/dist/esm/passkey/config.d.ts +2 -0
- package/dist/esm/passkey/config.js +23 -0
- package/dist/esm/passkey/memory.d.ts +34 -0
- package/dist/esm/passkey/memory.js +119 -0
- package/dist/esm/passkey/models.d.ts +34 -0
- package/dist/esm/passkey/models.js +135 -0
- package/dist/esm/passkey/sequelize.d.ts +42 -0
- package/dist/esm/passkey/sequelize.js +122 -0
- package/dist/esm/passkey/service.d.ts +21 -0
- package/dist/esm/passkey/service.js +376 -0
- package/dist/esm/passkey/types.d.ts +84 -0
- package/dist/esm/passkey/types.js +1 -0
- package/dist/esm/sequelize-utils.d.ts +8 -0
- package/dist/esm/sequelize-utils.js +47 -0
- package/dist/esm/token/base.d.ts +46 -0
- package/dist/esm/token/base.js +113 -0
- package/dist/esm/token/memory.d.ts +29 -0
- package/dist/esm/token/memory.js +230 -0
- package/dist/esm/token/sequelize.d.ts +58 -0
- package/dist/esm/token/sequelize.js +396 -0
- package/dist/esm/token/types.d.ts +34 -0
- package/dist/esm/token/types.js +1 -0
- package/dist/esm/upload/memory.d.ts +17 -0
- package/dist/esm/upload/memory.js +86 -0
- package/dist/esm/upload/tus-module.d.ts +38 -0
- package/dist/esm/upload/tus-module.js +266 -0
- package/dist/esm/upload/types.d.ts +28 -0
- package/dist/esm/upload/types.js +1 -0
- package/dist/esm/user/base.d.ts +36 -0
- package/dist/esm/user/base.js +46 -0
- package/dist/esm/user/memory.d.ts +37 -0
- package/dist/esm/user/memory.js +190 -0
- package/dist/esm/user/sequelize.d.ts +46 -0
- package/dist/esm/user/sequelize.js +188 -0
- package/dist/esm/user/types.d.ts +11 -0
- package/dist/esm/user/types.js +1 -0
- package/docs/swagger/openapi.json +2162 -0
- package/package.json +131 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* JSON Schema definitions for auth module routes.
|
|
4
|
+
* These are the runtime validation source-of-truth; TypeScript interfaces
|
|
5
|
+
* in auth-module.ts remain for handler-internal typing only.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.oauthTokenBodySchema = exports.oauthAuthorizeBodySchema = exports.oauthStartBodySchema = exports.oauthProviderParamsSchema = exports.deleteImpersonationQuerySchema = exports.impersonateBodySchema = exports.passkeyCredentialParamsSchema = exports.passkeyVerifyBodySchema = exports.passkeyChallengeBodySchema = exports.whoamiBodySchema = exports.logoutBodySchema = exports.refreshBodySchema = exports.loginBodySchema = void 0;
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/* Shared fragments */
|
|
11
|
+
/* ------------------------------------------------------------------ */
|
|
12
|
+
const tokenMetadataProperties = {
|
|
13
|
+
domain: { type: 'string' },
|
|
14
|
+
fingerprint: { type: 'string' },
|
|
15
|
+
label: { type: 'string' },
|
|
16
|
+
browser: { type: 'string' },
|
|
17
|
+
device: { type: 'string' },
|
|
18
|
+
ip: { type: 'string' },
|
|
19
|
+
os: { type: 'string' }
|
|
20
|
+
};
|
|
21
|
+
const keepSessionProperty = {
|
|
22
|
+
keepSession: { type: ['boolean', 'number', 'string'] }
|
|
23
|
+
};
|
|
24
|
+
function authIdentifierProperty(name) {
|
|
25
|
+
return { [name]: { type: ['string', 'number'] } };
|
|
26
|
+
}
|
|
27
|
+
/* ------------------------------------------------------------------ */
|
|
28
|
+
/* Auth route schemas */
|
|
29
|
+
/* ------------------------------------------------------------------ */
|
|
30
|
+
exports.loginBodySchema = {
|
|
31
|
+
type: 'object',
|
|
32
|
+
required: ['login', 'password'],
|
|
33
|
+
properties: {
|
|
34
|
+
login: { type: 'string', minLength: 1 },
|
|
35
|
+
password: { type: 'string', minLength: 1 },
|
|
36
|
+
...tokenMetadataProperties,
|
|
37
|
+
...keepSessionProperty
|
|
38
|
+
},
|
|
39
|
+
additionalProperties: true
|
|
40
|
+
};
|
|
41
|
+
exports.refreshBodySchema = {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
refreshToken: { type: 'string' },
|
|
45
|
+
domain: { type: 'string' },
|
|
46
|
+
fingerprint: { type: 'string' },
|
|
47
|
+
label: { type: 'string' },
|
|
48
|
+
...keepSessionProperty
|
|
49
|
+
},
|
|
50
|
+
additionalProperties: false
|
|
51
|
+
};
|
|
52
|
+
exports.logoutBodySchema = {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: {
|
|
55
|
+
token: { type: 'string' },
|
|
56
|
+
refreshToken: { type: 'string' }
|
|
57
|
+
},
|
|
58
|
+
additionalProperties: false
|
|
59
|
+
};
|
|
60
|
+
exports.whoamiBodySchema = {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
refreshToken: { type: 'string' },
|
|
64
|
+
refresh: { type: 'boolean' }
|
|
65
|
+
},
|
|
66
|
+
additionalProperties: false
|
|
67
|
+
};
|
|
68
|
+
/* ------------------------------------------------------------------ */
|
|
69
|
+
/* Passkey schemas */
|
|
70
|
+
/* ------------------------------------------------------------------ */
|
|
71
|
+
exports.passkeyChallengeBodySchema = {
|
|
72
|
+
type: 'object',
|
|
73
|
+
required: ['action'],
|
|
74
|
+
properties: {
|
|
75
|
+
action: { type: 'string', enum: ['register', 'authenticate'] },
|
|
76
|
+
login: { type: 'string' },
|
|
77
|
+
...authIdentifierProperty('userId')
|
|
78
|
+
},
|
|
79
|
+
additionalProperties: false
|
|
80
|
+
};
|
|
81
|
+
exports.passkeyVerifyBodySchema = {
|
|
82
|
+
type: 'object',
|
|
83
|
+
required: ['expectedChallenge', 'response'],
|
|
84
|
+
properties: {
|
|
85
|
+
expectedChallenge: { type: 'string' },
|
|
86
|
+
response: { type: 'object' },
|
|
87
|
+
login: { type: 'string' },
|
|
88
|
+
...authIdentifierProperty('userId'),
|
|
89
|
+
userAgent: { type: 'string' },
|
|
90
|
+
...tokenMetadataProperties,
|
|
91
|
+
...keepSessionProperty
|
|
92
|
+
},
|
|
93
|
+
additionalProperties: true
|
|
94
|
+
};
|
|
95
|
+
exports.passkeyCredentialParamsSchema = {
|
|
96
|
+
type: 'object',
|
|
97
|
+
required: ['credentialId'],
|
|
98
|
+
properties: {
|
|
99
|
+
credentialId: { type: 'string', minLength: 1 }
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/* ------------------------------------------------------------------ */
|
|
103
|
+
/* Impersonation schemas */
|
|
104
|
+
/* ------------------------------------------------------------------ */
|
|
105
|
+
exports.impersonateBodySchema = {
|
|
106
|
+
type: 'object',
|
|
107
|
+
properties: {
|
|
108
|
+
...authIdentifierProperty('userId'),
|
|
109
|
+
login: { type: 'string' },
|
|
110
|
+
...tokenMetadataProperties,
|
|
111
|
+
...keepSessionProperty,
|
|
112
|
+
clientId: { type: 'string' },
|
|
113
|
+
scope: {},
|
|
114
|
+
loginType: { type: 'string' }
|
|
115
|
+
},
|
|
116
|
+
additionalProperties: true
|
|
117
|
+
};
|
|
118
|
+
exports.deleteImpersonationQuerySchema = {
|
|
119
|
+
type: 'object',
|
|
120
|
+
additionalProperties: true
|
|
121
|
+
};
|
|
122
|
+
/* ------------------------------------------------------------------ */
|
|
123
|
+
/* OAuth schemas */
|
|
124
|
+
/* ------------------------------------------------------------------ */
|
|
125
|
+
exports.oauthProviderParamsSchema = {
|
|
126
|
+
type: 'object',
|
|
127
|
+
required: ['provider'],
|
|
128
|
+
properties: {
|
|
129
|
+
provider: { type: 'string', minLength: 1 }
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
exports.oauthStartBodySchema = {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
redirectUri: { type: 'string' },
|
|
136
|
+
scope: {},
|
|
137
|
+
state: { type: 'string' },
|
|
138
|
+
extras: { type: 'object' }
|
|
139
|
+
},
|
|
140
|
+
additionalProperties: true
|
|
141
|
+
};
|
|
142
|
+
exports.oauthAuthorizeBodySchema = {
|
|
143
|
+
type: 'object',
|
|
144
|
+
required: ['clientId', 'redirectUri'],
|
|
145
|
+
properties: {
|
|
146
|
+
clientId: { type: 'string', minLength: 1 },
|
|
147
|
+
redirectUri: { type: 'string', minLength: 1 },
|
|
148
|
+
scope: {},
|
|
149
|
+
state: { type: 'string' },
|
|
150
|
+
codeChallenge: { type: 'string' },
|
|
151
|
+
codeChallengeMethod: { type: 'string' },
|
|
152
|
+
login: { type: 'string' },
|
|
153
|
+
password: { type: 'string' }
|
|
154
|
+
},
|
|
155
|
+
additionalProperties: false
|
|
156
|
+
};
|
|
157
|
+
exports.oauthTokenBodySchema = {
|
|
158
|
+
type: 'object',
|
|
159
|
+
required: ['grant_type'],
|
|
160
|
+
properties: {
|
|
161
|
+
grant_type: { type: 'string', enum: ['authorization_code', 'refresh_token'] },
|
|
162
|
+
code: { type: 'string' },
|
|
163
|
+
redirect_uri: { type: 'string' },
|
|
164
|
+
code_verifier: { type: 'string' },
|
|
165
|
+
client_id: { type: 'string' },
|
|
166
|
+
client_secret: { type: 'string' },
|
|
167
|
+
refresh_token: { type: 'string' },
|
|
168
|
+
scope: { type: 'string' }
|
|
169
|
+
},
|
|
170
|
+
additionalProperties: false
|
|
171
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema definitions for auth module routes.
|
|
3
|
+
* These are the runtime validation source-of-truth; TypeScript interfaces
|
|
4
|
+
* in auth-module.ts remain for handler-internal typing only.
|
|
5
|
+
*/
|
|
6
|
+
/** Loose JSON Schema object type used for Fastify route schema definitions. */
|
|
7
|
+
type JsonSchema = Record<string, unknown>;
|
|
8
|
+
export declare const loginBodySchema: JsonSchema;
|
|
9
|
+
export declare const refreshBodySchema: JsonSchema;
|
|
10
|
+
export declare const logoutBodySchema: JsonSchema;
|
|
11
|
+
export declare const whoamiBodySchema: JsonSchema;
|
|
12
|
+
export declare const passkeyChallengeBodySchema: JsonSchema;
|
|
13
|
+
export declare const passkeyVerifyBodySchema: JsonSchema;
|
|
14
|
+
export declare const passkeyCredentialParamsSchema: JsonSchema;
|
|
15
|
+
export declare const impersonateBodySchema: JsonSchema;
|
|
16
|
+
export declare const deleteImpersonationQuerySchema: JsonSchema;
|
|
17
|
+
export declare const oauthProviderParamsSchema: JsonSchema;
|
|
18
|
+
export declare const oauthStartBodySchema: JsonSchema;
|
|
19
|
+
export declare const oauthAuthorizeBodySchema: JsonSchema;
|
|
20
|
+
export declare const oauthTokenBodySchema: JsonSchema;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqlAuthStore = void 0;
|
|
4
|
+
const sequelize_js_1 = require("../oauth/sequelize.cjs");
|
|
5
|
+
const config_js_1 = require("../passkey/config.cjs");
|
|
6
|
+
const sequelize_js_2 = require("../passkey/sequelize.cjs");
|
|
7
|
+
const sequelize_utils_js_1 = require("../sequelize-utils.cjs");
|
|
8
|
+
const sequelize_js_3 = require("../token/sequelize.cjs");
|
|
9
|
+
const sequelize_js_4 = require("../user/sequelize.cjs");
|
|
10
|
+
const compat_auth_storage_js_1 = require("./compat-auth-storage.cjs");
|
|
11
|
+
const user_id_js_1 = require("./user-id.cjs");
|
|
12
|
+
function resolveTablePrefix(...prefixes) {
|
|
13
|
+
for (const prefix of prefixes) {
|
|
14
|
+
const normalized = (0, sequelize_utils_js_1.normalizeTablePrefix)(prefix);
|
|
15
|
+
if (normalized) {
|
|
16
|
+
return normalized;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
class SqlAuthStore {
|
|
22
|
+
constructor(params) {
|
|
23
|
+
this.closed = false;
|
|
24
|
+
if (!params?.sequelize) {
|
|
25
|
+
throw new Error('SqlAuthStore requires an initialised Sequelize instance');
|
|
26
|
+
}
|
|
27
|
+
this.sequelize = params.sequelize;
|
|
28
|
+
this.syncOptions = params.syncOptions;
|
|
29
|
+
const moduleTablePrefixes = params.tablePrefixes ?? {};
|
|
30
|
+
const userTablePrefix = resolveTablePrefix(moduleTablePrefixes.user, params.tablePrefix);
|
|
31
|
+
this.userStore = new sequelize_js_4.SequelizeUserStore({
|
|
32
|
+
sequelize: this.sequelize,
|
|
33
|
+
userModel: params.userModel,
|
|
34
|
+
userModelFactory: params.userModelFactory,
|
|
35
|
+
recordMapper: params.userRecordMapper,
|
|
36
|
+
toPublic: params.publicUserMapper,
|
|
37
|
+
bcryptRounds: params.bcryptRounds,
|
|
38
|
+
bcryptPepper: params.passwordPepper,
|
|
39
|
+
tablePrefix: userTablePrefix
|
|
40
|
+
});
|
|
41
|
+
const tokenTablePrefix = resolveTablePrefix(params.tokenStoreOptions?.tablePrefix, moduleTablePrefixes.token, params.tablePrefix);
|
|
42
|
+
this.tokenStore =
|
|
43
|
+
params.tokenStore ??
|
|
44
|
+
new sequelize_js_3.SequelizeTokenStore({
|
|
45
|
+
sequelize: this.sequelize,
|
|
46
|
+
...params.tokenStoreOptions,
|
|
47
|
+
tablePrefix: tokenTablePrefix
|
|
48
|
+
});
|
|
49
|
+
const oauthTablePrefix = resolveTablePrefix(params.oauthStoreOptions?.tablePrefix, moduleTablePrefixes.oauth, params.tablePrefix);
|
|
50
|
+
this.oauthStore = new sequelize_js_1.SequelizeOAuthStore({
|
|
51
|
+
sequelize: this.sequelize,
|
|
52
|
+
...params.oauthStoreOptions,
|
|
53
|
+
tablePrefix: oauthTablePrefix,
|
|
54
|
+
bcryptRounds: params.bcryptRounds
|
|
55
|
+
});
|
|
56
|
+
let passkeyStore;
|
|
57
|
+
let passkeyConfig;
|
|
58
|
+
if (params.passkeys !== false) {
|
|
59
|
+
const passkeyTablePrefix = resolveTablePrefix(moduleTablePrefixes.passkey, params.tablePrefix);
|
|
60
|
+
passkeyConfig = (0, config_js_1.normalizePasskeyConfig)(params.passkeys ?? {});
|
|
61
|
+
const resolveUser = async (lookup) => {
|
|
62
|
+
const found = await this.userStore.findUser(lookup.userId ?? lookup.login ?? '');
|
|
63
|
+
if (!found) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const mapper = params.passkeyUserMapper ??
|
|
67
|
+
((user) => ({
|
|
68
|
+
id: (this.userStore.getUserId(user) ?? user['user_id']),
|
|
69
|
+
login: user.login ?? String(this.userStore.getUserId(user)),
|
|
70
|
+
displayName: user.login ?? String(this.userStore.getUserId(user))
|
|
71
|
+
}));
|
|
72
|
+
return mapper(found);
|
|
73
|
+
};
|
|
74
|
+
passkeyStore = new sequelize_js_2.SequelizePasskeyStore({
|
|
75
|
+
sequelize: this.sequelize,
|
|
76
|
+
resolveUser,
|
|
77
|
+
tablePrefix: passkeyTablePrefix
|
|
78
|
+
});
|
|
79
|
+
this.passkeyStore = passkeyStore;
|
|
80
|
+
}
|
|
81
|
+
this.adapter = new compat_auth_storage_js_1.CompositeAuthAdapter({
|
|
82
|
+
userStore: this.userStore,
|
|
83
|
+
tokenStore: this.tokenStore,
|
|
84
|
+
passkeys: passkeyStore && passkeyConfig ? { store: passkeyStore, config: passkeyConfig } : undefined,
|
|
85
|
+
oauthStore: this.oauthStore,
|
|
86
|
+
canImpersonate: params.canImpersonate
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async initialise(withSync = false) {
|
|
90
|
+
await this.sequelize.authenticate();
|
|
91
|
+
if (withSync) {
|
|
92
|
+
await this.sequelize.sync(this.syncOptions);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async close() {
|
|
96
|
+
if (this.closed) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.closed = true;
|
|
100
|
+
try {
|
|
101
|
+
await this.sequelize.close();
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const message = error?.message ?? '';
|
|
105
|
+
if (!/closed/i.test(message)) {
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
// Prevent double-close errors when the same Sequelize instance is shared with other code.
|
|
111
|
+
this.sequelize.close = async () => { };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async getUser(identifier) {
|
|
115
|
+
return this.adapter.getUser(identifier);
|
|
116
|
+
}
|
|
117
|
+
getUserPasswordHash(user) {
|
|
118
|
+
return this.adapter.getUserPasswordHash(user);
|
|
119
|
+
}
|
|
120
|
+
getUserId(user) {
|
|
121
|
+
return this.adapter.getUserId(user);
|
|
122
|
+
}
|
|
123
|
+
filterUser(user) {
|
|
124
|
+
return this.adapter.filterUser(user);
|
|
125
|
+
}
|
|
126
|
+
async verifyPassword(password, hash) {
|
|
127
|
+
return this.adapter.verifyPassword(password, hash);
|
|
128
|
+
}
|
|
129
|
+
async storeToken(data) {
|
|
130
|
+
return this.adapter.storeToken(data);
|
|
131
|
+
}
|
|
132
|
+
async getToken(query, opts) {
|
|
133
|
+
const normalized = {
|
|
134
|
+
...query,
|
|
135
|
+
userId: (0, user_id_js_1.toOptionalStringId)(query.userId),
|
|
136
|
+
ruid: (0, user_id_js_1.toOptionalStringId)(query.ruid)
|
|
137
|
+
};
|
|
138
|
+
return this.adapter.getToken(normalized, opts);
|
|
139
|
+
}
|
|
140
|
+
async deleteToken(query) {
|
|
141
|
+
const normalized = {
|
|
142
|
+
...query,
|
|
143
|
+
userId: (0, user_id_js_1.toOptionalStringId)(query.userId),
|
|
144
|
+
ruid: (0, user_id_js_1.toOptionalStringId)(query.ruid)
|
|
145
|
+
};
|
|
146
|
+
return this.adapter.deleteToken(normalized);
|
|
147
|
+
}
|
|
148
|
+
async updateToken(updates) {
|
|
149
|
+
return this.adapter.updateToken(updates);
|
|
150
|
+
}
|
|
151
|
+
async createPasskeyChallenge(params) {
|
|
152
|
+
return this.adapter.createPasskeyChallenge(params);
|
|
153
|
+
}
|
|
154
|
+
async verifyPasskeyResponse(params) {
|
|
155
|
+
return this.adapter.verifyPasskeyResponse(params);
|
|
156
|
+
}
|
|
157
|
+
async listUserCredentials(userId) {
|
|
158
|
+
return this.adapter.listUserCredentials(userId);
|
|
159
|
+
}
|
|
160
|
+
async deletePasskeyCredential(credentialId) {
|
|
161
|
+
return this.adapter.deletePasskeyCredential(credentialId);
|
|
162
|
+
}
|
|
163
|
+
async getClient(clientId) {
|
|
164
|
+
return this.adapter.getClient(clientId);
|
|
165
|
+
}
|
|
166
|
+
async verifyClientSecret(client, clientSecret) {
|
|
167
|
+
return this.adapter.verifyClientSecret(client, clientSecret);
|
|
168
|
+
}
|
|
169
|
+
async createAuthCode(request) {
|
|
170
|
+
return this.adapter.createAuthCode(request);
|
|
171
|
+
}
|
|
172
|
+
async consumeAuthCode(code, clientId) {
|
|
173
|
+
return this.adapter.consumeAuthCode(code, clientId);
|
|
174
|
+
}
|
|
175
|
+
async canImpersonate(params) {
|
|
176
|
+
return this.adapter.canImpersonate(params);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.SqlAuthStore = SqlAuthStore;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Sequelize, type SyncOptions } from 'sequelize';
|
|
2
|
+
import { SequelizeOAuthStore, type SequelizeOAuthStoreOptions } from '../oauth/sequelize.js';
|
|
3
|
+
import { SequelizePasskeyStore } from '../passkey/sequelize.js';
|
|
4
|
+
import { type SequelizeTokenStoreOptions } from '../token/sequelize.js';
|
|
5
|
+
import { SequelizeUserStore, type AuthUserAttributes, GenericUserModel, GenericUserModelStatic } from '../user/sequelize.js';
|
|
6
|
+
import type { AuthAdapter, AuthIdentifier } from './types.js';
|
|
7
|
+
import type { AuthCodeData, AuthCodeRequest, OAuthClient } from '../oauth/types.js';
|
|
8
|
+
import type { PasskeyChallenge, PasskeyChallengeParams, PasskeyServiceConfig, PasskeyUserDescriptor, StoredPasskeyCredential, PasskeyVerificationParams, PasskeyVerificationResult } from '../passkey/types.js';
|
|
9
|
+
import type { TokenStore } from '../token/base.js';
|
|
10
|
+
import type { Token } from '../token/types.js';
|
|
11
|
+
interface PasskeyOptions extends Partial<PasskeyServiceConfig> {
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SqlAuthStoreTablePrefixes {
|
|
15
|
+
user?: string;
|
|
16
|
+
token?: string;
|
|
17
|
+
passkey?: string;
|
|
18
|
+
oauth?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface SqlAuthStoreParams<UserAttributes extends AuthUserAttributes = AuthUserAttributes, PublicUserShape extends Omit<UserAttributes, 'password'> = Omit<UserAttributes, 'password'>> {
|
|
21
|
+
sequelize: Sequelize;
|
|
22
|
+
syncOptions?: SyncOptions;
|
|
23
|
+
bcryptRounds?: number;
|
|
24
|
+
passwordPepper?: string;
|
|
25
|
+
tablePrefix?: string;
|
|
26
|
+
tablePrefixes?: SqlAuthStoreTablePrefixes;
|
|
27
|
+
userModel?: GenericUserModelStatic;
|
|
28
|
+
userModelFactory?: (sequelize: Sequelize, options?: {
|
|
29
|
+
tablePrefix?: string;
|
|
30
|
+
}) => GenericUserModelStatic;
|
|
31
|
+
userRecordMapper?: (model: GenericUserModel) => UserAttributes;
|
|
32
|
+
publicUserMapper?: (user: UserAttributes) => PublicUserShape;
|
|
33
|
+
passkeyUserMapper?: (user: UserAttributes) => PasskeyUserDescriptor;
|
|
34
|
+
passkeys?: false | PasskeyOptions;
|
|
35
|
+
canImpersonate?: (params: {
|
|
36
|
+
realUserId: AuthIdentifier;
|
|
37
|
+
effectiveUserId: AuthIdentifier;
|
|
38
|
+
}) => boolean | Promise<boolean>;
|
|
39
|
+
tokenStore?: TokenStore;
|
|
40
|
+
tokenStoreOptions?: Omit<SequelizeTokenStoreOptions, 'sequelize'>;
|
|
41
|
+
oauthStoreOptions?: Omit<SequelizeOAuthStoreOptions, 'sequelize'>;
|
|
42
|
+
}
|
|
43
|
+
export declare class SqlAuthStore<UserAttributes extends AuthUserAttributes = AuthUserAttributes, PublicUserShape extends Omit<UserAttributes, 'password'> = Omit<UserAttributes, 'password'>> implements AuthAdapter<UserAttributes, PublicUserShape> {
|
|
44
|
+
readonly userStore: SequelizeUserStore<UserAttributes, PublicUserShape>;
|
|
45
|
+
readonly tokenStore: TokenStore;
|
|
46
|
+
readonly passkeyStore?: SequelizePasskeyStore;
|
|
47
|
+
readonly oauthStore: SequelizeOAuthStore;
|
|
48
|
+
private readonly adapter;
|
|
49
|
+
private readonly sequelize;
|
|
50
|
+
private closed;
|
|
51
|
+
private readonly syncOptions?;
|
|
52
|
+
constructor(params: SqlAuthStoreParams<UserAttributes, PublicUserShape>);
|
|
53
|
+
initialise(withSync?: boolean): Promise<void>;
|
|
54
|
+
close(): Promise<void>;
|
|
55
|
+
getUser(identifier: AuthIdentifier): Promise<UserAttributes | null>;
|
|
56
|
+
getUserPasswordHash(user: UserAttributes): string;
|
|
57
|
+
getUserId(user: UserAttributes): AuthIdentifier;
|
|
58
|
+
filterUser(user: UserAttributes): PublicUserShape;
|
|
59
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
60
|
+
storeToken(data: Token): Promise<void>;
|
|
61
|
+
getToken(query: Partial<Token> & {
|
|
62
|
+
userId?: AuthIdentifier;
|
|
63
|
+
ruid?: AuthIdentifier;
|
|
64
|
+
}, opts?: {
|
|
65
|
+
includeExpired?: boolean;
|
|
66
|
+
}): Promise<Token | null>;
|
|
67
|
+
deleteToken(query: Partial<Token> & {
|
|
68
|
+
userId?: AuthIdentifier;
|
|
69
|
+
ruid?: AuthIdentifier;
|
|
70
|
+
}): Promise<number>;
|
|
71
|
+
updateToken(updates: Partial<Token> & {
|
|
72
|
+
refreshToken: string;
|
|
73
|
+
}): Promise<boolean>;
|
|
74
|
+
createPasskeyChallenge(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
|
|
75
|
+
verifyPasskeyResponse(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
|
|
76
|
+
listUserCredentials(userId: AuthIdentifier): Promise<StoredPasskeyCredential[]>;
|
|
77
|
+
deletePasskeyCredential(credentialId: Buffer | string): Promise<boolean>;
|
|
78
|
+
getClient(clientId: string): Promise<OAuthClient | null>;
|
|
79
|
+
verifyClientSecret(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
|
|
80
|
+
createAuthCode(request: AuthCodeRequest): Promise<AuthCodeData>;
|
|
81
|
+
consumeAuthCode(code: string, clientId: string): Promise<AuthCodeData | null>;
|
|
82
|
+
canImpersonate(params: {
|
|
83
|
+
realUserId: AuthIdentifier;
|
|
84
|
+
effectiveUserId: AuthIdentifier;
|
|
85
|
+
}): Promise<boolean>;
|
|
86
|
+
}
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nullAuthAdapter = exports.BaseAuthAdapter = void 0;
|
|
4
|
+
// Handy base you can extend when wiring a real auth adapter. Every method
|
|
5
|
+
// throws by default so unimplemented hooks fail loudly.
|
|
6
|
+
class BaseAuthAdapter {
|
|
7
|
+
// Override to load a user record by identifier
|
|
8
|
+
async getUser(identifier) {
|
|
9
|
+
void identifier;
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
// Override to return the stored password hash for the user
|
|
13
|
+
getUserPasswordHash(user) {
|
|
14
|
+
void user;
|
|
15
|
+
throw new Error('Auth storage not configured');
|
|
16
|
+
}
|
|
17
|
+
// Override to expose the canonical user identifier
|
|
18
|
+
getUserId(user) {
|
|
19
|
+
void user;
|
|
20
|
+
throw new Error('Auth storage not configured');
|
|
21
|
+
}
|
|
22
|
+
// Override to strip sensitive fields from the user record
|
|
23
|
+
filterUser(user) {
|
|
24
|
+
return user;
|
|
25
|
+
}
|
|
26
|
+
// Override to validate a raw password against the stored hash
|
|
27
|
+
async verifyPassword(password, hash) {
|
|
28
|
+
void password;
|
|
29
|
+
void hash;
|
|
30
|
+
throw new Error('Auth storage not configured');
|
|
31
|
+
}
|
|
32
|
+
// Override to persist newly issued tokens
|
|
33
|
+
async storeToken(data) {
|
|
34
|
+
void data;
|
|
35
|
+
throw new Error('Auth storage not configured');
|
|
36
|
+
}
|
|
37
|
+
// Override to look up a stored token by query
|
|
38
|
+
async getToken(query, opts) {
|
|
39
|
+
void query;
|
|
40
|
+
void opts;
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Override to remove stored tokens that match the query
|
|
44
|
+
async deleteToken(query) {
|
|
45
|
+
void query;
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
// Override to update metadata for an existing refresh token
|
|
49
|
+
async updateToken(updates) {
|
|
50
|
+
void updates;
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
// Override to create a new passkey challenge record
|
|
54
|
+
async createPasskeyChallenge(params) {
|
|
55
|
+
void params;
|
|
56
|
+
throw new Error('Auth storage not configured');
|
|
57
|
+
}
|
|
58
|
+
// Override to verify an incoming WebAuthn response
|
|
59
|
+
async verifyPasskeyResponse(params) {
|
|
60
|
+
void params;
|
|
61
|
+
throw new Error('Auth storage not configured');
|
|
62
|
+
}
|
|
63
|
+
// Override to list passkey credentials for a user
|
|
64
|
+
async listUserCredentials(userId) {
|
|
65
|
+
void userId;
|
|
66
|
+
throw new Error('Auth storage not configured');
|
|
67
|
+
}
|
|
68
|
+
// Override to delete a passkey credential
|
|
69
|
+
async deletePasskeyCredential(credentialId) {
|
|
70
|
+
void credentialId;
|
|
71
|
+
throw new Error('Auth storage not configured');
|
|
72
|
+
}
|
|
73
|
+
// Override to fetch an OAuth client by identifier
|
|
74
|
+
async getClient(clientId) {
|
|
75
|
+
void clientId;
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
// Override to compare a provided client secret against storage
|
|
79
|
+
async verifyClientSecret(client, clientSecret) {
|
|
80
|
+
void client;
|
|
81
|
+
void clientSecret;
|
|
82
|
+
throw new Error('Auth storage not configured');
|
|
83
|
+
}
|
|
84
|
+
// Override to create a new authorization code entry
|
|
85
|
+
async createAuthCode(request) {
|
|
86
|
+
void request;
|
|
87
|
+
throw new Error('Auth storage not configured');
|
|
88
|
+
}
|
|
89
|
+
// Override to consume and invalidate an authorization code
|
|
90
|
+
async consumeAuthCode(code, clientId) {
|
|
91
|
+
void code;
|
|
92
|
+
void clientId;
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
// Override to decide if a real user may impersonate another user
|
|
96
|
+
async canImpersonate(params) {
|
|
97
|
+
void params;
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.BaseAuthAdapter = BaseAuthAdapter;
|
|
102
|
+
exports.nullAuthAdapter = new BaseAuthAdapter();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AuthAdapter, AuthIdentifier } from './types.js';
|
|
2
|
+
import type { AuthCodeData, AuthCodeRequest, OAuthClient } from '../oauth/types.js';
|
|
3
|
+
import type { PasskeyChallenge, PasskeyChallengeParams, PasskeyVerificationParams, PasskeyVerificationResult, StoredPasskeyCredential } from '../passkey/types.js';
|
|
4
|
+
import type { Token } from '../token/types.js';
|
|
5
|
+
export declare class BaseAuthAdapter<UserRow = unknown, SafeUser = unknown> implements AuthAdapter<UserRow, SafeUser> {
|
|
6
|
+
getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
|
|
7
|
+
getUserPasswordHash(user: UserRow): string;
|
|
8
|
+
getUserId(user: UserRow): AuthIdentifier;
|
|
9
|
+
filterUser(user: UserRow): SafeUser;
|
|
10
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
11
|
+
storeToken(data: Token): Promise<void>;
|
|
12
|
+
getToken(query: Partial<Omit<Token, 'userId' | 'ruid'>> & {
|
|
13
|
+
userId?: string | number;
|
|
14
|
+
ruid?: string | number;
|
|
15
|
+
}, opts?: {
|
|
16
|
+
includeExpired?: boolean;
|
|
17
|
+
}): Promise<Token | null>;
|
|
18
|
+
deleteToken(query: Partial<Omit<Token, 'userId' | 'ruid'>> & {
|
|
19
|
+
userId?: string | number;
|
|
20
|
+
ruid?: string | number;
|
|
21
|
+
}): Promise<number>;
|
|
22
|
+
updateToken(updates: Partial<Token> & {
|
|
23
|
+
refreshToken: string;
|
|
24
|
+
}): Promise<boolean>;
|
|
25
|
+
createPasskeyChallenge(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
|
|
26
|
+
verifyPasskeyResponse(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
|
|
27
|
+
listUserCredentials(userId: AuthIdentifier): Promise<StoredPasskeyCredential[]>;
|
|
28
|
+
deletePasskeyCredential(credentialId: Buffer | string): Promise<boolean>;
|
|
29
|
+
getClient(clientId: string): Promise<OAuthClient | null>;
|
|
30
|
+
verifyClientSecret(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
|
|
31
|
+
createAuthCode(request: AuthCodeRequest): Promise<AuthCodeData>;
|
|
32
|
+
consumeAuthCode(code: string, clientId: string): Promise<AuthCodeData | null>;
|
|
33
|
+
canImpersonate(params: {
|
|
34
|
+
realUserId: AuthIdentifier;
|
|
35
|
+
effectiveUserId: AuthIdentifier;
|
|
36
|
+
}): Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
export declare const nullAuthAdapter: AuthAdapter<unknown, unknown>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AuthCodeData, AuthCodeRequest, OAuthClient } from '../oauth/types.js';
|
|
2
|
+
import type { PasskeyChallenge, PasskeyChallengeParams, PasskeyVerificationParams, PasskeyVerificationResult, StoredPasskeyCredential } from '../passkey/types.js';
|
|
3
|
+
import type { Token } from '../token/types.js';
|
|
4
|
+
export type AuthIdentifier = string | number;
|
|
5
|
+
/** @internal */
|
|
6
|
+
export interface AuthAdapter<UserRow, SafeUser> {
|
|
7
|
+
getUser(identifier: AuthIdentifier): Promise<UserRow | null>;
|
|
8
|
+
getUserPasswordHash(user: UserRow): string;
|
|
9
|
+
getUserId(user: UserRow): AuthIdentifier;
|
|
10
|
+
filterUser(user: UserRow): SafeUser;
|
|
11
|
+
verifyPassword(password: string, hash: string): Promise<boolean>;
|
|
12
|
+
storeToken(data: Token): Promise<void>;
|
|
13
|
+
getToken(query: Partial<Token>, opts?: {
|
|
14
|
+
includeExpired?: boolean;
|
|
15
|
+
}): Promise<Token | null>;
|
|
16
|
+
deleteToken(query: Partial<Token>): Promise<number>;
|
|
17
|
+
updateToken?(updates: Partial<Token> & {
|
|
18
|
+
refreshToken: string;
|
|
19
|
+
}): Promise<boolean>;
|
|
20
|
+
createPasskeyChallenge?(params: PasskeyChallengeParams): Promise<PasskeyChallenge>;
|
|
21
|
+
verifyPasskeyResponse?(params: PasskeyVerificationParams): Promise<PasskeyVerificationResult>;
|
|
22
|
+
listUserCredentials?(userId: AuthIdentifier): Promise<StoredPasskeyCredential[]>;
|
|
23
|
+
deletePasskeyCredential?(credentialId: Buffer | string): Promise<boolean>;
|
|
24
|
+
getClient?(clientId: string): Promise<OAuthClient | null>;
|
|
25
|
+
verifyClientSecret?(client: OAuthClient, clientSecret: string | null): Promise<boolean>;
|
|
26
|
+
createAuthCode?(request: AuthCodeRequest): Promise<AuthCodeData>;
|
|
27
|
+
consumeAuthCode?(code: string, clientId: string): Promise<AuthCodeData | null>;
|
|
28
|
+
canImpersonate?(params: {
|
|
29
|
+
realUserId: AuthIdentifier;
|
|
30
|
+
effectiveUserId: AuthIdentifier;
|
|
31
|
+
}): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
/** @internal */
|
|
34
|
+
export type AuthStorage<UserRow, SafeUser> = AuthAdapter<UserRow, SafeUser>;
|