@atproto/oauth-provider 0.23.1 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/account/account-manager.d.ts +11 -4
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +100 -67
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +8 -6
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/sign-in-data.d.ts +3 -0
- package/dist/account/sign-in-data.d.ts.map +1 -1
- package/dist/account/sign-in-data.js +1 -0
- package/dist/account/sign-in-data.js.map +1 -1
- package/dist/account/sign-up-input.d.ts +3 -0
- package/dist/account/sign-up-input.d.ts.map +1 -1
- package/dist/account/sign-up-input.js +1 -0
- package/dist/account/sign-up-input.js.map +1 -1
- package/dist/errors/invalid-credentials-error.d.ts +11 -12
- package/dist/errors/invalid-credentials-error.d.ts.map +1 -1
- package/dist/errors/invalid-credentials-error.js +11 -12
- package/dist/errors/invalid-credentials-error.js.map +1 -1
- package/dist/lib/util/time.d.ts +1 -0
- package/dist/lib/util/time.d.ts.map +1 -1
- package/dist/lib/util/time.js +3 -0
- package/dist/lib/util/time.js.map +1 -1
- package/dist/oauth-constants.d.ts +1 -1
- package/dist/oauth-constants.d.ts.map +1 -1
- package/dist/oauth-constants.js +2 -2
- package/dist/oauth-constants.js.map +1 -1
- package/dist/oauth-hooks.d.ts +10 -4
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +5 -17
- package/dist/oauth-provider.js.map +1 -1
- package/dist/router/create-api-middleware.d.ts.map +1 -1
- package/dist/router/create-api-middleware.js +12 -35
- package/dist/router/create-api-middleware.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atproto/oauth-provider
|
|
2
2
|
|
|
3
|
+
## 0.24.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#5629](https://github.com/bluesky-social/atproto/pull/5629) [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Always require `did` argument when constructing `InvalidCredentialsError`
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#5629](https://github.com/bluesky-social/atproto/pull/5629) [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Avoid signing users out on code replay
|
|
12
|
+
|
|
13
|
+
- [#5629](https://github.com/bluesky-social/atproto/pull/5629) [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Improve handling of "remember" setting during sign-in and sign-up. Keeps current "remember me" status when user did not explicitly enable/disable it (avoiding sign users out when they are presented with a UI that does not show the "remember me" option)
|
|
14
|
+
|
|
15
|
+
- [#5629](https://github.com/bluesky-social/atproto/pull/5629) [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Better wrap hcaptcha errors
|
|
16
|
+
|
|
17
|
+
- [#5629](https://github.com/bluesky-social/atproto/pull/5629) [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Do not swallow errors thrown during `onSignInFailed`
|
|
18
|
+
- Updated dependencies [[`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706), [`32f8e45`](https://github.com/bluesky-social/atproto/commit/32f8e454f199f4355574e452f660098a55365706)]:
|
|
19
|
+
- @atproto/oauth-provider-ui@0.10.6
|
|
20
|
+
- @atproto/oauth-provider-api@0.10.0
|
|
21
|
+
|
|
3
22
|
## 0.23.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -18,16 +18,23 @@ export declare class AccountManager {
|
|
|
18
18
|
protected processHcaptchaToken(input: SignUpInput, deviceId: DeviceId, deviceMetadata: RequestMetadata): Promise<HcaptchaVerifyResult | undefined>;
|
|
19
19
|
protected enforceInviteCode(input: SignUpInput, _deviceId: DeviceId, _deviceMetadata: RequestMetadata): Promise<string | undefined>;
|
|
20
20
|
protected buildSignupData(input: SignUpInput, deviceId: DeviceId, deviceMetadata: RequestMetadata): Promise<SignUpData>;
|
|
21
|
-
createAccount(deviceId: DeviceId, deviceMetadata: RequestMetadata, input: SignUpInput, clientId?: ClientId): Promise<
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
createAccount(deviceId: DeviceId, deviceMetadata: RequestMetadata, input: SignUpInput, clientId?: ClientId): Promise<{
|
|
22
|
+
account: Account;
|
|
23
|
+
remembered: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
authenticateAccount(deviceId: DeviceId, deviceMetadata: RequestMetadata, data: SignInData, clientId?: ClientId): Promise<{
|
|
26
|
+
account: Account;
|
|
27
|
+
remembered: boolean;
|
|
28
|
+
}>;
|
|
29
|
+
signOut(deviceId: DeviceId, did: Did): Promise<void>;
|
|
30
|
+
protected upsertDeviceAccount(deviceId: DeviceId, did: Did): Promise<void>;
|
|
31
|
+
protected removeDeviceAccount(deviceId: DeviceId, did: Did): Promise<void>;
|
|
24
32
|
getDeviceAccount(deviceId: DeviceId, did: Did): Promise<DeviceAccount>;
|
|
25
33
|
setAuthorizedClient(account: Account, client: Client, data: AuthorizedClientData): Promise<void>;
|
|
26
34
|
getAccount(did: Did): Promise<{
|
|
27
35
|
account: Account;
|
|
28
36
|
authorizedClients: import("./account-store.js").AuthorizedClients;
|
|
29
37
|
}>;
|
|
30
|
-
removeDeviceAccount(deviceId: DeviceId, did: Did): Promise<void>;
|
|
31
38
|
listDeviceAccounts(deviceId: DeviceId): Promise<DeviceAccount[]>;
|
|
32
39
|
listAccountDevices(did: Did): Promise<DeviceAccount[]>;
|
|
33
40
|
resetPasswordRequest(deviceId: DeviceId, deviceMetadata: RequestMetadata, input: ResetPasswordRequestInput): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-manager.d.ts","sourceRoot":"","sources":["../../src/account/account-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAG9E,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,EACzB,aAAa,EACb,2BAA2B,EAC3B,0BAA0B,EAC1B,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EACzB,UAAU,EACV,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAOrD,qBAAa,cAAc;IAMvB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY;IACtC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU;IANtC,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAA;IAC9C,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAA;IAElD,YACE,MAAM,EAAE,qBAAqB,EACV,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACpC,aAAa,EAAE,aAAa,EAM7B;IAED,UAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,eAAe,GAC9B,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"account-manager.d.ts","sourceRoot":"","sources":["../../src/account/account-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,26 +23,22 @@ export class AccountManager {
|
|
|
23
23
|
if (!input.hcaptchaToken) {
|
|
24
24
|
throw new InvalidRequestError('hCaptcha token is required');
|
|
25
25
|
}
|
|
26
|
-
const tokens = await this.hcaptchaClient.buildClientTokens(deviceMetadata.ipAddress, input.handle, deviceMetadata.userAgent);
|
|
27
|
-
const result = await this.hcaptchaClient
|
|
28
|
-
.verify('signup', input.hcaptchaToken, deviceMetadata.ipAddress, tokens)
|
|
29
|
-
.catch((err) => {
|
|
30
|
-
throw InvalidRequestError.from(err, 'hCaptcha verification failed');
|
|
31
|
-
});
|
|
32
|
-
await this.hooks.onHcaptchaResult?.call(null, {
|
|
33
|
-
input,
|
|
34
|
-
deviceId,
|
|
35
|
-
deviceMetadata,
|
|
36
|
-
tokens,
|
|
37
|
-
result,
|
|
38
|
-
});
|
|
39
26
|
try {
|
|
27
|
+
const tokens = await this.hcaptchaClient.buildClientTokens(deviceMetadata.ipAddress, input.handle, deviceMetadata.userAgent);
|
|
28
|
+
const result = await this.hcaptchaClient.verify('signup', input.hcaptchaToken, deviceMetadata.ipAddress, tokens);
|
|
29
|
+
await this.hooks.onHcaptchaResult?.call(null, {
|
|
30
|
+
input,
|
|
31
|
+
deviceId,
|
|
32
|
+
deviceMetadata,
|
|
33
|
+
tokens,
|
|
34
|
+
result,
|
|
35
|
+
});
|
|
40
36
|
this.hcaptchaClient.checkVerifyResult(result, tokens);
|
|
37
|
+
return result;
|
|
41
38
|
}
|
|
42
39
|
catch (err) {
|
|
43
40
|
throw InvalidRequestError.from(err, 'hCaptcha verification failed');
|
|
44
41
|
}
|
|
45
|
-
return result;
|
|
46
42
|
}
|
|
47
43
|
async enforceInviteCode(input, _deviceId, _deviceMetadata) {
|
|
48
44
|
if (!this.inviteCodeRequired) {
|
|
@@ -62,96 +58,136 @@ export class AccountManager {
|
|
|
62
58
|
}
|
|
63
59
|
async createAccount(deviceId, deviceMetadata, input, clientId) {
|
|
64
60
|
return constantTime(BRUTE_FORCE_MITIGATION_DELAY, async () => {
|
|
65
|
-
await this.hooks.onSignUpAttempt
|
|
61
|
+
await callAsync(this.hooks.onSignUpAttempt, {
|
|
66
62
|
input,
|
|
67
63
|
deviceId,
|
|
68
64
|
deviceMetadata,
|
|
69
65
|
clientId,
|
|
70
66
|
});
|
|
71
67
|
const data = await this.buildSignupData(input, deviceId, deviceMetadata);
|
|
72
|
-
const account = await callAsync(
|
|
68
|
+
const account = await callAsync(async () => {
|
|
69
|
+
return this.store.createAccount(data);
|
|
70
|
+
}).catch((err) => {
|
|
73
71
|
throw InvalidRequestError.from(err, 'Account creation failed');
|
|
74
72
|
});
|
|
73
|
+
// @TODO Any error occurring below this point (server error most likely)
|
|
74
|
+
// will not prevent the account from being created, but it will be
|
|
75
|
+
// reported to the caller. We may want to wrap these errors in a way that
|
|
76
|
+
// allows the UI to detect that a sign-up attempt will fail ("account
|
|
77
|
+
// already exists"), and should provide appropriate feedback to the user
|
|
78
|
+
// (eg. show sign-in form?).
|
|
79
|
+
const isOAuthFlow = clientId != null;
|
|
80
|
+
const remembered = input.remember ?? !isOAuthFlow;
|
|
81
|
+
if (remembered) {
|
|
82
|
+
await this.upsertDeviceAccount(deviceId, account.did);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// no need to remove the device account since it was never added (the
|
|
86
|
+
// account was just created).
|
|
87
|
+
}
|
|
75
88
|
try {
|
|
76
|
-
await this.hooks.onSignedUp
|
|
89
|
+
await callAsync(this.hooks.onSignedUp, {
|
|
77
90
|
data,
|
|
78
91
|
account,
|
|
79
92
|
deviceId,
|
|
80
93
|
deviceMetadata,
|
|
81
94
|
clientId,
|
|
82
95
|
});
|
|
83
|
-
return account;
|
|
96
|
+
return { account, remembered };
|
|
84
97
|
}
|
|
85
98
|
catch (err) {
|
|
86
|
-
|
|
99
|
+
// Delete the device account if an error occurred during the hook
|
|
100
|
+
if (remembered) {
|
|
101
|
+
await this.removeDeviceAccount(deviceId, account.did);
|
|
102
|
+
}
|
|
87
103
|
throw InvalidRequestError.from(err, 'The account was successfully created but something went wrong, try signing-in.');
|
|
88
104
|
}
|
|
89
105
|
});
|
|
90
106
|
}
|
|
91
107
|
async authenticateAccount(deviceId, deviceMetadata, data, clientId) {
|
|
92
108
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
109
|
+
// @NOTE If the user did not explicitly specify a "remember" preference,
|
|
110
|
+
// we will use the existence of previously remembered device accounts to
|
|
111
|
+
// determine the default "remember" behavior.
|
|
112
|
+
const deviceAccounts = await this.listDeviceAccounts(deviceId);
|
|
93
113
|
await this.hooks.onSignInAttempt?.call(null, {
|
|
94
114
|
data,
|
|
95
115
|
deviceId,
|
|
96
116
|
deviceMetadata,
|
|
117
|
+
deviceAccounts,
|
|
97
118
|
clientId,
|
|
98
119
|
});
|
|
99
|
-
const account = await callAsync(
|
|
120
|
+
const account = await callAsync(async () => {
|
|
121
|
+
return this.store.authenticateAccount({
|
|
122
|
+
locale: data.locale,
|
|
123
|
+
password: data.password,
|
|
124
|
+
username: data.username,
|
|
125
|
+
emailOtp: data.emailOtp,
|
|
126
|
+
deviceAccounts,
|
|
127
|
+
});
|
|
128
|
+
}).catch(async (error) => {
|
|
100
129
|
// Only notify for credential failures (e.g. unknown identifier, wrong
|
|
101
130
|
// password). Server errors and flows that require an additional factor
|
|
102
|
-
// are not "failed sign-ins"
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const isCredentialsError = err instanceof InvalidCredentialsError;
|
|
117
|
-
const did = isCredentialsError ? (err.did ?? null) : null;
|
|
118
|
-
// Swallow any error from the hook itself so that it does not mask
|
|
119
|
-
// the underlying authentication failure being reported.
|
|
120
|
-
try {
|
|
121
|
-
await this.hooks.onSignInFailed?.call(null, {
|
|
122
|
-
data,
|
|
123
|
-
error: err,
|
|
124
|
-
did,
|
|
125
|
-
deviceId,
|
|
126
|
-
deviceMetadata,
|
|
127
|
-
clientId,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
// noop
|
|
132
|
-
}
|
|
133
|
-
if (isCredentialsError) {
|
|
134
|
-
// Defensively downgrade to a plain InvalidRequestError
|
|
135
|
-
throw new InvalidRequestError(err.error_description);
|
|
136
|
-
}
|
|
131
|
+
// (SecondAuthenticationFactorRequiredError) are not "failed sign-ins"
|
|
132
|
+
// and do not trigger the hook.
|
|
133
|
+
// Stores that throw the more specific `InvalidCredentialsError`
|
|
134
|
+
// can attach the matched subject identifier to distinguish
|
|
135
|
+
// "identifier known, password wrong" from "identifier unknown".
|
|
136
|
+
if (error instanceof InvalidRequestError) {
|
|
137
|
+
await this.hooks.onSignInFailed?.call(null, {
|
|
138
|
+
data,
|
|
139
|
+
error,
|
|
140
|
+
did: error instanceof InvalidCredentialsError ? error.did : null,
|
|
141
|
+
deviceId,
|
|
142
|
+
deviceMetadata,
|
|
143
|
+
clientId,
|
|
144
|
+
});
|
|
137
145
|
}
|
|
138
|
-
throw
|
|
146
|
+
throw error;
|
|
139
147
|
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
const remembered =
|
|
149
|
+
// If the user has explicitly specified a "remember" preference, use it.
|
|
150
|
+
data.remember ??
|
|
151
|
+
// Fall back to checking if the account was previously remembered.
|
|
152
|
+
deviceAccounts.some((da) => da.account.did === account.did);
|
|
153
|
+
if (remembered) {
|
|
154
|
+
await this.upsertDeviceAccount(deviceId, account.did);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// In case the user was already signed in, and signed in again, this
|
|
158
|
+
// time without "remember me", let's sign them off of the device.
|
|
159
|
+
await this.removeDeviceAccount(deviceId, account.did);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
await callAsync(this.hooks.onSignedIn, {
|
|
163
|
+
data,
|
|
164
|
+
account,
|
|
165
|
+
remembered,
|
|
166
|
+
deviceId,
|
|
167
|
+
deviceMetadata,
|
|
168
|
+
clientId,
|
|
169
|
+
});
|
|
170
|
+
return { account, remembered };
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
if (remembered) {
|
|
174
|
+
await this.removeDeviceAccount(deviceId, account.did);
|
|
175
|
+
}
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
148
178
|
}).catch((err) => {
|
|
149
179
|
throw InvalidRequestError.from(err, 'Unable to sign-in due to an unexpected server error');
|
|
150
180
|
});
|
|
151
181
|
}
|
|
182
|
+
async signOut(deviceId, did) {
|
|
183
|
+
await this.removeDeviceAccount(deviceId, did);
|
|
184
|
+
}
|
|
152
185
|
async upsertDeviceAccount(deviceId, did) {
|
|
153
186
|
await this.store.upsertDeviceAccount(deviceId, did);
|
|
154
187
|
}
|
|
188
|
+
async removeDeviceAccount(deviceId, did) {
|
|
189
|
+
return this.store.removeDeviceAccount(deviceId, did);
|
|
190
|
+
}
|
|
155
191
|
async getDeviceAccount(deviceId, did) {
|
|
156
192
|
const deviceAccount = await this.store.getDeviceAccount(deviceId, did);
|
|
157
193
|
if (!deviceAccount)
|
|
@@ -167,9 +203,6 @@ export class AccountManager {
|
|
|
167
203
|
async getAccount(did) {
|
|
168
204
|
return this.store.getAccount(did);
|
|
169
205
|
}
|
|
170
|
-
async removeDeviceAccount(deviceId, did) {
|
|
171
|
-
return this.store.removeDeviceAccount(deviceId, did);
|
|
172
|
-
}
|
|
173
206
|
async listDeviceAccounts(deviceId) {
|
|
174
207
|
const deviceAccounts = await this.store.listDeviceAccounts({
|
|
175
208
|
deviceId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-manager.js","sourceRoot":"","sources":["../../src/account/account-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Did } from '@atproto/did'\nimport {\n type OAuthIssuerIdentifier,\n isOAuthClientIdLoopback,\n} from '@atproto/oauth-types'\nimport type { ClientId } from '../client/client-id.js'\nimport type { Client } from '../client/client.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport { InvalidCredentialsError } from '../errors/invalid-credentials-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { HCaptchaClient, type HcaptchaVerifyResult } from '../lib/hcaptcha.js'\nimport { callAsync } from '../lib/util/function.js'\nimport { constantTime } from '../lib/util/time.js'\nimport type { OAuthHooks, RequestMetadata } from '../oauth-hooks.js'\nimport type { Customization } from '../oauth-provider.js'\nimport type {\n Account,\n AccountStore,\n AuthorizedClientData,\n DeleteAccountConfirmInput,\n DeleteAccountRequestInput,\n DeviceAccount,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n HandleString,\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n UpdateEmailConfirmInput,\n UpdateEmailRequestInput,\n UpdateHandleData,\n VerifyEmailConfirmInput,\n VerifyEmailRequestInput,\n} from './account-store.js'\nimport type { SignInData } from './sign-in-data.js'\nimport type { SignUpInput } from './sign-up-input.js'\n\nconst TIMING_ATTACK_MITIGATION_DELAY = 400\nconst BRUTE_FORCE_MITIGATION_DELAY = 300\n\n// @TODO Add rate limit to all the OAuth routes.\n\nexport class AccountManager {\n protected readonly inviteCodeRequired: boolean\n protected readonly hcaptchaClient?: HCaptchaClient\n\n constructor(\n issuer: OAuthIssuerIdentifier,\n protected readonly store: AccountStore,\n protected readonly hooks: OAuthHooks,\n customization: Customization,\n ) {\n this.inviteCodeRequired = customization.inviteCodeRequired !== false\n this.hcaptchaClient = customization.hcaptcha\n ? new HCaptchaClient(new URL(issuer).hostname, customization.hcaptcha)\n : undefined\n }\n\n protected async processHcaptchaToken(\n input: SignUpInput,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n ): Promise<HcaptchaVerifyResult | undefined> {\n if (!this.hcaptchaClient) {\n return undefined\n }\n\n if (!input.hcaptchaToken) {\n throw new InvalidRequestError('hCaptcha token is required')\n }\n\n const tokens = await this.hcaptchaClient.buildClientTokens(\n deviceMetadata.ipAddress,\n input.handle,\n deviceMetadata.userAgent,\n )\n\n const result = await this.hcaptchaClient\n .verify('signup', input.hcaptchaToken, deviceMetadata.ipAddress, tokens)\n .catch((err) => {\n throw InvalidRequestError.from(err, 'hCaptcha verification failed')\n })\n\n await this.hooks.onHcaptchaResult?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n tokens,\n result,\n })\n\n try {\n this.hcaptchaClient.checkVerifyResult(result, tokens)\n } catch (err) {\n throw InvalidRequestError.from(err, 'hCaptcha verification failed')\n }\n\n return result\n }\n\n protected async enforceInviteCode(\n input: SignUpInput,\n _deviceId: DeviceId,\n _deviceMetadata: RequestMetadata,\n ): Promise<string | undefined> {\n if (!this.inviteCodeRequired) {\n return undefined\n }\n\n if (!input.inviteCode) {\n throw new InvalidRequestError('Invite code is required')\n }\n\n return input.inviteCode\n }\n\n protected async buildSignupData(\n input: SignUpInput,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n ): Promise<SignUpData> {\n const [hcaptchaResult, inviteCode] = await Promise.all([\n this.processHcaptchaToken(input, deviceId, deviceMetadata),\n this.enforceInviteCode(input, deviceId, deviceMetadata),\n ])\n\n return { ...input, hcaptchaResult, inviteCode }\n }\n\n public async createAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: SignUpInput,\n clientId?: ClientId,\n ): Promise<Account> {\n return constantTime(BRUTE_FORCE_MITIGATION_DELAY, async () => {\n await this.hooks.onSignUpAttempt?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n const data = await this.buildSignupData(input, deviceId, deviceMetadata)\n\n const account = await callAsync(() =>\n this.store.createAccount(data),\n ).catch((err) => {\n throw InvalidRequestError.from(err, 'Account creation failed')\n })\n\n try {\n await this.hooks.onSignedUp?.call(null, {\n data,\n account,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n return account\n } catch (err) {\n await this.removeDeviceAccount(deviceId, account.did)\n\n throw InvalidRequestError.from(\n err,\n 'The account was successfully created but something went wrong, try signing-in.',\n )\n }\n })\n }\n\n public async authenticateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n data: SignInData,\n clientId?: ClientId,\n ): Promise<Account> {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n await this.hooks.onSignInAttempt?.call(null, {\n data,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n const account = await callAsync(() =>\n this.store.authenticateAccount(data),\n ).catch(async (err) => {\n // Only notify for credential failures (e.g. unknown identifier, wrong\n // password). Server errors and flows that require an additional factor\n // are not \"failed sign-ins\" and do not trigger the hook.\n //\n // @NOTE That exclusion rests on the error hierarchy rather than an\n // explicit guard: `SecondAuthenticationFactorRequiredError` extends\n // `OAuthError` directly, so it misses this branch and falls through to\n // the rethrow below. Re-parenting it under `InvalidRequestError` would\n // silently start reporting second-factor challenges as failed\n // sign-ins.\n if (err instanceof InvalidRequestError) {\n // Stores that throw the more specific `InvalidCredentialsError`\n // can attach the matched subject identifier to distinguish\n // \"identifier known, password wrong\" from \"identifier unknown\".\n // This information is only exposed to the hook and is never\n // surfaced to the client.\n const isCredentialsError = err instanceof InvalidCredentialsError\n const did = isCredentialsError ? (err.did ?? null) : null\n\n // Swallow any error from the hook itself so that it does not mask\n // the underlying authentication failure being reported.\n try {\n await this.hooks.onSignInFailed?.call(null, {\n data,\n error: err,\n did,\n deviceId,\n deviceMetadata,\n clientId,\n })\n } catch {\n // noop\n }\n\n if (isCredentialsError) {\n // Defensively downgrade to a plain InvalidRequestError\n throw new InvalidRequestError(err.error_description)\n }\n }\n\n throw err\n })\n\n await this.hooks.onSignedIn?.call(null, {\n data,\n account,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n return account\n }).catch((err) => {\n throw InvalidRequestError.from(\n err,\n 'Unable to sign-in due to an unexpected server error',\n )\n })\n }\n\n public async upsertDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Promise<void> {\n await this.store.upsertDeviceAccount(deviceId, did)\n }\n\n public async getDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Promise<DeviceAccount> {\n const deviceAccount = await this.store.getDeviceAccount(deviceId, did)\n if (!deviceAccount) throw new InvalidRequestError(`Account not found`)\n\n return deviceAccount\n }\n\n public async setAuthorizedClient(\n account: Account,\n client: Client,\n data: AuthorizedClientData,\n ): Promise<void> {\n // \"Loopback\" clients are not distinguishable from one another.\n if (isOAuthClientIdLoopback(client.id)) return\n\n await this.store.setAuthorizedClient(account.did, client.id, data)\n }\n\n public async getAccount(did: Did) {\n return this.store.getAccount(did)\n }\n\n public async removeDeviceAccount(deviceId: DeviceId, did: Did) {\n return this.store.removeDeviceAccount(deviceId, did)\n }\n\n public async listDeviceAccounts(\n deviceId: DeviceId,\n ): Promise<DeviceAccount[]> {\n const deviceAccounts = await this.store.listDeviceAccounts({\n deviceId,\n })\n\n return deviceAccounts // Fool proof\n .filter((deviceAccount) => deviceAccount.deviceId === deviceId)\n }\n\n public async listAccountDevices(did: Did): Promise<DeviceAccount[]> {\n const deviceAccounts = await this.store.listDeviceAccounts({\n did,\n })\n\n return deviceAccounts // Fool proof\n .filter((deviceAccount) => deviceAccount.account.did === did)\n }\n\n public async resetPasswordRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: ResetPasswordRequestInput,\n ) {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n await this.hooks.onResetPasswordRequest?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n })\n\n const account = await this.store.resetPasswordRequest(input)\n\n // @NOTE Do not throw here, to prevent user enumeration\n\n await this.hooks.onResetPasswordRequested?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n account,\n })\n })\n }\n\n public async resetPasswordConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: ResetPasswordConfirmInput,\n ) {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n await this.hooks.onResetPasswordConfirm?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n })\n\n const account = await this.store.resetPasswordConfirm(input)\n\n if (!account) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onResetPasswordConfirmed?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n account,\n })\n\n return account\n })\n }\n\n public async verifyHandleAvailability(handle: HandleString): Promise<void> {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n return this.store.verifyHandleAvailability(handle)\n })\n }\n\n public async updateEmailRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateEmailRequestInput,\n account: Account,\n ): Promise<{ tokenRequired: boolean }> {\n await this.hooks.onChangeEmailRequest?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const { tokenRequired } = await this.store.updateEmailRequest(input)\n\n await this.hooks.onChangeEmailRequested?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n return { tokenRequired: tokenRequired === true }\n }\n\n public async updateEmailConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateEmailConfirmInput,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onUpdateEmailConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.updateEmailConfirm(input)\n\n if (!updatedAccount) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onUpdateEmailConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n prevAccount: account,\n })\n\n return updatedAccount\n }\n\n public async verifyEmailRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: VerifyEmailRequestInput,\n account: Account,\n ): Promise<void> {\n await this.hooks.onVerifyEmailRequest?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n\n await this.store.verifyEmailRequest(input)\n\n await this.hooks.onVerifyEmailRequested?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n }\n\n public async verifyEmailConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: VerifyEmailConfirmInput,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onVerifyEmailConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n\n const updatedAccount = await this.store.verifyEmailConfirm(input)\n\n if (!updatedAccount) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onVerifyEmailConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n input,\n })\n\n return updatedAccount\n }\n\n public async enableEmailAuthFactor(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: EnableEmailAuthFactorInput,\n account: Account,\n ): Promise<Account> {\n // Already enabled\n if (account.emailAuthFactor) return account\n\n await this.hooks.onEnableEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.enableEmailAuthFactor(input)\n\n if (updatedAccount.emailAuthFactor !== account.emailAuthFactor) {\n await this.hooks.onEnabledEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n }\n\n return updatedAccount\n }\n\n public async disableEmailAuthFactor(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DisableEmailAuthFactorInput,\n account: Account,\n ): Promise<Account> {\n // Already disabled\n if (!account.emailAuthFactor) return account\n\n await this.hooks.onDisableEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.disableEmailAuthFactor(input)\n\n if (updatedAccount.emailAuthFactor !== account.emailAuthFactor) {\n await this.hooks.onDisabledEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n }\n\n return updatedAccount\n }\n\n public async updateHandle(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateHandleData,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onUpdateHandle?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.updateHandle(input)\n\n await this.hooks.onUpdatedHandle?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async deactivateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onDeactivateAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n const updatedAccount = await callAsync(() =>\n this.store.deactivateAccount({\n did: account.did,\n // @TODO support setting this from the UI/API\n deleteAfter: undefined,\n }),\n ).catch((err) => {\n throw InvalidRequestError.from(err, 'Account deactivation failed')\n })\n\n await this.hooks.onDeactivatedAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async reactivateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onReactivateAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n const updatedAccount = await callAsync(() =>\n this.store.reactivateAccount({ did: account.did }),\n ).catch((err) => {\n throw InvalidRequestError.from(err, 'Account reactivation failed')\n })\n\n await this.hooks.onReactivatedAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async deleteAccountRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DeleteAccountRequestInput,\n account: Account,\n ): Promise<void> {\n await this.hooks.onDeleteAccountRequest?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n await this.store.deleteAccountRequest(input)\n\n await this.hooks.onDeleteAccountRequested?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n }\n\n public async deleteAccountConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DeleteAccountConfirmInput,\n account: Account,\n ): Promise<void> {\n return constantTime(BRUTE_FORCE_MITIGATION_DELAY, async () => {\n await this.hooks.onDeleteAccountConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n await callAsync(() => this.store.deleteAccountConfirm(input)).catch(\n (err) => {\n throw InvalidRequestError.from(err, 'Account deletion failed')\n },\n )\n\n await this.hooks.onDeleteAccountConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"account-manager.js","sourceRoot":"","sources":["../../src/account/account-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,uBAAuB,GACxB,MAAM,sBAAsB,CAAA;AAI7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAA;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,EAAE,cAAc,EAA6B,MAAM,oBAAoB,CAAA;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAyBlD,MAAM,8BAA8B,GAAG,GAAG,CAAA;AAC1C,MAAM,4BAA4B,GAAG,GAAG,CAAA;AAExC,gDAAgD;AAEhD,MAAM,OAAO,cAAc;IAIzB,YACE,MAA6B,EACV,KAAmB,EACnB,KAAiB,EACpC,aAA4B;qBAFT,KAAK;qBACL,KAAK;QAGxB,IAAI,CAAC,kBAAkB,GAAG,aAAa,CAAC,kBAAkB,KAAK,KAAK,CAAA;QACpE,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC,QAAQ;YAC1C,CAAC,CAAC,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;YACtE,CAAC,CAAC,SAAS,CAAA;IACf,CAAC;IAES,KAAK,CAAC,oBAAoB,CAClC,KAAkB,EAClB,QAAkB,EAClB,cAA+B;QAE/B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,IAAI,mBAAmB,CAAC,4BAA4B,CAAC,CAAA;QAC7D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,iBAAiB,CACxD,cAAc,CAAC,SAAS,EACxB,KAAK,CAAC,MAAM,EACZ,cAAc,CAAC,SAAS,CACzB,CAAA;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAC7C,QAAQ,EACR,KAAK,CAAC,aAAa,EACnB,cAAc,CAAC,SAAS,EACxB,MAAM,CACP,CAAA;YAED,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE;gBAC5C,KAAK;gBACL,QAAQ;gBACR,cAAc;gBACd,MAAM;gBACN,MAAM;aACP,CAAC,CAAA;YAEF,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAErD,OAAO,MAAM,CAAA;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,8BAA8B,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IAES,KAAK,CAAC,iBAAiB,CAC/B,KAAkB,EAClB,SAAmB,EACnB,eAAgC;QAEhC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,MAAM,IAAI,mBAAmB,CAAC,yBAAyB,CAAC,CAAA;QAC1D,CAAC;QAED,OAAO,KAAK,CAAC,UAAU,CAAA;IACzB,CAAC;IAES,KAAK,CAAC,eAAe,CAC7B,KAAkB,EAClB,QAAkB,EAClB,cAA+B;QAE/B,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACrD,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,CAAC;YAC1D,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,CAAC;SACxD,CAAC,CAAA;QAEF,OAAO,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,CAAA;IACjD,CAAC;IAEM,KAAK,CAAC,aAAa,CACxB,QAAkB,EAClB,cAA+B,EAC/B,KAAkB,EAClB,QAAmB;QAEnB,OAAO,YAAY,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;gBAC1C,KAAK;gBACL,QAAQ;gBACR,cAAc;gBACd,QAAQ;aACT,CAAC,CAAA;YAEF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAA;YAExE,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,IAAI,EAAE;gBACzC,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;YACvC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACf,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAA;YAChE,CAAC,CAAC,CAAA;YAEF,wEAAwE;YACxE,kEAAkE;YAClE,yEAAyE;YACzE,qEAAqE;YACrE,wEAAwE;YACxE,4BAA4B;YAE5B,MAAM,WAAW,GAAG,QAAQ,IAAI,IAAI,CAAA;YACpC,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAA;YAEjD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;YACvD,CAAC;iBAAM,CAAC;gBACN,qEAAqE;gBACrE,6BAA6B;YAC/B,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;oBACrC,IAAI;oBACJ,OAAO;oBACP,QAAQ;oBACR,cAAc;oBACd,QAAQ;iBACT,CAAC,CAAA;gBAEF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAA;YAChC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,iEAAiE;gBACjE,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;gBACvD,CAAC;gBAED,MAAM,mBAAmB,CAAC,IAAI,CAC5B,GAAG,EACH,gFAAgF,CACjF,CAAA;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC9B,QAAkB,EAClB,cAA+B,EAC/B,IAAgB,EAChB,QAAmB;QAEnB,OAAO,YAAY,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC7D,wEAAwE;YACxE,wEAAwE;YACxE,6CAA6C;YAC7C,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;YAE9D,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE;gBAC3C,IAAI;gBACJ,QAAQ;gBACR,cAAc;gBACd,cAAc;gBACd,QAAQ;aACT,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,IAAI,EAAE;gBACzC,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC;oBACpC,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,cAAc;iBACf,CAAC,CAAA;YACJ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACvB,sEAAsE;gBACtE,uEAAuE;gBACvE,sEAAsE;gBACtE,+BAA+B;gBAE/B,gEAAgE;gBAChE,2DAA2D;gBAC3D,gEAAgE;gBAChE,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;oBACzC,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE;wBAC1C,IAAI;wBACJ,KAAK;wBACL,GAAG,EAAE,KAAK,YAAY,uBAAuB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;wBAChE,QAAQ;wBACR,cAAc;wBACd,QAAQ;qBACT,CAAC,CAAA;gBACJ,CAAC;gBAED,MAAM,KAAK,CAAA;YACb,CAAC,CAAC,CAAA;YAEF,MAAM,UAAU;YACd,wEAAwE;YACxE,IAAI,CAAC,QAAQ;gBACb,kEAAkE;gBAClE,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;YAE7D,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;YACvD,CAAC;iBAAM,CAAC;gBACN,oEAAoE;gBACpE,iEAAiE;gBACjE,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;YACvD,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;oBACrC,IAAI;oBACJ,OAAO;oBACP,UAAU;oBACV,QAAQ;oBACR,cAAc;oBACd,QAAQ;iBACT,CAAC,CAAA;gBAEF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAA;YAChC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;gBACvD,CAAC;gBAED,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACf,MAAM,mBAAmB,CAAC,IAAI,CAC5B,GAAG,EACH,qDAAqD,CACtD,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,QAAkB,EAAE,GAAQ;QAC/C,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;IAC/C,CAAC;IAES,KAAK,CAAC,mBAAmB,CACjC,QAAkB,EAClB,GAAQ;QAER,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;IACrD,CAAC;IAES,KAAK,CAAC,mBAAmB,CAAC,QAAkB,EAAE,GAAQ;QAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;IAEM,KAAK,CAAC,gBAAgB,CAC3B,QAAkB,EAClB,GAAQ;QAER,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;QACtE,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,CAAC,CAAA;QAEtE,OAAO,aAAa,CAAA;IACtB,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAC9B,OAAgB,EAChB,MAAc,EACd,IAA0B;QAE1B,+DAA+D;QAC/D,IAAI,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,OAAM;QAE9C,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;IACpE,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,GAAQ;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;IACnC,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,QAAkB;QAElB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC;YACzD,QAAQ;SACT,CAAC,CAAA;QAEF,OAAO,cAAc,CAAC,aAAa;aAChC,MAAM,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAA;IACnE,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAAC,GAAQ;QACtC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC;YACzD,GAAG;SACJ,CAAC,CAAA;QAEF,OAAO,cAAc,CAAC,aAAa;aAChC,MAAM,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;IACjE,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,QAAkB,EAClB,cAA+B,EAC/B,KAAgC;QAEhC,OAAO,YAAY,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;gBAClD,KAAK;gBACL,QAAQ;gBACR,cAAc;aACf,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;YAE5D,uDAAuD;YAEvD,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;gBACpD,KAAK;gBACL,QAAQ;gBACR,cAAc;gBACd,OAAO;aACR,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,QAAkB,EAClB,cAA+B,EAC/B,KAAgC;QAEhC,OAAO,YAAY,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;gBAClD,KAAK;gBACL,QAAQ;gBACR,cAAc;aACf,CAAC,CAAA;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;YAE5D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,mBAAmB,CAAC,eAAe,CAAC,CAAA;YAChD,CAAC;YAED,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;gBACpD,KAAK;gBACL,QAAQ;gBACR,cAAc;gBACd,OAAO;aACR,CAAC,CAAA;YAEF,OAAO,OAAO,CAAA;QAChB,CAAC,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,wBAAwB,CAAC,MAAoB;QACxD,OAAO,YAAY,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAA;QACpD,CAAC,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,QAAkB,EAClB,cAA+B,EAC/B,KAA8B,EAC9B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QAEpE,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,OAAO,EAAE,aAAa,EAAE,aAAa,KAAK,IAAI,EAAE,CAAA;IAClD,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,QAAkB,EAClB,cAA+B,EAC/B,KAA8B,EAC9B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QAEjE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,mBAAmB,CAAC,eAAe,CAAC,CAAA;QAChD,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO,EAAE,cAAc;YACvB,WAAW,EAAE,OAAO;SACrB,CAAC,CAAA;QAEF,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,QAAkB,EAClB,cAA+B,EAC/B,KAA8B,EAC9B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,OAAO;YACP,KAAK;SACN,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QAE1C,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,QAAQ;YACR,cAAc;YACd,OAAO;YACP,KAAK;SACN,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,QAAkB,EAClB,cAA+B,EAC/B,KAA8B,EAC9B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,OAAO;YACP,KAAK;SACN,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QAEjE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,mBAAmB,CAAC,eAAe,CAAC,CAAA;QAChD,CAAC;QAED,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,QAAQ;YACR,cAAc;YACd,OAAO,EAAE,cAAc;YACvB,KAAK;SACN,CAAC,CAAA;QAEF,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAChC,QAAkB,EAClB,cAA+B,EAC/B,KAAiC,EACjC,OAAgB;QAEhB,kBAAkB;QAClB,IAAI,OAAO,CAAC,eAAe;YAAE,OAAO,OAAO,CAAA;QAE3C,MAAM,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAI,EAAE;YACnD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAA;QAEpE,IAAI,cAAc,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;YAC/D,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;gBACpD,QAAQ;gBACR,cAAc;gBACd,KAAK;gBACL,OAAO,EAAE,cAAc;aACxB,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,sBAAsB,CACjC,QAAkB,EAClB,cAA+B,EAC/B,KAAkC,EAClC,OAAgB;QAEhB,mBAAmB;QACnB,IAAI,CAAC,OAAO,CAAC,eAAe;YAAE,OAAO,OAAO,CAAA;QAE5C,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;YACpD,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAA;QAErE,IAAI,cAAc,CAAC,eAAe,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;YAC/D,MAAM,IAAI,CAAC,KAAK,CAAC,yBAAyB,EAAE,IAAI,CAAC,IAAI,EAAE;gBACrD,QAAQ;gBACR,cAAc;gBACd,KAAK;gBACL,OAAO,EAAE,cAAc;aACxB,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,YAAY,CACvB,QAAkB,EAClB,cAA+B,EAC/B,KAAuB,EACvB,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE;YAC1C,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAE3D,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE;YAC3C,QAAQ;YACR,cAAc;YACd,KAAK;YACL,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAC5B,QAAkB,EAClB,cAA+B,EAC/B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,IAAI,CAAC,IAAI,EAAE;YAC/C,QAAQ;YACR,cAAc;YACd,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAC1C,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,6CAA6C;YAC7C,WAAW,EAAE,SAAS;SACvB,CAAC,CACH,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAC5B,QAAkB,EAClB,cAA+B,EAC/B,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,IAAI,CAAC,IAAI,EAAE;YAC/C,QAAQ;YACR,cAAc;YACd,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAC1C,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CACnD,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,6BAA6B,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,EAAE;YAChD,QAAQ;YACR,cAAc;YACd,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,OAAO,cAAc,CAAA;IACvB,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,QAAkB,EAClB,cAA+B,EAC/B,KAAgC,EAChC,OAAgB;QAEhB,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;YAClD,QAAQ;YACR,cAAc;YACd,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAA;QAE5C,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;YACpD,QAAQ;YACR,cAAc;YACd,OAAO;SACR,CAAC,CAAA;IACJ,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAC/B,QAAkB,EAClB,cAA+B,EAC/B,KAAgC,EAChC,OAAgB;QAEhB,OAAO,YAAY,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,EAAE;gBAClD,QAAQ;gBACR,cAAc;gBACd,OAAO;aACR,CAAC,CAAA;YAEF,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CACjE,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAA;YAChE,CAAC,CACF,CAAA;YAED,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,EAAE;gBACpD,QAAQ;gBACR,cAAc;gBACd,OAAO;gBACP,KAAK;aACN,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF","sourcesContent":["import type { Did } from '@atproto/did'\nimport {\n type OAuthIssuerIdentifier,\n isOAuthClientIdLoopback,\n} from '@atproto/oauth-types'\nimport type { ClientId } from '../client/client-id.js'\nimport type { Client } from '../client/client.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport { InvalidCredentialsError } from '../errors/invalid-credentials-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { HCaptchaClient, type HcaptchaVerifyResult } from '../lib/hcaptcha.js'\nimport { callAsync } from '../lib/util/function.js'\nimport { constantTime } from '../lib/util/time.js'\nimport type { OAuthHooks, RequestMetadata } from '../oauth-hooks.js'\nimport type { Customization } from '../oauth-provider.js'\nimport type {\n Account,\n AccountStore,\n AuthorizedClientData,\n DeleteAccountConfirmInput,\n DeleteAccountRequestInput,\n DeviceAccount,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n HandleString,\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n UpdateEmailConfirmInput,\n UpdateEmailRequestInput,\n UpdateHandleData,\n VerifyEmailConfirmInput,\n VerifyEmailRequestInput,\n} from './account-store.js'\nimport type { SignInData } from './sign-in-data.js'\nimport type { SignUpInput } from './sign-up-input.js'\n\nconst TIMING_ATTACK_MITIGATION_DELAY = 400\nconst BRUTE_FORCE_MITIGATION_DELAY = 300\n\n// @TODO Add rate limit to all the OAuth routes.\n\nexport class AccountManager {\n protected readonly inviteCodeRequired: boolean\n protected readonly hcaptchaClient?: HCaptchaClient\n\n constructor(\n issuer: OAuthIssuerIdentifier,\n protected readonly store: AccountStore,\n protected readonly hooks: OAuthHooks,\n customization: Customization,\n ) {\n this.inviteCodeRequired = customization.inviteCodeRequired !== false\n this.hcaptchaClient = customization.hcaptcha\n ? new HCaptchaClient(new URL(issuer).hostname, customization.hcaptcha)\n : undefined\n }\n\n protected async processHcaptchaToken(\n input: SignUpInput,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n ): Promise<HcaptchaVerifyResult | undefined> {\n if (!this.hcaptchaClient) {\n return undefined\n }\n\n if (!input.hcaptchaToken) {\n throw new InvalidRequestError('hCaptcha token is required')\n }\n\n try {\n const tokens = await this.hcaptchaClient.buildClientTokens(\n deviceMetadata.ipAddress,\n input.handle,\n deviceMetadata.userAgent,\n )\n\n const result = await this.hcaptchaClient.verify(\n 'signup',\n input.hcaptchaToken,\n deviceMetadata.ipAddress,\n tokens,\n )\n\n await this.hooks.onHcaptchaResult?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n tokens,\n result,\n })\n\n this.hcaptchaClient.checkVerifyResult(result, tokens)\n\n return result\n } catch (err) {\n throw InvalidRequestError.from(err, 'hCaptcha verification failed')\n }\n }\n\n protected async enforceInviteCode(\n input: SignUpInput,\n _deviceId: DeviceId,\n _deviceMetadata: RequestMetadata,\n ): Promise<string | undefined> {\n if (!this.inviteCodeRequired) {\n return undefined\n }\n\n if (!input.inviteCode) {\n throw new InvalidRequestError('Invite code is required')\n }\n\n return input.inviteCode\n }\n\n protected async buildSignupData(\n input: SignUpInput,\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n ): Promise<SignUpData> {\n const [hcaptchaResult, inviteCode] = await Promise.all([\n this.processHcaptchaToken(input, deviceId, deviceMetadata),\n this.enforceInviteCode(input, deviceId, deviceMetadata),\n ])\n\n return { ...input, hcaptchaResult, inviteCode }\n }\n\n public async createAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: SignUpInput,\n clientId?: ClientId,\n ): Promise<{ account: Account; remembered: boolean }> {\n return constantTime(BRUTE_FORCE_MITIGATION_DELAY, async () => {\n await callAsync(this.hooks.onSignUpAttempt, {\n input,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n const data = await this.buildSignupData(input, deviceId, deviceMetadata)\n\n const account = await callAsync(async () => {\n return this.store.createAccount(data)\n }).catch((err) => {\n throw InvalidRequestError.from(err, 'Account creation failed')\n })\n\n // @TODO Any error occurring below this point (server error most likely)\n // will not prevent the account from being created, but it will be\n // reported to the caller. We may want to wrap these errors in a way that\n // allows the UI to detect that a sign-up attempt will fail (\"account\n // already exists\"), and should provide appropriate feedback to the user\n // (eg. show sign-in form?).\n\n const isOAuthFlow = clientId != null\n const remembered = input.remember ?? !isOAuthFlow\n\n if (remembered) {\n await this.upsertDeviceAccount(deviceId, account.did)\n } else {\n // no need to remove the device account since it was never added (the\n // account was just created).\n }\n\n try {\n await callAsync(this.hooks.onSignedUp, {\n data,\n account,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n return { account, remembered }\n } catch (err) {\n // Delete the device account if an error occurred during the hook\n if (remembered) {\n await this.removeDeviceAccount(deviceId, account.did)\n }\n\n throw InvalidRequestError.from(\n err,\n 'The account was successfully created but something went wrong, try signing-in.',\n )\n }\n })\n }\n\n public async authenticateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n data: SignInData,\n clientId?: ClientId,\n ): Promise<{ account: Account; remembered: boolean }> {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n // @NOTE If the user did not explicitly specify a \"remember\" preference,\n // we will use the existence of previously remembered device accounts to\n // determine the default \"remember\" behavior.\n const deviceAccounts = await this.listDeviceAccounts(deviceId)\n\n await this.hooks.onSignInAttempt?.call(null, {\n data,\n deviceId,\n deviceMetadata,\n deviceAccounts,\n clientId,\n })\n\n const account = await callAsync(async () => {\n return this.store.authenticateAccount({\n locale: data.locale,\n password: data.password,\n username: data.username,\n emailOtp: data.emailOtp,\n deviceAccounts,\n })\n }).catch(async (error) => {\n // Only notify for credential failures (e.g. unknown identifier, wrong\n // password). Server errors and flows that require an additional factor\n // (SecondAuthenticationFactorRequiredError) are not \"failed sign-ins\"\n // and do not trigger the hook.\n\n // Stores that throw the more specific `InvalidCredentialsError`\n // can attach the matched subject identifier to distinguish\n // \"identifier known, password wrong\" from \"identifier unknown\".\n if (error instanceof InvalidRequestError) {\n await this.hooks.onSignInFailed?.call(null, {\n data,\n error,\n did: error instanceof InvalidCredentialsError ? error.did : null,\n deviceId,\n deviceMetadata,\n clientId,\n })\n }\n\n throw error\n })\n\n const remembered =\n // If the user has explicitly specified a \"remember\" preference, use it.\n data.remember ??\n // Fall back to checking if the account was previously remembered.\n deviceAccounts.some((da) => da.account.did === account.did)\n\n if (remembered) {\n await this.upsertDeviceAccount(deviceId, account.did)\n } else {\n // In case the user was already signed in, and signed in again, this\n // time without \"remember me\", let's sign them off of the device.\n await this.removeDeviceAccount(deviceId, account.did)\n }\n\n try {\n await callAsync(this.hooks.onSignedIn, {\n data,\n account,\n remembered,\n deviceId,\n deviceMetadata,\n clientId,\n })\n\n return { account, remembered }\n } catch (err) {\n if (remembered) {\n await this.removeDeviceAccount(deviceId, account.did)\n }\n\n throw err\n }\n }).catch((err) => {\n throw InvalidRequestError.from(\n err,\n 'Unable to sign-in due to an unexpected server error',\n )\n })\n }\n\n public async signOut(deviceId: DeviceId, did: Did) {\n await this.removeDeviceAccount(deviceId, did)\n }\n\n protected async upsertDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Promise<void> {\n await this.store.upsertDeviceAccount(deviceId, did)\n }\n\n protected async removeDeviceAccount(deviceId: DeviceId, did: Did) {\n return this.store.removeDeviceAccount(deviceId, did)\n }\n\n public async getDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Promise<DeviceAccount> {\n const deviceAccount = await this.store.getDeviceAccount(deviceId, did)\n if (!deviceAccount) throw new InvalidRequestError(`Account not found`)\n\n return deviceAccount\n }\n\n public async setAuthorizedClient(\n account: Account,\n client: Client,\n data: AuthorizedClientData,\n ): Promise<void> {\n // \"Loopback\" clients are not distinguishable from one another.\n if (isOAuthClientIdLoopback(client.id)) return\n\n await this.store.setAuthorizedClient(account.did, client.id, data)\n }\n\n public async getAccount(did: Did) {\n return this.store.getAccount(did)\n }\n\n public async listDeviceAccounts(\n deviceId: DeviceId,\n ): Promise<DeviceAccount[]> {\n const deviceAccounts = await this.store.listDeviceAccounts({\n deviceId,\n })\n\n return deviceAccounts // Fool proof\n .filter((deviceAccount) => deviceAccount.deviceId === deviceId)\n }\n\n public async listAccountDevices(did: Did): Promise<DeviceAccount[]> {\n const deviceAccounts = await this.store.listDeviceAccounts({\n did,\n })\n\n return deviceAccounts // Fool proof\n .filter((deviceAccount) => deviceAccount.account.did === did)\n }\n\n public async resetPasswordRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: ResetPasswordRequestInput,\n ) {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n await this.hooks.onResetPasswordRequest?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n })\n\n const account = await this.store.resetPasswordRequest(input)\n\n // @NOTE Do not throw here, to prevent user enumeration\n\n await this.hooks.onResetPasswordRequested?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n account,\n })\n })\n }\n\n public async resetPasswordConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: ResetPasswordConfirmInput,\n ) {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n await this.hooks.onResetPasswordConfirm?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n })\n\n const account = await this.store.resetPasswordConfirm(input)\n\n if (!account) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onResetPasswordConfirmed?.call(null, {\n input,\n deviceId,\n deviceMetadata,\n account,\n })\n\n return account\n })\n }\n\n public async verifyHandleAvailability(handle: HandleString): Promise<void> {\n return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {\n return this.store.verifyHandleAvailability(handle)\n })\n }\n\n public async updateEmailRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateEmailRequestInput,\n account: Account,\n ): Promise<{ tokenRequired: boolean }> {\n await this.hooks.onChangeEmailRequest?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const { tokenRequired } = await this.store.updateEmailRequest(input)\n\n await this.hooks.onChangeEmailRequested?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n return { tokenRequired: tokenRequired === true }\n }\n\n public async updateEmailConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateEmailConfirmInput,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onUpdateEmailConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.updateEmailConfirm(input)\n\n if (!updatedAccount) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onUpdateEmailConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n prevAccount: account,\n })\n\n return updatedAccount\n }\n\n public async verifyEmailRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: VerifyEmailRequestInput,\n account: Account,\n ): Promise<void> {\n await this.hooks.onVerifyEmailRequest?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n\n await this.store.verifyEmailRequest(input)\n\n await this.hooks.onVerifyEmailRequested?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n }\n\n public async verifyEmailConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: VerifyEmailConfirmInput,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onVerifyEmailConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n\n const updatedAccount = await this.store.verifyEmailConfirm(input)\n\n if (!updatedAccount) {\n throw new InvalidRequestError('Invalid token')\n }\n\n await this.hooks.onVerifyEmailConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n input,\n })\n\n return updatedAccount\n }\n\n public async enableEmailAuthFactor(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: EnableEmailAuthFactorInput,\n account: Account,\n ): Promise<Account> {\n // Already enabled\n if (account.emailAuthFactor) return account\n\n await this.hooks.onEnableEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.enableEmailAuthFactor(input)\n\n if (updatedAccount.emailAuthFactor !== account.emailAuthFactor) {\n await this.hooks.onEnabledEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n }\n\n return updatedAccount\n }\n\n public async disableEmailAuthFactor(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DisableEmailAuthFactorInput,\n account: Account,\n ): Promise<Account> {\n // Already disabled\n if (!account.emailAuthFactor) return account\n\n await this.hooks.onDisableEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.disableEmailAuthFactor(input)\n\n if (updatedAccount.emailAuthFactor !== account.emailAuthFactor) {\n await this.hooks.onDisabledEmailAuthFactor?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n }\n\n return updatedAccount\n }\n\n public async updateHandle(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: UpdateHandleData,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onUpdateHandle?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account,\n })\n\n const updatedAccount = await this.store.updateHandle(input)\n\n await this.hooks.onUpdatedHandle?.call(null, {\n deviceId,\n deviceMetadata,\n input,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async deactivateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onDeactivateAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n const updatedAccount = await callAsync(() =>\n this.store.deactivateAccount({\n did: account.did,\n // @TODO support setting this from the UI/API\n deleteAfter: undefined,\n }),\n ).catch((err) => {\n throw InvalidRequestError.from(err, 'Account deactivation failed')\n })\n\n await this.hooks.onDeactivatedAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async reactivateAccount(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n account: Account,\n ): Promise<Account> {\n await this.hooks.onReactivateAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n const updatedAccount = await callAsync(() =>\n this.store.reactivateAccount({ did: account.did }),\n ).catch((err) => {\n throw InvalidRequestError.from(err, 'Account reactivation failed')\n })\n\n await this.hooks.onReactivatedAccount?.call(null, {\n deviceId,\n deviceMetadata,\n account: updatedAccount,\n })\n\n return updatedAccount\n }\n\n public async deleteAccountRequest(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DeleteAccountRequestInput,\n account: Account,\n ): Promise<void> {\n await this.hooks.onDeleteAccountRequest?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n await this.store.deleteAccountRequest(input)\n\n await this.hooks.onDeleteAccountRequested?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n }\n\n public async deleteAccountConfirm(\n deviceId: DeviceId,\n deviceMetadata: RequestMetadata,\n input: DeleteAccountConfirmInput,\n account: Account,\n ): Promise<void> {\n return constantTime(BRUTE_FORCE_MITIGATION_DELAY, async () => {\n await this.hooks.onDeleteAccountConfirm?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n })\n\n await callAsync(() => this.store.deleteAccountConfirm(input)).catch(\n (err) => {\n throw InvalidRequestError.from(err, 'Account deletion failed')\n },\n )\n\n await this.hooks.onDeleteAccountConfirmed?.call(null, {\n deviceId,\n deviceMetadata,\n account,\n input,\n })\n })\n }\n}\n"]}
|
|
@@ -41,7 +41,12 @@ export type AuthenticateAccountData = {
|
|
|
41
41
|
locale: string;
|
|
42
42
|
password: string;
|
|
43
43
|
username: string;
|
|
44
|
-
emailOtp
|
|
44
|
+
emailOtp: string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Lists the accounts that were previously remembered on the device, allowing
|
|
47
|
+
* OTP bypass for these accounts (based on the store's own logic)
|
|
48
|
+
*/
|
|
49
|
+
deviceAccounts: readonly DeviceAccount[];
|
|
45
50
|
};
|
|
46
51
|
export type AuthorizedClientData = {
|
|
47
52
|
authorizedScopes: readonly string[];
|
|
@@ -88,11 +93,8 @@ export interface AccountStore {
|
|
|
88
93
|
/**
|
|
89
94
|
* @throws {InvalidCredentialsError} - When the credentials are not valid.
|
|
90
95
|
* Populate {@link InvalidCredentialsError.did} with the subject identifier
|
|
91
|
-
* when the identifier matched an existing account (e.g. wrong password for
|
|
92
|
-
*
|
|
93
|
-
* generic {@link InvalidRequestError} is also accepted for backward
|
|
94
|
-
* compatibility but prevents the `onSignInFailed` hook from distinguishing
|
|
95
|
-
* the two cases.
|
|
96
|
+
* when the identifier matched an existing account (e.g. wrong password for a
|
|
97
|
+
* known user); omit it when the identifier was not found.
|
|
96
98
|
* @throws {SecondAuthenticationFactorRequiredError} - To indicate that an {@link SecondAuthenticationFactorRequiredError.type} is required in the credentials
|
|
97
99
|
*/
|
|
98
100
|
authenticateAccount(data: AuthenticateAccountData): Awaitable<Account>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-store.d.ts","sourceRoot":"","sources":["../../src/account/account-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,EACV,OAAO,EACP,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC7B,yBAAyB,EACzB,sBAAsB,EACtB,2BAA2B,EAC3B,0BAA0B,EAC1B,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,EAC1B,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,6BAA6B,CAAA;AACpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AACpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGrD,YAAY,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,GAAG,EACH,2BAA2B,EAC3B,0BAA0B,EAC1B,YAAY,EACZ,uBAAuB,EACvB,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,GACZ,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAA;AAClE,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAA;AAEjE,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAA;AAC9D,MAAM,MAAM,wBAAwB,GAAG,yBAAyB,CAAA;AAChE,MAAM,MAAM,uBAAuB,GAAG,uBAAuB,CAAA;AAC7D,MAAM,MAAM,uBAAuB,GAAG,8BAA8B,CAAA;AACpE,MAAM,MAAM,uBAAuB,GAAG,6BAA6B,CAAA;AACnE,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG;IAC3D,WAAW,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;CACzC,CAAA;AACD,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,CAAA;AAC1D,MAAM,MAAM,yBAAyB,GAAG,4BAA4B,CAAA;AACpE,MAAM,MAAM,yBAAyB,GAAG,2BAA2B,CAAA;AAEnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,
|
|
1
|
+
{"version":3,"file":"account-store.d.ts","sourceRoot":"","sources":["../../src/account/account-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-store.js","sourceRoot":"","sources":["../../src/account/account-store.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAyR3D,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAe;IAChE,qBAAqB;IACrB,eAAe;IACf,mBAAmB;IACnB,sBAAsB;IACtB,sBAAsB;IACtB,wBAAwB;IACxB,uBAAuB;IACvB,YAAY;IACZ,kBAAkB;IAClB,oBAAoB;IACpB,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,qBAAqB;IACrB,oBAAoB;IACpB,oBAAoB;IACpB,cAAc;IACd,qBAAqB;IACrB,oBAAoB;IACpB,oBAAoB;IACpB,0BAA0B;CAC3B,CAAC,CAAA;AAEF,MAAM,UAAU,cAAc,CAAI,cAAiB;IACjD,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC","sourcesContent":["import type { Did } from '@atproto/did'\nimport type {\n Account,\n ConfirmAccountDeletionInput,\n ConfirmEmailUpdateInput,\n ConfirmEmailVerificationInput,\n ConfirmResetPasswordInput,\n DeactivateAccountInput,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n InitiateAccountDeletionInput,\n InitiateEmailUpdateInput,\n InitiateEmailUpdateOutput,\n InitiateEmailVerificationInput,\n InitiatePasswordResetInput,\n ReactivateAccountInput,\n UpdateHandleInput,\n} from '@atproto/oauth-provider-api'\nimport type { OAuthScope } from '@atproto/oauth-types'\nimport type { DatetimeString, HandleString } from '@atproto/syntax'\nimport type { ClientId } from '../client/client-id.js'\nimport type { DeviceData } from '../device/device-data.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport type { SessionId } from '../device/session-id.js'\nimport type { HandleUnavailableReason } from '../errors/handle-unavailable-error.js'\nimport type { HcaptchaVerifyResult } from '../lib/hcaptcha.js'\nimport type { Awaitable } from '../lib/util/type.js'\nimport { buildInterfaceChecker } from '../lib/util/type.js'\nimport type { InviteCode } from '../types/invite-code.js'\nimport type { SignUpInput } from './sign-up-input.js'\n\n// Export all types needed to implement the AccountStore interface\nexport type {\n Account,\n ClientId,\n DeviceData,\n DeviceId,\n Did,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n HandleString,\n HandleUnavailableReason,\n HcaptchaVerifyResult,\n InviteCode,\n OAuthScope,\n SessionId,\n SignUpInput,\n}\n\nexport type ResetPasswordRequestInput = InitiatePasswordResetInput\nexport type ResetPasswordConfirmInput = ConfirmResetPasswordInput\n\nexport type UpdateEmailRequestInput = InitiateEmailUpdateInput\nexport type UpdateEmailRequestOutput = InitiateEmailUpdateOutput\nexport type UpdateEmailConfirmInput = ConfirmEmailUpdateInput\nexport type VerifyEmailRequestInput = InitiateEmailVerificationInput\nexport type VerifyEmailConfirmInput = ConfirmEmailVerificationInput\nexport type UpdateHandleData = UpdateHandleInput\n\n/**\n * @NOTE `deleteAfter` is part of the store contract but is not (yet) exposed\n * over the API, hence the extension of {@link DeactivateAccountInput}.\n */\nexport type DeactivateAccountData = DeactivateAccountInput & {\n deleteAfter?: DatetimeString | undefined\n}\nexport type ReactivateAccountData = ReactivateAccountInput\nexport type DeleteAccountRequestInput = InitiateAccountDeletionInput\nexport type DeleteAccountConfirmInput = ConfirmAccountDeletionInput\n\nexport type CreateAccountData = {\n locale: string\n email: string\n password: string\n handle: HandleString\n inviteCode?: string | undefined\n}\n\nexport type AuthenticateAccountData = {\n locale: string\n password: string\n username: string\n emailOtp?: string | undefined\n}\n\nexport type AuthorizedClientData = { authorizedScopes: readonly string[] }\nexport type AuthorizedClients = Map<ClientId, AuthorizedClientData>\n\nexport type DeviceAccount = {\n deviceId: DeviceId\n\n /**\n * The data associated with the device, created through the\n * {@link DeviceStore}. This data is used to identify devices on which a user\n * has logged in.\n */\n deviceData: DeviceData\n\n /**\n * The account associated with the device account.\n */\n account: Account\n\n /**\n * The list of clients that are authorized by the account, as created through\n * the {@link AccountStore.setAuthorizedClient} method.\n */\n authorizedClients: AuthorizedClients\n\n /**\n * The date at which the device account was created. This value is currently\n * not used.\n */\n createdAt: Date\n\n /**\n * The date at which the device account was last updated. This value is used\n * to determine the date at which the user last authenticated on a device\n */\n updatedAt: Date\n}\n\nexport type SignUpData = SignUpInput & {\n hcaptchaResult?: HcaptchaVerifyResult\n inviteCode?: InviteCode\n}\n\nexport interface AccountStore {\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n * @throws {InvalidRequestError} - To indicate that some data is invalid\n */\n createAccount(data: CreateAccountData): Awaitable<Account>\n\n /**\n * @throws {InvalidCredentialsError} - When the credentials are not valid.\n * Populate {@link InvalidCredentialsError.did} with the subject identifier\n * when the identifier matched an existing account (e.g. wrong password for\n * a known user); omit it when the identifier was not found. Throwing the\n * generic {@link InvalidRequestError} is also accepted for backward\n * compatibility but prevents the `onSignInFailed` hook from distinguishing\n * the two cases.\n * @throws {SecondAuthenticationFactorRequiredError} - To indicate that an {@link SecondAuthenticationFactorRequiredError.type} is required in the credentials\n */\n authenticateAccount(data: AuthenticateAccountData): Awaitable<Account>\n\n /**\n * Add a client & scopes to the list of authorized clients for the given account.\n */\n setAuthorizedClient(\n did: Did,\n clientId: ClientId,\n data: AuthorizedClientData,\n ): Awaitable<void>\n\n /**\n * @throws {InvalidRequestError} - When the credentials are not valid\n */\n getAccount(did: Did): Awaitable<{\n account: Account\n authorizedClients: AuthorizedClients\n }>\n\n /**\n * @param data.requestId - If provided, the inserted account must be bound to\n * that particular requestId.\n *\n * @note Whenever a particular device account is created, all **unbound**\n * device accounts for the same `deviceId` & `sub` should be deleted.\n *\n * @note When a particular request is deleted (through\n * {@link RequestStore.deleteRequest}), all accounts bound to that request\n * should be deleted as well.\n */\n upsertDeviceAccount(deviceId: DeviceId, did: Did): Awaitable<void>\n\n /**\n * @param requestId - If provided, the result must either have the same\n * requestId, or not be bound to a particular requestId. If `null`, the\n * result must not be bound to a particular requestId.\n * @throws {InvalidRequestError} - Instead of returning `null` in order to\n * provide a custom error message\n */\n getDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Awaitable<DeviceAccount | null>\n\n /**\n * Removes *all* the unbound device-accounts associated with the given device\n * & account.\n *\n * @note Noop if the device-account is not found.\n */\n removeDeviceAccount(deviceId: DeviceId, did: Did): Awaitable<void>\n\n /**\n * @returns **all** the device accounts matching the given `filter`.\n */\n listDeviceAccounts(\n filter: { did: Did } | { deviceId: DeviceId },\n ): Awaitable<DeviceAccount[]>\n\n resetPasswordRequest(\n data: ResetPasswordRequestInput,\n ): Awaitable<null | Account>\n\n resetPasswordConfirm(\n data: ResetPasswordConfirmInput,\n ): Awaitable<null | Account>\n\n updateEmailRequest(\n data: UpdateEmailRequestInput,\n ): Awaitable<UpdateEmailRequestOutput>\n /**\n * Must trigger a verification email to be sent to the new email address, that\n * will then be confirmed through {@link updateEmailConfirm}. The account's\n * {@link Account['emailVerified'] emailVerified} field is expected to become\n * `false` until the new email is confirmed.\n */\n updateEmailConfirm(data: UpdateEmailConfirmInput): Awaitable<Account | null>\n\n verifyEmailRequest(data: VerifyEmailRequestInput): Awaitable<void>\n verifyEmailConfirm(data: VerifyEmailConfirmInput): Awaitable<Account | null>\n\n /**\n * Enables the email auth factor on the account.\n *\n * @returns the updated account, or `null` when the factor was already enabled\n * (no-op).\n *\n * @note when `null` is returned (no-op), the \"confirmed\" hook is skipped, so\n * a repeat request is not counted as a fresh opt-in.\n *\n * @throws {InvalidRequestError} - To indicate enabling cannot take place due\n * to mismatch of email or email not being verified.\n */\n enableEmailAuthFactor(data: EnableEmailAuthFactorInput): Awaitable<Account>\n\n /**\n * Two-phase disable flow. When `token` is undefined and the factor is still\n * enabled, an email-based OTP isÒ dispatched and `{ tokenRequired: true }` is\n * returned (the account is unchanged, nothing has been disabled yet). Calling\n * again with a valid `token` disables the factor and returns\n * `{ tokenRequired: false }`. Disabling an already-disabled factor is an\n * idempotent no-op that returns `{ tokenRequired: false }` without\n * dispatching an email.\n *\n * `updatedAccount` is `null` in both cases where nothing changed — the\n * OTP-dispatch phase and the already-disabled no-op — and an `Account` only\n * once the factor has actually been turned off. Callers pair it with\n * `tokenRequired` to decide whether to fire the \"confirmed\" hook.\n *\n * @throws {InvalidRequestError} - To indicate disabling cannot take place due\n * to mismatch of email or email not being verified.\n * @throws {SecondAuthenticationFactorRequiredError} - To indicate that a\n * second authentication factor is required to complete the action.\n */\n disableEmailAuthFactor(data: DisableEmailAuthFactorInput): Awaitable<Account>\n\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n */\n verifyHandleAvailability(handle: HandleString): Awaitable<void>\n\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n * @throws {InvalidRequestError} - To indicate that the handle is invalid or\n * cannot be used\n */\n updateHandle(data: UpdateHandleData): Awaitable<Account>\n\n /**\n * Mark the account as deactivated. The account remains recoverable. Should\n * be a no-op when the account is already deactivated.\n *\n * @throws {InvalidRequestError} - When the account cannot be deactivated\n * (e.g. unknown account)\n */\n deactivateAccount(data: DeactivateAccountData): Awaitable<Account>\n\n /**\n * Reactivate a previously-deactivated account. Should be a no-op when the\n * account is already active.\n *\n * @throws {InvalidRequestError} - When the account cannot be reactivated\n * (e.g. unknown account)\n */\n reactivateAccount(data: ReactivateAccountData): Awaitable<Account>\n\n /**\n * Initiate account deletion: typically sends a confirmation token to the\n * account's email address. The account is NOT deleted until\n * {@link deleteAccountConfirm} is called with the matching token and the\n * user's current password.\n */\n deleteAccountRequest(data: DeleteAccountRequestInput): Awaitable<void>\n\n /**\n * Finalize account deletion. Implementations MUST verify both the email\n * confirmation `token` issued by {@link deleteAccountRequest} and the user's\n * current `password` before deleting any data. Deletion is irreversible.\n *\n * @throws {InvalidRequestError} - When the token or password is invalid.\n */\n deleteAccountConfirm(data: DeleteAccountConfirmInput): Awaitable<void>\n}\n\nexport const isAccountStore = buildInterfaceChecker<AccountStore>([\n 'authenticateAccount',\n 'createAccount',\n 'deactivateAccount',\n 'deleteAccountConfirm',\n 'deleteAccountRequest',\n 'disableEmailAuthFactor',\n 'enableEmailAuthFactor',\n 'getAccount',\n 'getDeviceAccount',\n 'listDeviceAccounts',\n 'reactivateAccount',\n 'removeDeviceAccount',\n 'resetPasswordConfirm',\n 'resetPasswordRequest',\n 'setAuthorizedClient',\n 'updateEmailConfirm',\n 'updateEmailRequest',\n 'updateHandle',\n 'upsertDeviceAccount',\n 'verifyEmailConfirm',\n 'verifyEmailRequest',\n 'verifyHandleAvailability',\n])\n\nexport function asAccountStore<V>(implementation: V): V & AccountStore {\n if (!implementation || !isAccountStore(implementation)) {\n throw new Error('Invalid AccountStore implementation')\n }\n return implementation\n}\n"]}
|
|
1
|
+
{"version":3,"file":"account-store.js","sourceRoot":"","sources":["../../src/account/account-store.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AA2R3D,MAAM,CAAC,MAAM,cAAc,GAAG,qBAAqB,CAAe;IAChE,qBAAqB;IACrB,eAAe;IACf,mBAAmB;IACnB,sBAAsB;IACtB,sBAAsB;IACtB,wBAAwB;IACxB,uBAAuB;IACvB,YAAY;IACZ,kBAAkB;IAClB,oBAAoB;IACpB,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,qBAAqB;IACrB,oBAAoB;IACpB,oBAAoB;IACpB,cAAc;IACd,qBAAqB;IACrB,oBAAoB;IACpB,oBAAoB;IACpB,0BAA0B;CAC3B,CAAC,CAAA;AAEF,MAAM,UAAU,cAAc,CAAI,cAAiB;IACjD,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,CAAC;IACD,OAAO,cAAc,CAAA;AACvB,CAAC","sourcesContent":["import type { Did } from '@atproto/did'\nimport type {\n Account,\n ConfirmAccountDeletionInput,\n ConfirmEmailUpdateInput,\n ConfirmEmailVerificationInput,\n ConfirmResetPasswordInput,\n DeactivateAccountInput,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n InitiateAccountDeletionInput,\n InitiateEmailUpdateInput,\n InitiateEmailUpdateOutput,\n InitiateEmailVerificationInput,\n InitiatePasswordResetInput,\n ReactivateAccountInput,\n UpdateHandleInput,\n} from '@atproto/oauth-provider-api'\nimport type { OAuthScope } from '@atproto/oauth-types'\nimport type { DatetimeString, HandleString } from '@atproto/syntax'\nimport type { ClientId } from '../client/client-id.js'\nimport type { DeviceData } from '../device/device-data.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport type { SessionId } from '../device/session-id.js'\nimport type { HandleUnavailableReason } from '../errors/handle-unavailable-error.js'\nimport type { HcaptchaVerifyResult } from '../lib/hcaptcha.js'\nimport type { Awaitable } from '../lib/util/type.js'\nimport { buildInterfaceChecker } from '../lib/util/type.js'\nimport type { InviteCode } from '../types/invite-code.js'\nimport type { SignUpInput } from './sign-up-input.js'\n\n// Export all types needed to implement the AccountStore interface\nexport type {\n Account,\n ClientId,\n DeviceData,\n DeviceId,\n Did,\n DisableEmailAuthFactorInput,\n EnableEmailAuthFactorInput,\n HandleString,\n HandleUnavailableReason,\n HcaptchaVerifyResult,\n InviteCode,\n OAuthScope,\n SessionId,\n SignUpInput,\n}\n\nexport type ResetPasswordRequestInput = InitiatePasswordResetInput\nexport type ResetPasswordConfirmInput = ConfirmResetPasswordInput\n\nexport type UpdateEmailRequestInput = InitiateEmailUpdateInput\nexport type UpdateEmailRequestOutput = InitiateEmailUpdateOutput\nexport type UpdateEmailConfirmInput = ConfirmEmailUpdateInput\nexport type VerifyEmailRequestInput = InitiateEmailVerificationInput\nexport type VerifyEmailConfirmInput = ConfirmEmailVerificationInput\nexport type UpdateHandleData = UpdateHandleInput\n\n/**\n * @NOTE `deleteAfter` is part of the store contract but is not (yet) exposed\n * over the API, hence the extension of {@link DeactivateAccountInput}.\n */\nexport type DeactivateAccountData = DeactivateAccountInput & {\n deleteAfter?: DatetimeString | undefined\n}\nexport type ReactivateAccountData = ReactivateAccountInput\nexport type DeleteAccountRequestInput = InitiateAccountDeletionInput\nexport type DeleteAccountConfirmInput = ConfirmAccountDeletionInput\n\nexport type CreateAccountData = {\n locale: string\n email: string\n password: string\n handle: HandleString\n inviteCode?: string | undefined\n}\n\nexport type AuthenticateAccountData = {\n locale: string\n password: string\n username: string\n emailOtp: string | undefined\n /**\n * Lists the accounts that were previously remembered on the device, allowing\n * OTP bypass for these accounts (based on the store's own logic)\n */\n deviceAccounts: readonly DeviceAccount[]\n}\n\nexport type AuthorizedClientData = { authorizedScopes: readonly string[] }\nexport type AuthorizedClients = Map<ClientId, AuthorizedClientData>\n\nexport type DeviceAccount = {\n deviceId: DeviceId\n\n /**\n * The data associated with the device, created through the\n * {@link DeviceStore}. This data is used to identify devices on which a user\n * has logged in.\n */\n deviceData: DeviceData\n\n /**\n * The account associated with the device account.\n */\n account: Account\n\n /**\n * The list of clients that are authorized by the account, as created through\n * the {@link AccountStore.setAuthorizedClient} method.\n */\n authorizedClients: AuthorizedClients\n\n /**\n * The date at which the device account was created. This value is currently\n * not used.\n */\n createdAt: Date\n\n /**\n * The date at which the device account was last updated. This value is used\n * to determine the date at which the user last authenticated on a device\n */\n updatedAt: Date\n}\n\nexport type SignUpData = SignUpInput & {\n hcaptchaResult?: HcaptchaVerifyResult\n inviteCode?: InviteCode\n}\n\nexport interface AccountStore {\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n * @throws {InvalidRequestError} - To indicate that some data is invalid\n */\n createAccount(data: CreateAccountData): Awaitable<Account>\n\n /**\n * @throws {InvalidCredentialsError} - When the credentials are not valid.\n * Populate {@link InvalidCredentialsError.did} with the subject identifier\n * when the identifier matched an existing account (e.g. wrong password for a\n * known user); omit it when the identifier was not found.\n * @throws {SecondAuthenticationFactorRequiredError} - To indicate that an {@link SecondAuthenticationFactorRequiredError.type} is required in the credentials\n */\n authenticateAccount(data: AuthenticateAccountData): Awaitable<Account>\n\n /**\n * Add a client & scopes to the list of authorized clients for the given account.\n */\n setAuthorizedClient(\n did: Did,\n clientId: ClientId,\n data: AuthorizedClientData,\n ): Awaitable<void>\n\n /**\n * @throws {InvalidRequestError} - When the credentials are not valid\n */\n getAccount(did: Did): Awaitable<{\n account: Account\n authorizedClients: AuthorizedClients\n }>\n\n /**\n * @param data.requestId - If provided, the inserted account must be bound to\n * that particular requestId.\n *\n * @note Whenever a particular device account is created, all **unbound**\n * device accounts for the same `deviceId` & `sub` should be deleted.\n *\n * @note When a particular request is deleted (through\n * {@link RequestStore.deleteRequest}), all accounts bound to that request\n * should be deleted as well.\n */\n upsertDeviceAccount(deviceId: DeviceId, did: Did): Awaitable<void>\n\n /**\n * @param requestId - If provided, the result must either have the same\n * requestId, or not be bound to a particular requestId. If `null`, the\n * result must not be bound to a particular requestId.\n * @throws {InvalidRequestError} - Instead of returning `null` in order to\n * provide a custom error message\n */\n getDeviceAccount(\n deviceId: DeviceId,\n did: Did,\n ): Awaitable<DeviceAccount | null>\n\n /**\n * Removes *all* the unbound device-accounts associated with the given device\n * & account.\n *\n * @note Noop if the device-account is not found.\n */\n removeDeviceAccount(deviceId: DeviceId, did: Did): Awaitable<void>\n\n /**\n * @returns **all** the device accounts matching the given `filter`.\n */\n listDeviceAccounts(\n filter: { did: Did } | { deviceId: DeviceId },\n ): Awaitable<DeviceAccount[]>\n\n resetPasswordRequest(\n data: ResetPasswordRequestInput,\n ): Awaitable<null | Account>\n\n resetPasswordConfirm(\n data: ResetPasswordConfirmInput,\n ): Awaitable<null | Account>\n\n updateEmailRequest(\n data: UpdateEmailRequestInput,\n ): Awaitable<UpdateEmailRequestOutput>\n /**\n * Must trigger a verification email to be sent to the new email address, that\n * will then be confirmed through {@link updateEmailConfirm}. The account's\n * {@link Account['emailVerified'] emailVerified} field is expected to become\n * `false` until the new email is confirmed.\n */\n updateEmailConfirm(data: UpdateEmailConfirmInput): Awaitable<Account | null>\n\n verifyEmailRequest(data: VerifyEmailRequestInput): Awaitable<void>\n verifyEmailConfirm(data: VerifyEmailConfirmInput): Awaitable<Account | null>\n\n /**\n * Enables the email auth factor on the account.\n *\n * @returns the updated account, or `null` when the factor was already enabled\n * (no-op).\n *\n * @note when `null` is returned (no-op), the \"confirmed\" hook is skipped, so\n * a repeat request is not counted as a fresh opt-in.\n *\n * @throws {InvalidRequestError} - To indicate enabling cannot take place due\n * to mismatch of email or email not being verified.\n */\n enableEmailAuthFactor(data: EnableEmailAuthFactorInput): Awaitable<Account>\n\n /**\n * Two-phase disable flow. When `token` is undefined and the factor is still\n * enabled, an email-based OTP isÒ dispatched and `{ tokenRequired: true }` is\n * returned (the account is unchanged, nothing has been disabled yet). Calling\n * again with a valid `token` disables the factor and returns\n * `{ tokenRequired: false }`. Disabling an already-disabled factor is an\n * idempotent no-op that returns `{ tokenRequired: false }` without\n * dispatching an email.\n *\n * `updatedAccount` is `null` in both cases where nothing changed — the\n * OTP-dispatch phase and the already-disabled no-op — and an `Account` only\n * once the factor has actually been turned off. Callers pair it with\n * `tokenRequired` to decide whether to fire the \"confirmed\" hook.\n *\n * @throws {InvalidRequestError} - To indicate disabling cannot take place due\n * to mismatch of email or email not being verified.\n * @throws {SecondAuthenticationFactorRequiredError} - To indicate that a\n * second authentication factor is required to complete the action.\n */\n disableEmailAuthFactor(data: DisableEmailAuthFactorInput): Awaitable<Account>\n\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n */\n verifyHandleAvailability(handle: HandleString): Awaitable<void>\n\n /**\n * @throws {HandleUnavailableError} - To indicate that the handle is already taken\n * @throws {InvalidRequestError} - To indicate that the handle is invalid or\n * cannot be used\n */\n updateHandle(data: UpdateHandleData): Awaitable<Account>\n\n /**\n * Mark the account as deactivated. The account remains recoverable. Should\n * be a no-op when the account is already deactivated.\n *\n * @throws {InvalidRequestError} - When the account cannot be deactivated\n * (e.g. unknown account)\n */\n deactivateAccount(data: DeactivateAccountData): Awaitable<Account>\n\n /**\n * Reactivate a previously-deactivated account. Should be a no-op when the\n * account is already active.\n *\n * @throws {InvalidRequestError} - When the account cannot be reactivated\n * (e.g. unknown account)\n */\n reactivateAccount(data: ReactivateAccountData): Awaitable<Account>\n\n /**\n * Initiate account deletion: typically sends a confirmation token to the\n * account's email address. The account is NOT deleted until\n * {@link deleteAccountConfirm} is called with the matching token and the\n * user's current password.\n */\n deleteAccountRequest(data: DeleteAccountRequestInput): Awaitable<void>\n\n /**\n * Finalize account deletion. Implementations MUST verify both the email\n * confirmation `token` issued by {@link deleteAccountRequest} and the user's\n * current `password` before deleting any data. Deletion is irreversible.\n *\n * @throws {InvalidRequestError} - When the token or password is invalid.\n */\n deleteAccountConfirm(data: DeleteAccountConfirmInput): Awaitable<void>\n}\n\nexport const isAccountStore = buildInterfaceChecker<AccountStore>([\n 'authenticateAccount',\n 'createAccount',\n 'deactivateAccount',\n 'deleteAccountConfirm',\n 'deleteAccountRequest',\n 'disableEmailAuthFactor',\n 'enableEmailAuthFactor',\n 'getAccount',\n 'getDeviceAccount',\n 'listDeviceAccounts',\n 'reactivateAccount',\n 'removeDeviceAccount',\n 'resetPasswordConfirm',\n 'resetPasswordRequest',\n 'setAuthorizedClient',\n 'updateEmailConfirm',\n 'updateEmailRequest',\n 'updateHandle',\n 'upsertDeviceAccount',\n 'verifyEmailConfirm',\n 'verifyEmailRequest',\n 'verifyHandleAvailability',\n])\n\nexport function asAccountStore<V>(implementation: V): V & AccountStore {\n if (!implementation || !isAccountStore(implementation)) {\n throw new Error('Invalid AccountStore implementation')\n }\n return implementation\n}\n"]}
|
|
@@ -4,16 +4,19 @@ export declare const signInDataSchema: z.ZodObject<{
|
|
|
4
4
|
username: z.ZodString;
|
|
5
5
|
password: z.ZodUnion<[z.ZodString, z.ZodString]>;
|
|
6
6
|
emailOtp: z.ZodOptional<z.ZodString>;
|
|
7
|
+
remember: z.ZodOptional<z.ZodBoolean>;
|
|
7
8
|
}, "strict", z.ZodTypeAny, {
|
|
8
9
|
locale: string;
|
|
9
10
|
username: string;
|
|
10
11
|
password: string;
|
|
11
12
|
emailOtp?: string | undefined;
|
|
13
|
+
remember?: boolean | undefined;
|
|
12
14
|
}, {
|
|
13
15
|
locale: string;
|
|
14
16
|
username: string;
|
|
15
17
|
password: string;
|
|
16
18
|
emailOtp?: string | undefined;
|
|
19
|
+
remember?: boolean | undefined;
|
|
17
20
|
}>;
|
|
18
21
|
export type SignInData = z.output<typeof signInDataSchema>;
|
|
19
22
|
//# sourceMappingURL=sign-in-data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in-data.d.ts","sourceRoot":"","sources":["../../src/account/sign-in-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"sign-in-data.d.ts","sourceRoot":"","sources":["../../src/account/sign-in-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAQlB,CAAA;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAA"}
|