auth-vir 5.0.1 → 5.0.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.
- package/package.json +4 -4
- package/src/auth-client/backend-auth.client.ts +8 -0
- package/src/auth.ts +9 -1
- package/dist/auth-client/backend-auth.client.d.ts +0 -263
- package/dist/auth-client/backend-auth.client.js +0 -391
- package/dist/auth-client/frontend-auth.client.d.ts +0 -113
- package/dist/auth-client/frontend-auth.client.js +0 -131
- package/dist/auth-client/is-session-refresh-ready.d.ts +0 -23
- package/dist/auth-client/is-session-refresh-ready.js +0 -21
- package/dist/auth.d.ts +0 -74
- package/dist/auth.js +0 -128
- package/dist/cookie.d.ts +0 -111
- package/dist/cookie.js +0 -137
- package/dist/csrf-token.d.ts +0 -33
- package/dist/csrf-token.js +0 -42
- package/dist/generated/browser.d.ts +0 -9
- package/dist/generated/browser.js +0 -17
- package/dist/generated/client.d.ts +0 -26
- package/dist/generated/client.js +0 -32
- package/dist/generated/commonInputTypes.d.ts +0 -122
- package/dist/generated/commonInputTypes.js +0 -1
- package/dist/generated/enums.d.ts +0 -1
- package/dist/generated/enums.js +0 -10
- package/dist/generated/internal/class.d.ts +0 -126
- package/dist/generated/internal/class.js +0 -85
- package/dist/generated/internal/prismaNamespace.d.ts +0 -545
- package/dist/generated/internal/prismaNamespace.js +0 -102
- package/dist/generated/internal/prismaNamespaceBrowser.d.ts +0 -75
- package/dist/generated/internal/prismaNamespaceBrowser.js +0 -70
- package/dist/generated/models/User.d.ts +0 -980
- package/dist/generated/models/User.js +0 -1
- package/dist/generated/models.d.ts +0 -2
- package/dist/generated/models.js +0 -1
- package/dist/generated/shapes.gen.d.ts +0 -8
- package/dist/generated/shapes.gen.js +0 -11
- package/dist/hash.d.ts +0 -42
- package/dist/hash.js +0 -52
- package/dist/headers.d.ts +0 -19
- package/dist/headers.js +0 -32
- package/dist/index.d.ts +0 -11
- package/dist/index.js +0 -11
- package/dist/jwt/jwt-keys.d.ts +0 -44
- package/dist/jwt/jwt-keys.js +0 -57
- package/dist/jwt/jwt-keys.script.d.ts +0 -1
- package/dist/jwt/jwt-keys.script.js +0 -3
- package/dist/jwt/jwt.d.ts +0 -126
- package/dist/jwt/jwt.js +0 -109
- package/dist/jwt/user-jwt.d.ts +0 -44
- package/dist/jwt/user-jwt.js +0 -53
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auth-vir",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"description": "Auth made easy and secure via JWT cookies, CSRF tokens, and password hashing helpers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"url": "https://github.com/electrovir"
|
|
26
26
|
},
|
|
27
27
|
"type": "module",
|
|
28
|
-
"main": "
|
|
29
|
-
"module": "
|
|
30
|
-
"types": "
|
|
28
|
+
"main": "src/index.ts",
|
|
29
|
+
"module": "src/index.ts",
|
|
30
|
+
"types": "src/index.ts",
|
|
31
31
|
"bin": "bin.js",
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "virmator frontend build",
|
|
@@ -578,6 +578,8 @@ export class BackendAuthClient<
|
|
|
578
578
|
'set-cookie': string[];
|
|
579
579
|
}
|
|
580
580
|
> {
|
|
581
|
+
const clearingAllCookies = !!params.allCookies;
|
|
582
|
+
|
|
581
583
|
const signUpCookieHeaders =
|
|
582
584
|
params.allCookies || params.isSignUpCookie
|
|
583
585
|
? generateLogoutHeaders(
|
|
@@ -585,6 +587,9 @@ export class BackendAuthClient<
|
|
|
585
587
|
isSignUpCookie: true,
|
|
586
588
|
requestHeaders: undefined,
|
|
587
589
|
}),
|
|
590
|
+
{
|
|
591
|
+
preserveCsrf: !clearingAllCookies,
|
|
592
|
+
},
|
|
588
593
|
)
|
|
589
594
|
: undefined;
|
|
590
595
|
const authCookieHeaders =
|
|
@@ -594,6 +599,9 @@ export class BackendAuthClient<
|
|
|
594
599
|
isSignUpCookie: false,
|
|
595
600
|
requestHeaders: undefined,
|
|
596
601
|
}),
|
|
602
|
+
{
|
|
603
|
+
preserveCsrf: !clearingAllCookies,
|
|
604
|
+
},
|
|
597
605
|
)
|
|
598
606
|
: undefined;
|
|
599
607
|
|
package/src/auth.ts
CHANGED
|
@@ -189,11 +189,19 @@ export async function generateSuccessfulLoginHeaders(
|
|
|
189
189
|
*/
|
|
190
190
|
export function generateLogoutHeaders(
|
|
191
191
|
cookieConfig: Readonly<SelectFrom<CookieParams, {hostOrigin: true; isDev: true}>>,
|
|
192
|
+
options?: Readonly<{
|
|
193
|
+
/**
|
|
194
|
+
* When `true`, the CSRF cookie is preserved (not cleared). Use this when clearing only one
|
|
195
|
+
* cookie type (e.g., the auth cookie) while keeping the other active session (e.g.,
|
|
196
|
+
* sign-up) that still needs its CSRF token.
|
|
197
|
+
*/
|
|
198
|
+
preserveCsrf?: boolean | undefined;
|
|
199
|
+
}>,
|
|
192
200
|
): Record<string, string[]> {
|
|
193
201
|
return {
|
|
194
202
|
'set-cookie': [
|
|
195
203
|
clearAuthCookie(cookieConfig),
|
|
196
|
-
clearCsrfCookie(cookieConfig),
|
|
204
|
+
...(options?.preserveCsrf ? [] : [clearCsrfCookie(cookieConfig)]),
|
|
197
205
|
],
|
|
198
206
|
};
|
|
199
207
|
}
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { type AnyObject, type JsonCompatibleObject, type MaybePromise, type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
-
import { type AnyDuration } from 'date-vir';
|
|
3
|
-
import { type IncomingHttpHeaders, type OutgoingHttpHeaders } from 'node:http';
|
|
4
|
-
import { type EmptyObject, type RequireExactlyOne, type RequireOneOrNone } from 'type-fest';
|
|
5
|
-
import { type UserIdResult } from '../auth.js';
|
|
6
|
-
import { type CookieParams } from '../cookie.js';
|
|
7
|
-
import { type CsrfHeaderNameOption } from '../csrf-token.js';
|
|
8
|
-
import { type JwtKeys, type RawJwtKeys } from '../jwt/jwt-keys.js';
|
|
9
|
-
import { type CreateJwtParams, type ParseJwtParams } from '../jwt/jwt.js';
|
|
10
|
-
/**
|
|
11
|
-
* Output from `BackendAuthClient.getSecureUser()`.
|
|
12
|
-
*
|
|
13
|
-
* @category Internal
|
|
14
|
-
*/
|
|
15
|
-
export type GetUserResult<DatabaseUser extends AnyObject> = {
|
|
16
|
-
/** The retrieved user. */
|
|
17
|
-
user: DatabaseUser;
|
|
18
|
-
/**
|
|
19
|
-
* When `true`, indicates that the current `user` result is as assumed user. This can only be
|
|
20
|
-
* `true` if you've configured user assuming in `BackendAuthClient`.
|
|
21
|
-
*/
|
|
22
|
-
isAssumed: boolean;
|
|
23
|
-
/**
|
|
24
|
-
* This should be merged into your own response headers. It usually contains auth cookie
|
|
25
|
-
* duration refresh headers.
|
|
26
|
-
*/
|
|
27
|
-
responseHeaders: OutgoingHttpHeaders;
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Config for {@link BackendAuthClient}.
|
|
31
|
-
*
|
|
32
|
-
* @category Internal
|
|
33
|
-
*/
|
|
34
|
-
export type BackendAuthClientConfig<DatabaseUser extends AnyObject, UserId extends string | number, AssumedUserParams extends JsonCompatibleObject = EmptyObject> = Readonly<{
|
|
35
|
-
csrf: Readonly<CsrfHeaderNameOption>;
|
|
36
|
-
/** The origin of your backend that is offering auth cookies. */
|
|
37
|
-
serviceOrigin: string;
|
|
38
|
-
/** Finds the relevant user from your own database. */
|
|
39
|
-
getUserFromDatabase: (userParams: {
|
|
40
|
-
/** The user id extracted from the request cookie. */
|
|
41
|
-
userId: UserId;
|
|
42
|
-
/** Indicates that we're loading the user from a sign up cookie. */
|
|
43
|
-
isSignUpCookie: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* If this is set, we're attempting to load a database user for the purpose of assuming
|
|
46
|
-
* their user identity. Otherwise, this is `undefined`.
|
|
47
|
-
*/
|
|
48
|
-
assumingUser: AssumedUserParams | undefined;
|
|
49
|
-
requestHeaders: Readonly<IncomingHttpHeaders>;
|
|
50
|
-
}) => MaybePromise<DatabaseUser | undefined | null>;
|
|
51
|
-
/**
|
|
52
|
-
* Get JWT keys produced by {@link generateNewJwtKeys}. Make sure that each time this is
|
|
53
|
-
* called, the same JWT keys are returned (do not call {@link generateNewJwtKeys} each time
|
|
54
|
-
* this is called). Any time the JWT keys change, all current sessions will terminate.
|
|
55
|
-
*/
|
|
56
|
-
getJwtKeys: () => MaybePromise<Readonly<RawJwtKeys>>;
|
|
57
|
-
/**
|
|
58
|
-
* When `isDev` is set, cookies do not require HTTPS (so they can be used with
|
|
59
|
-
* http://localhost).
|
|
60
|
-
*/
|
|
61
|
-
isDev: boolean;
|
|
62
|
-
} & PartialWithUndefined<{
|
|
63
|
-
/** If this returns true, logging will be enabled while handling the relevant session. */
|
|
64
|
-
enableLogging(params: {
|
|
65
|
-
user: DatabaseUser | undefined;
|
|
66
|
-
userId: UserId | undefined;
|
|
67
|
-
assumedUserParams: AssumedUserParams | undefined;
|
|
68
|
-
}): boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Overwrite the header name used for tracking is an admin is assuming the identity of
|
|
71
|
-
* another user.
|
|
72
|
-
*/
|
|
73
|
-
assumedUserHeaderName: string;
|
|
74
|
-
/**
|
|
75
|
-
* Optionally generate a service origin from request headers. The generated origin is used
|
|
76
|
-
* for set-cookie headers.
|
|
77
|
-
*/
|
|
78
|
-
generateServiceOrigin(params: {
|
|
79
|
-
requestHeaders: Readonly<IncomingHttpHeaders>;
|
|
80
|
-
}): MaybePromise<undefined | string>;
|
|
81
|
-
/** If provided, logs will be sent to this method. */
|
|
82
|
-
log?: (message: string, extraData: AnyObject) => void;
|
|
83
|
-
/**
|
|
84
|
-
* Set this to allow specific users (determined by `canAssumeUser`) to assume the identity
|
|
85
|
-
* of other users. This should only be used for admins so that they can troubleshoot user
|
|
86
|
-
* issues.
|
|
87
|
-
*
|
|
88
|
-
* @see {@link AuthHeaderName}
|
|
89
|
-
*/
|
|
90
|
-
assumeUser: {
|
|
91
|
-
/**
|
|
92
|
-
* Parse the assumed user header value.
|
|
93
|
-
*
|
|
94
|
-
* @see {@link AuthHeaderName}
|
|
95
|
-
*/
|
|
96
|
-
parseAssumedUserHeaderValue: (
|
|
97
|
-
/**
|
|
98
|
-
* The assumed user header value.
|
|
99
|
-
*
|
|
100
|
-
* @see {@link AuthHeaderName}
|
|
101
|
-
*/
|
|
102
|
-
data: string) => MaybePromise<{
|
|
103
|
-
assumedUserParams: AssumedUserParams;
|
|
104
|
-
userId: UserId;
|
|
105
|
-
} | undefined>;
|
|
106
|
-
/**
|
|
107
|
-
* Return `true` to allow the current/original user to assume identities of other users.
|
|
108
|
-
* Return `false` to block it. It is recommended to only return `true` for admin users.
|
|
109
|
-
*
|
|
110
|
-
* @see {@link AuthHeaderName}
|
|
111
|
-
*/
|
|
112
|
-
canAssumeUser: (originalUser: DatabaseUser) => MaybePromise<boolean>;
|
|
113
|
-
};
|
|
114
|
-
/**
|
|
115
|
-
* This determines how long a cookie will be valid until it needs to be refreshed.
|
|
116
|
-
*
|
|
117
|
-
* @default {minutes: 20}
|
|
118
|
-
*/
|
|
119
|
-
userSessionIdleTimeout: Readonly<AnyDuration>;
|
|
120
|
-
/**
|
|
121
|
-
* How long into a user's session when we should start trying to refresh their session.
|
|
122
|
-
*
|
|
123
|
-
* @default {minutes: 2}
|
|
124
|
-
*/
|
|
125
|
-
sessionRefreshStartTime: Readonly<AnyDuration>;
|
|
126
|
-
/**
|
|
127
|
-
* The maximum duration a session can last, regardless of activity. After this time, the
|
|
128
|
-
* user will be logged out even if they are actively using the application.
|
|
129
|
-
*
|
|
130
|
-
* @default {days: 1.5}
|
|
131
|
-
*/
|
|
132
|
-
maxSessionDuration: Readonly<AnyDuration>;
|
|
133
|
-
/**
|
|
134
|
-
* Allowed clock skew tolerance for JWT and CSRF token expiration checks. Accounts for
|
|
135
|
-
* differences between server and client clocks.
|
|
136
|
-
*
|
|
137
|
-
* @default {minutes: 5}
|
|
138
|
-
*/
|
|
139
|
-
allowedClockSkew: Readonly<AnyDuration>;
|
|
140
|
-
}>>;
|
|
141
|
-
/**
|
|
142
|
-
* An auth client for creating and validating JWTs embedded in cookies. This should only be used in
|
|
143
|
-
* a backend environment as it accesses native Node packages.
|
|
144
|
-
*
|
|
145
|
-
* @category Auth : Host
|
|
146
|
-
* @category Clients
|
|
147
|
-
*/
|
|
148
|
-
export declare class BackendAuthClient<DatabaseUser extends AnyObject, UserId extends string | number, AssumedUserParams extends AnyObject = EmptyObject> {
|
|
149
|
-
protected readonly config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams>;
|
|
150
|
-
protected cachedParsedJwtKeys: Record<string, Readonly<JwtKeys>>;
|
|
151
|
-
constructor(config: BackendAuthClientConfig<DatabaseUser, UserId, AssumedUserParams>);
|
|
152
|
-
/** Conditionally logs a message if logging is enabled for the given user context. */
|
|
153
|
-
protected logForUser(params: {
|
|
154
|
-
user: DatabaseUser | undefined;
|
|
155
|
-
userId: UserId | undefined;
|
|
156
|
-
assumedUserParams: AssumedUserParams | undefined;
|
|
157
|
-
}, message: string, extra?: Record<string, unknown>): void;
|
|
158
|
-
/** Get all the parameters used for cookie generation. */
|
|
159
|
-
protected getCookieParams({ isSignUpCookie, requestHeaders, }: {
|
|
160
|
-
/**
|
|
161
|
-
* Set this to `true` when we are setting the initial cookie right after a user signs up.
|
|
162
|
-
* This allows them to auto-authorize when they verify their email address.
|
|
163
|
-
*
|
|
164
|
-
* This should only be set to `true` when a new user is signing up.
|
|
165
|
-
*/
|
|
166
|
-
isSignUpCookie: boolean;
|
|
167
|
-
requestHeaders: Readonly<IncomingHttpHeaders> | undefined;
|
|
168
|
-
}): Promise<Readonly<CookieParams>>;
|
|
169
|
-
/** Calls the provided `getUserFromDatabase` config. */
|
|
170
|
-
protected getDatabaseUser({ isSignUpCookie, userId, assumingUser, requestHeaders, }: {
|
|
171
|
-
userId: UserId | undefined;
|
|
172
|
-
assumingUser: AssumedUserParams | undefined;
|
|
173
|
-
isSignUpCookie: boolean;
|
|
174
|
-
requestHeaders: IncomingHttpHeaders;
|
|
175
|
-
}): Promise<undefined | DatabaseUser>;
|
|
176
|
-
/** Creates a `'cookie-set'` header to refresh the user's session cookie. */
|
|
177
|
-
protected createCookieRefreshHeaders({ userIdResult, requestHeaders, }: {
|
|
178
|
-
userIdResult: Readonly<UserIdResult<UserId>>;
|
|
179
|
-
requestHeaders: IncomingHttpHeaders;
|
|
180
|
-
}): Promise<OutgoingHttpHeaders | undefined>;
|
|
181
|
-
/** Reads the user's assumed user headers and, if configured, gets the assumed user. */
|
|
182
|
-
protected getAssumedUser({ requestHeaders, user, }: {
|
|
183
|
-
user: DatabaseUser;
|
|
184
|
-
requestHeaders: IncomingHttpHeaders;
|
|
185
|
-
}): Promise<DatabaseUser | undefined>;
|
|
186
|
-
/** Securely extract a user from their request headers. */
|
|
187
|
-
getSecureUser({ requestHeaders, isSignUpCookie, allowUserAuthRefresh, }: {
|
|
188
|
-
requestHeaders: IncomingHttpHeaders;
|
|
189
|
-
isSignUpCookie: boolean;
|
|
190
|
-
/**
|
|
191
|
-
* If true, this method will generate headers to refresh the user's auth session. This
|
|
192
|
-
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
193
|
-
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
194
|
-
*/
|
|
195
|
-
allowUserAuthRefresh: boolean;
|
|
196
|
-
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
197
|
-
/**
|
|
198
|
-
* Get all the JWT params used when creating the auth cookie, in case you need them for
|
|
199
|
-
* something else too.
|
|
200
|
-
*/
|
|
201
|
-
getJwtParams(): Promise<Readonly<CreateJwtParams> & ParseJwtParams>;
|
|
202
|
-
/** Use these headers to log out the user. */
|
|
203
|
-
createLogoutHeaders(params: Readonly<RequireExactlyOne<{
|
|
204
|
-
allCookies: true;
|
|
205
|
-
isSignUpCookie: boolean;
|
|
206
|
-
}> & {
|
|
207
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
208
|
-
serviceOrigin?: string | undefined;
|
|
209
|
-
}>): Promise<Record<string, string | string[]> & {
|
|
210
|
-
'set-cookie': string[];
|
|
211
|
-
}>;
|
|
212
|
-
/**
|
|
213
|
-
* Refreshes a login session by reissuing the auth cookie with the same CSRF token instead of
|
|
214
|
-
* generating a new one.
|
|
215
|
-
*/
|
|
216
|
-
protected refreshLoginHeaders({ userId, cookieParams, existingUserIdResult, }: {
|
|
217
|
-
userId: UserId;
|
|
218
|
-
cookieParams: Readonly<CookieParams>;
|
|
219
|
-
existingUserIdResult: Readonly<UserIdResult<UserId>>;
|
|
220
|
-
}): Promise<Record<string, string | string[]>>;
|
|
221
|
-
/** Use these headers to log a user in. */
|
|
222
|
-
createLoginHeaders({ userId, requestHeaders, isSignUpCookie, }: {
|
|
223
|
-
userId: UserId;
|
|
224
|
-
requestHeaders: IncomingHttpHeaders;
|
|
225
|
-
isSignUpCookie: boolean;
|
|
226
|
-
}): Promise<OutgoingHttpHeaders>;
|
|
227
|
-
/** Combines `.getInsecureUser()` and `.getSecureUser()` into one method. */
|
|
228
|
-
getInsecureOrSecureUser(params: {
|
|
229
|
-
requestHeaders: IncomingHttpHeaders;
|
|
230
|
-
isSignUpCookie: boolean;
|
|
231
|
-
/**
|
|
232
|
-
* If true, this method will generate headers to refresh the user's auth session. This
|
|
233
|
-
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
234
|
-
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
235
|
-
*/
|
|
236
|
-
allowUserAuthRefresh: boolean;
|
|
237
|
-
/** Overrides the client's already established `serviceOrigin`. */
|
|
238
|
-
serviceOrigin?: string | undefined;
|
|
239
|
-
}): Promise<RequireOneOrNone<{
|
|
240
|
-
secureUser: GetUserResult<DatabaseUser>;
|
|
241
|
-
/**
|
|
242
|
-
* @deprecated This only half authenticates the user. It should only be used in
|
|
243
|
-
* circumstances where JavaScript cannot be used to attach the CSRF token header to
|
|
244
|
-
* the request (like when opening a PDF file). Use `.getSecureUser()` instead,
|
|
245
|
-
* whenever possible.
|
|
246
|
-
*/
|
|
247
|
-
insecureUser: GetUserResult<DatabaseUser>;
|
|
248
|
-
}>>;
|
|
249
|
-
/**
|
|
250
|
-
* @deprecated This only half authenticates the user. It should only be used in circumstances
|
|
251
|
-
* where JavaScript cannot be used to attach the CSRF token header to the request (like when
|
|
252
|
-
* opening a PDF file). Use `.getSecureUser()` instead, whenever possible.
|
|
253
|
-
*/
|
|
254
|
-
getInsecureUser({ requestHeaders, allowUserAuthRefresh, }: {
|
|
255
|
-
requestHeaders: IncomingHttpHeaders;
|
|
256
|
-
/**
|
|
257
|
-
* If true, this method will generate headers to refresh the user's auth session. This
|
|
258
|
-
* should likely only be done with a specific endpoint, like whatever endpoint you trigger
|
|
259
|
-
* with the frontend auth client's `checkUser.performCheck` callback.
|
|
260
|
-
*/
|
|
261
|
-
allowUserAuthRefresh: boolean;
|
|
262
|
-
}): Promise<GetUserResult<DatabaseUser> | undefined>;
|
|
263
|
-
}
|