@atproto/pds 0.4.226 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/account-manager/account-manager.d.ts +19 -5
- package/dist/account-manager/account-manager.d.ts.map +1 -1
- package/dist/account-manager/account-manager.js +94 -12
- package/dist/account-manager/account-manager.js.map +1 -1
- package/dist/account-manager/helpers/account.d.ts +2 -0
- package/dist/account-manager/helpers/account.d.ts.map +1 -1
- package/dist/account-manager/helpers/account.js +4 -0
- package/dist/account-manager/helpers/account.js.map +1 -1
- package/dist/account-manager/oauth-store.d.ts +5 -1
- package/dist/account-manager/oauth-store.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.js +50 -1
- package/dist/account-manager/oauth-store.js.map +1 -1
- package/dist/api/app/bsky/actor/getPreferences.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/getPreferences.js +7 -2
- package/dist/api/app/bsky/actor/getPreferences.js.map +1 -1
- package/dist/api/app/bsky/actor/putPreferences.d.ts.map +1 -1
- package/dist/api/app/bsky/actor/putPreferences.js +7 -2
- package/dist/api/app/bsky/actor/putPreferences.js.map +1 -1
- package/dist/api/com/atproto/admin/updateAccountEmail.js +1 -1
- package/dist/api/com/atproto/admin/updateAccountEmail.js.map +1 -1
- package/dist/api/com/atproto/server/confirmEmail.d.ts.map +1 -1
- package/dist/api/com/atproto/server/confirmEmail.js +20 -27
- package/dist/api/com/atproto/server/confirmEmail.js.map +1 -1
- package/dist/api/com/atproto/server/getServiceAuth.d.ts.map +1 -1
- package/dist/api/com/atproto/server/getServiceAuth.js +4 -0
- package/dist/api/com/atproto/server/getServiceAuth.js.map +1 -1
- package/dist/api/com/atproto/server/requestEmailConfirmation.d.ts +3 -1
- package/dist/api/com/atproto/server/requestEmailConfirmation.d.ts.map +1 -1
- package/dist/api/com/atproto/server/requestEmailConfirmation.js +44 -39
- package/dist/api/com/atproto/server/requestEmailConfirmation.js.map +1 -1
- package/dist/api/com/atproto/server/requestEmailUpdate.d.ts +3 -1
- package/dist/api/com/atproto/server/requestEmailUpdate.d.ts.map +1 -1
- package/dist/api/com/atproto/server/requestEmailUpdate.js +51 -47
- package/dist/api/com/atproto/server/requestEmailUpdate.js.map +1 -1
- package/dist/api/com/atproto/server/updateEmail.d.ts.map +1 -1
- package/dist/api/com/atproto/server/updateEmail.js +32 -46
- package/dist/api/com/atproto/server/updateEmail.js.map +1 -1
- package/dist/config/config.d.ts +5 -2
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +50 -46
- package/dist/config/config.js.map +1 -1
- package/dist/config/env.d.ts +1 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +1 -0
- package/dist/config/env.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +2 -2
- package/dist/context.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.d.ts +5 -0
- package/dist/lexicons/app/bsky/embed/external.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.js +4 -0
- package/dist/lexicons/app/bsky/embed/external.defs.js.map +1 -1
- package/dist/lexicons/chat/bsky/actor/getStatus.defs.d.ts +2 -0
- package/dist/lexicons/chat/bsky/actor/getStatus.defs.d.ts.map +1 -1
- package/dist/lexicons/chat/bsky/actor/getStatus.defs.js +1 -0
- package/dist/lexicons/chat/bsky/actor/getStatus.defs.js.map +1 -1
- package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts +4 -0
- package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/chat/bsky/convo/defs.defs.js +1 -0
- package/dist/lexicons/chat/bsky/convo/defs.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/server/getServiceAuth.defs.d.ts +2 -2
- package/dist/lexicons/com/atproto/server/getServiceAuth.defs.js +1 -1
- package/dist/lexicons/com/atproto/server/getServiceAuth.defs.js.map +1 -1
- package/dist/mailer/index.d.ts +5 -3
- package/dist/mailer/index.d.ts.map +1 -1
- package/dist/mailer/index.js +20 -9
- package/dist/mailer/index.js.map +1 -1
- package/dist/mailer/templates/confirm-email.js +11 -3
- package/dist/mailer/templates/confirm-email.js.map +2 -2
- package/dist/mailer/templates/delete-account.js +2 -2
- package/dist/mailer/templates/delete-account.js.map +2 -2
- package/dist/mailer/templates/plc-operation.js +2 -2
- package/dist/mailer/templates/plc-operation.js.map +2 -2
- package/dist/mailer/templates/reset-password.js +2 -2
- package/dist/mailer/templates/reset-password.js.map +2 -2
- package/dist/mailer/templates/update-email.js +2 -2
- package/dist/mailer/templates/update-email.js.map +2 -2
- package/dist/mailer/templates.d.ts +11 -0
- package/dist/mailer/templates.d.ts.map +1 -1
- package/dist/mailer/templates.js.map +1 -1
- package/dist/pipethrough.d.ts +3 -0
- package/dist/pipethrough.d.ts.map +1 -1
- package/dist/pipethrough.js +25 -9
- package/dist/pipethrough.js.map +1 -1
- package/package.json +12 -11
- package/src/account-manager/account-manager.ts +136 -15
- package/src/account-manager/helpers/account.ts +9 -1
- package/src/account-manager/oauth-store.ts +80 -1
- package/src/api/app/bsky/actor/getPreferences.ts +11 -2
- package/src/api/app/bsky/actor/putPreferences.ts +11 -2
- package/src/api/com/atproto/admin/updateAccountEmail.ts +1 -1
- package/src/api/com/atproto/server/confirmEmail.ts +24 -29
- package/src/api/com/atproto/server/getServiceAuth.ts +7 -0
- package/src/api/com/atproto/server/requestEmailConfirmation.ts +55 -48
- package/src/api/com/atproto/server/requestEmailUpdate.ts +64 -48
- package/src/api/com/atproto/server/updateEmail.ts +32 -62
- package/src/config/config.ts +69 -57
- package/src/config/env.ts +3 -0
- package/src/context.ts +2 -1
- package/src/mailer/index.ts +35 -11
- package/src/mailer/templates/confirm-email.hbs +18 -17
- package/src/mailer/templates/delete-account.hbs +6 -6
- package/src/mailer/templates/plc-operation.hbs +6 -6
- package/src/mailer/templates/reset-password.hbs +7 -7
- package/src/mailer/templates/update-email.hbs +6 -6
- package/src/mailer/templates.ts +12 -0
- package/src/pipethrough.ts +33 -12
- package/tests/account-manager.test.ts +89 -8
- package/tests/app-passwords.test.ts +5 -5
- package/tests/get-service-auth.test.ts +81 -0
- package/tests/proxied/proxy-header.test.ts +1 -0
- package/tests/proxied/proxy-oauth-aud.test.ts +175 -0
|
@@ -10,7 +10,7 @@ import { syncEvtDataFromCommit } from '../sequencer/index.js';
|
|
|
10
10
|
import { InvalidPasswordError } from './account-manager.js';
|
|
11
11
|
import * as accountDeviceHelper from './helpers/account-device.js';
|
|
12
12
|
import * as accountHelper from './helpers/account.js';
|
|
13
|
-
import { AccountStatus } from './helpers/account.js';
|
|
13
|
+
import { AccountStatus, UserAlreadyExistsError } from './helpers/account.js';
|
|
14
14
|
import * as authRequestHelper from './helpers/authorization-request.js';
|
|
15
15
|
import * as authorizedClientHelper from './helpers/authorized-client.js';
|
|
16
16
|
import * as deviceHelper from './helpers/device.js';
|
|
@@ -395,6 +395,55 @@ export class OAuthStore {
|
|
|
395
395
|
const row = await tokenHelper.findByQB(this.db, { code }).executeTakeFirst();
|
|
396
396
|
return row ? this.toTokenInfo(row) : null;
|
|
397
397
|
}
|
|
398
|
+
async verifyEmailRequest({ sub: did, locale, }) {
|
|
399
|
+
// @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`
|
|
400
|
+
assert(isDidString(did), 'sub must be a valid DID string');
|
|
401
|
+
try {
|
|
402
|
+
await this.accountManager.requestEmailConfirmation(did, { locale });
|
|
403
|
+
}
|
|
404
|
+
catch (err) {
|
|
405
|
+
if (err instanceof XrpcAuthRequiredError) {
|
|
406
|
+
throw new InvalidRequestError(err.message, err);
|
|
407
|
+
}
|
|
408
|
+
throw err;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
async verifyEmailConfirm({ sub: did, email, token, }) {
|
|
412
|
+
// @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`
|
|
413
|
+
assert(isDidString(did), 'sub must be a valid DID string');
|
|
414
|
+
try {
|
|
415
|
+
const account = await this.accountManager.confirmEmail(did, email, token);
|
|
416
|
+
return this.buildAccount(account);
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
if (err instanceof XrpcInvalidRequestError) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
throw err;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async updateEmailRequest({ sub: did, locale, }) {
|
|
426
|
+
// @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`
|
|
427
|
+
assert(isDidString(did), 'sub must be a valid DID string');
|
|
428
|
+
return this.accountManager.requestEmailUpdate(did, { locale });
|
|
429
|
+
}
|
|
430
|
+
async updateEmailConfirm({ sub: did, token, email, locale, }) {
|
|
431
|
+
// @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`
|
|
432
|
+
assert(isDidString(did), 'sub must be a valid DID string');
|
|
433
|
+
try {
|
|
434
|
+
const account = await this.accountManager.updateEmail(did, email, token, {
|
|
435
|
+
sendConfirmationEmail: true,
|
|
436
|
+
locale,
|
|
437
|
+
});
|
|
438
|
+
return this.buildAccount(account);
|
|
439
|
+
}
|
|
440
|
+
catch (cause) {
|
|
441
|
+
if (cause instanceof UserAlreadyExistsError) {
|
|
442
|
+
throw new InvalidRequestError(cause.message, cause);
|
|
443
|
+
}
|
|
444
|
+
throw cause;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
398
447
|
async toTokenInfo(row) {
|
|
399
448
|
return {
|
|
400
449
|
id: row.tokenId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../../src/account-manager/oauth-store.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { Client, createOp as createPlcOp } from '@did-plc/lib'\nimport { Selectable } from 'kysely'\nimport { Keypair, Secp256k1Keypair } from '@atproto/crypto'\nimport {\n HandleString,\n asAtIdentifierString,\n getBlobCidString,\n isDidString,\n isHandleString,\n} from '@atproto/lex'\nimport {\n Account,\n AccountStore,\n AuthenticateAccountData,\n AuthorizedClientData,\n AuthorizedClients,\n ClientId,\n Code,\n DeviceAccount,\n DeviceData,\n DeviceId,\n DeviceStore,\n FoundRequestResult,\n HandleUnavailableError,\n InvalidCredentialsError,\n InvalidInviteCodeError,\n InvalidRequestError,\n LexiconData,\n LexiconStore,\n NewTokenData,\n RefreshToken,\n RequestData,\n RequestId,\n RequestStore,\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n Sub,\n TokenData,\n TokenId,\n TokenInfo,\n TokenStore,\n UpdateRequestData,\n} from '@atproto/oauth-provider'\nimport {\n AuthRequiredError as XrpcAuthRequiredError,\n InvalidRequestError as XrpcInvalidRequestError,\n} from '@atproto/xrpc-server'\nimport { ActorStore } from '../actor-store/actor-store.js'\nimport { BackgroundQueue } from '../background.js'\nimport { fromDateISO } from '../db/index.js'\nimport { ImageUrlBuilder } from '../image/image-url-builder.js'\nimport { dbLogger } from '../logger.js'\nimport { ServerMailer } from '../mailer/index.js'\nimport { Sequencer, syncEvtDataFromCommit } from '../sequencer/index.js'\nimport { AccountManager, InvalidPasswordError } from './account-manager.js'\nimport * as schemas from './db/schema/index.js'\nimport * as accountDeviceHelper from './helpers/account-device.js'\nimport * as accountHelper from './helpers/account.js'\nimport { AccountStatus } from './helpers/account.js'\nimport * as authRequestHelper from './helpers/authorization-request.js'\nimport * as authorizedClientHelper from './helpers/authorized-client.js'\nimport * as deviceHelper from './helpers/device.js'\nimport * as lexiconHelper from './helpers/lexicon.js'\nimport * as tokenHelper from './helpers/token.js'\nimport * as usedRefreshTokenHelper from './helpers/used-refresh-token.js'\n\n/**\n * This class' purpose is to implement the interface needed by the OAuthProvider\n * to interact with the account database (through the {@link AccountManager}).\n *\n * @note The use of this class assumes that there is no entryway.\n */\nexport class OAuthStore\n implements AccountStore, RequestStore, DeviceStore, LexiconStore, TokenStore\n{\n constructor(\n private readonly accountManager: AccountManager,\n private readonly actorStore: ActorStore,\n private readonly imageUrlBuilder: ImageUrlBuilder,\n private readonly backgroundQueue: BackgroundQueue,\n private readonly mailer: ServerMailer,\n private readonly sequencer: Sequencer,\n private readonly plcClient: Client,\n private readonly plcRotationKey: Keypair,\n private readonly publicUrl: string,\n private readonly recoveryDidKey: string | null,\n ) {}\n\n private get db() {\n const { db } = this.accountManager\n if (db.destroyed) throw new Error('Database connection is closed')\n return db\n }\n\n private get serviceDid() {\n return this.accountManager.serviceDid\n }\n\n private async verifyEmailAvailability(email: string): Promise<void> {\n // @NOTE Email validity & disposability check performed by the OAuthProvider\n\n const account = await this.accountManager.getAccountByEmail(email, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (account) {\n throw new InvalidRequestError(`Email already taken`)\n }\n }\n\n private async verifyInviteCode(code: string) {\n try {\n await this.accountManager.ensureInviteIsAvailable(code)\n } catch (err) {\n const message =\n err instanceof XrpcInvalidRequestError ? err.message : undefined\n throw new InvalidInviteCodeError(message, err)\n }\n }\n\n // AccountStore\n\n async createAccount({\n locale: _locale,\n inviteCode,\n handle,\n email,\n password,\n }: SignUpData): Promise<Account> {\n // @TODO Send an account creation confirmation email (+verification link) to the user (in their locale)\n // @NOTE Password strength & length already enforced by the OAuthProvider\n\n assert(isHandleString(handle), 'Handle must be a valid HandleString')\n\n await Promise.all([\n this.verifyEmailAvailability(email),\n this.verifyHandleAvailability(handle),\n !inviteCode || this.verifyInviteCode(inviteCode),\n ])\n\n // @TODO The code bellow should probably be refactored to be common with the\n // code of the `com.atproto.server.createAccount` XRPC endpoint.\n\n const signingKey = await Secp256k1Keypair.create({ exportable: true })\n const signingKeyDid = signingKey.did()\n\n const plcCreate = await createPlcOp({\n signingKey: signingKeyDid,\n rotationKeys: this.recoveryDidKey\n ? [this.recoveryDidKey, this.plcRotationKey.did()]\n : [this.plcRotationKey.did()],\n handle,\n pds: this.publicUrl,\n signer: this.plcRotationKey,\n })\n\n const { did, op } = plcCreate\n assert(isDidString(did), 'Generated DID is not a valid DidString')\n\n try {\n await this.actorStore.create(did, signingKey)\n try {\n const commit = await this.actorStore.transact(did, (actorTxn) =>\n actorTxn.repo.createRepo([]),\n )\n\n await this.plcClient.sendOperation(did, op)\n\n await this.accountManager.createAccount({\n did,\n handle,\n email,\n password,\n inviteCode,\n repoCid: commit.cid,\n repoRev: commit.rev,\n })\n try {\n await this.sequencer.sequenceIdentityEvt(did, handle)\n await this.sequencer.sequenceAccountEvt(did, AccountStatus.Active)\n await this.sequencer.sequenceCommit(did, commit)\n await this.sequencer.sequenceSyncEvt(\n did,\n syncEvtDataFromCommit(commit),\n )\n await this.accountManager.updateRepoRoot(did, commit.cid, commit.rev)\n await this.actorStore.clearReservedKeypair(signingKeyDid, did)\n\n const account = await this.accountManager.getAccount(did)\n if (!account) throw new Error('Account not found')\n\n return await this.buildAccount(account)\n } catch (err) {\n this.accountManager.deleteAccount(did)\n throw err\n }\n } catch (err) {\n await this.actorStore.destroy(did)\n throw err\n }\n } catch (err) {\n // XrpcError => OAuthError\n if (err instanceof XrpcInvalidRequestError) {\n throw new InvalidRequestError(err.message, err)\n }\n throw err\n }\n }\n\n async authenticateAccount({\n locale: _locale,\n username: identifier,\n password,\n // Not supported by the PDS (yet?)\n emailOtp = undefined,\n }: AuthenticateAccountData): Promise<Account> {\n // @TODO (?) Send an email to the user to notify them of the login attempt\n try {\n // Should never happen\n if (emailOtp != null) {\n throw new Error('Email OTP is not supported')\n }\n\n const { user, appPassword, isSoftDeleted } =\n await this.accountManager.login({ identifier, password })\n\n if (isSoftDeleted) {\n throw new InvalidRequestError('Account was taken down')\n }\n\n if (appPassword) {\n throw new InvalidRequestError('App passwords are not allowed')\n }\n\n return this.buildAccount(user)\n } catch (err) {\n // `InvalidPasswordError` is a subclass of `XrpcAuthRequiredError`,\n // so it must be checked first. Surfacing the matched `did` as the\n // `sub` lets the oauth-provider's `onSignInFailed` hook distinguish\n // \"identifier known, credentials wrong\" from \"identifier unknown\".\n if (err instanceof InvalidPasswordError) {\n throw new InvalidCredentialsError(err.message, err.did, err)\n }\n if (err instanceof XrpcAuthRequiredError) {\n throw new InvalidCredentialsError(err.message, undefined, err)\n }\n throw err\n }\n }\n\n async setAuthorizedClient(\n sub: Sub,\n clientId: ClientId,\n data: AuthorizedClientData,\n ): Promise<void> {\n await authorizedClientHelper.upsert(this.db, sub, clientId, data)\n }\n\n async getAccount(sub: Sub): Promise<{\n account: Account\n authorizedClients: AuthorizedClients\n }> {\n const accountRow = await accountHelper.getAccount(\n this.db,\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n asAtIdentifierString(sub),\n { includeDeactivated: true },\n )\n\n assert(accountRow, 'Account not found')\n\n const account = await this.buildAccount(accountRow)\n const authorizedClients = await authorizedClientHelper.getAuthorizedClients(\n this.db,\n sub,\n )\n\n return { account, authorizedClients }\n }\n\n async upsertDeviceAccount(deviceId: DeviceId, sub: string): Promise<void> {\n await this.db.executeWithRetry(\n accountDeviceHelper.upsertQB(this.db, deviceId, sub),\n )\n }\n\n async getDeviceAccount(\n deviceId: DeviceId,\n sub: string,\n ): Promise<DeviceAccount | null> {\n const row = await accountDeviceHelper\n .selectQB(this.db, { deviceId, sub })\n .executeTakeFirst()\n\n if (!row) return null\n\n return {\n deviceId,\n deviceData: deviceHelper.rowToDeviceData(row),\n account: await this.buildAccount(row),\n authorizedClients: await authorizedClientHelper.getAuthorizedClients(\n this.db,\n sub,\n ),\n createdAt: fromDateISO(row.adCreatedAt),\n updatedAt: fromDateISO(row.adUpdatedAt),\n }\n }\n\n async removeDeviceAccount(deviceId: DeviceId, sub: Sub): Promise<void> {\n await this.db.executeWithRetry(\n accountDeviceHelper.removeQB(this.db, deviceId, sub),\n )\n }\n\n async listDeviceAccounts(\n filter: { sub: Sub } | { deviceId: DeviceId },\n ): Promise<DeviceAccount[]> {\n const rows = await accountDeviceHelper.selectQB(this.db, filter).execute()\n\n const uniqueDids: string[] = [...new Set(rows.map((row) => row.did))]\n\n // Enrich all distinct account with their profile data\n const accounts = new Map(\n await Promise.all(\n Array.from(uniqueDids, async (did): Promise<[Sub, Account]> => {\n const row = rows.find((r) => r.did === did)!\n return [did, await this.buildAccount(row)]\n }),\n ),\n )\n\n const authorizedClientsMap =\n await authorizedClientHelper.getAuthorizedClientsMulti(\n this.db,\n uniqueDids,\n )\n\n return rows.map((row) => ({\n deviceId: row.deviceId,\n deviceData: deviceHelper.rowToDeviceData(row),\n account: accounts.get(row.did)!,\n authorizedClients: authorizedClientsMap.get(row.did)!,\n createdAt: fromDateISO(row.adCreatedAt),\n updatedAt: fromDateISO(row.adUpdatedAt),\n }))\n }\n\n async resetPasswordRequest({\n locale: _locale,\n email,\n }: ResetPasswordRequestInput): Promise<Account | null> {\n const account = await this.accountManager.getAccountByEmail(email, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account?.email || !account?.handle) return null\n\n const { handle } = account\n const token = await this.accountManager.createEmailToken(\n account.did,\n 'reset_password',\n )\n\n // @TODO Use the locale to send the email in the right language\n await this.mailer.sendResetPassword(\n { handle, token },\n { to: account.email },\n )\n\n return this.buildAccount(account)\n }\n\n async resetPasswordConfirm(\n data: ResetPasswordConfirmInput,\n ): Promise<Account | null> {\n try {\n const did = await this.accountManager.resetPassword(data)\n const account = await this.accountManager.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n return account ? this.buildAccount(account) : null\n } catch (err) {\n if (err instanceof XrpcInvalidRequestError) {\n return null\n }\n\n throw err\n }\n }\n\n async verifyHandleAvailability(handle: HandleString): Promise<void> {\n // @NOTE Handle validity & normalization already enforced by the OAuthProvider\n try {\n const normalized =\n await this.accountManager.normalizeAndValidateHandle(handle)\n\n // Should never happen (OAuthProvider should have already validated the\n // handle) This check is just a safeguard against future normalization\n // changes.\n if (normalized !== handle) {\n throw new HandleUnavailableError('syntax', 'Invalid handle')\n }\n\n const account = await this.accountManager.getAccount(normalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (account) {\n throw new HandleUnavailableError('taken')\n }\n } catch (err) {\n if (err instanceof XrpcInvalidRequestError) {\n throw err.customErrorName === 'HandleNotAvailable'\n ? new HandleUnavailableError('taken', err.message)\n : new HandleUnavailableError('syntax', err.message)\n }\n\n throw err\n }\n }\n\n // RequestStore\n\n async createRequest(id: RequestId, data: RequestData): Promise<void> {\n await this.db.executeWithRetry(\n authRequestHelper.createQB(this.db, id, data),\n )\n }\n\n async readRequest(id: RequestId): Promise<RequestData | null> {\n try {\n const row = await authRequestHelper.readQB(this.db, id).executeTakeFirst()\n if (!row) return null\n return authRequestHelper.rowToRequestData(row)\n } finally {\n // Take the opportunity to clean up expired requests. Do this after we got\n // the current (potentially expired) request data to allow the provider to\n // handle expired requests.\n this.backgroundQueue.add(async () => {\n await this.db.executeWithRetry(\n authRequestHelper.removeOldExpiredQB(this.db),\n )\n })\n }\n }\n\n async updateRequest(id: RequestId, data: UpdateRequestData): Promise<void> {\n await this.db.executeWithRetry(\n authRequestHelper.updateQB(this.db, id, data),\n )\n }\n\n async deleteRequest(id: RequestId): Promise<void> {\n await this.db.executeWithRetry(authRequestHelper.removeByIdQB(this.db, id))\n }\n\n async consumeRequestCode(code: Code): Promise<FoundRequestResult | null> {\n const row = await authRequestHelper\n .consumeByCodeQB(this.db, code)\n .executeTakeFirst()\n return row ? authRequestHelper.rowToFoundRequestResult(row) : null\n }\n\n // DeviceStore\n\n async createDevice(deviceId: DeviceId, data: DeviceData): Promise<void> {\n await this.db.executeWithRetry(\n deviceHelper.createQB(this.db, deviceId, data),\n )\n }\n\n async readDevice(deviceId: DeviceId): Promise<null | DeviceData> {\n const row = await deviceHelper.readQB(this.db, deviceId).executeTakeFirst()\n return row ? deviceHelper.rowToDeviceData(row) : null\n }\n\n async updateDevice(\n deviceId: DeviceId,\n data: Partial<DeviceData>,\n ): Promise<void> {\n await this.db.executeWithRetry(\n deviceHelper.updateQB(this.db, deviceId, data),\n )\n }\n\n async deleteDevice(deviceId: DeviceId): Promise<void> {\n // Will cascade to device_account (device_account_device_id_fk)\n await this.db.executeWithRetry(deviceHelper.removeQB(this.db, deviceId))\n }\n\n // LexiconStore\n\n async findLexicon(nsid: string): Promise<LexiconData | null> {\n return lexiconHelper.find(this.db, nsid)\n }\n\n async storeLexicon(nsid: string, data: LexiconData): Promise<void> {\n return lexiconHelper.upsert(this.db, nsid, data)\n }\n\n async deleteLexicon(nsid: string): Promise<void> {\n return lexiconHelper.remove(this.db, nsid)\n }\n\n // TokenStore\n\n async createToken(\n id: TokenId,\n data: TokenData,\n refreshToken?: RefreshToken,\n ): Promise<void> {\n await this.db.transaction(async (dbTxn) => {\n if (refreshToken) {\n const { count } = await usedRefreshTokenHelper\n .countQB(dbTxn, refreshToken)\n .executeTakeFirstOrThrow()\n\n if (count > 0) {\n throw new Error('Refresh token already in use')\n }\n }\n\n return tokenHelper.createQB(dbTxn, id, data, refreshToken).execute()\n })\n }\n\n async listAccountTokens(sub: Sub): Promise<TokenInfo[]> {\n const rows = await tokenHelper.findByQB(this.db, { did: sub }).execute()\n return Promise.all(rows.map((row) => this.toTokenInfo(row)))\n }\n\n async readToken(tokenId: TokenId): Promise<TokenInfo | null> {\n const row = await tokenHelper\n .findByQB(this.db, { tokenId })\n .executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n async deleteToken(tokenId: TokenId): Promise<void> {\n // Will cascade to used_refresh_token (used_refresh_token_fk)\n await this.db.executeWithRetry(tokenHelper.removeQB(this.db, tokenId))\n }\n\n async rotateToken(\n tokenId: TokenId,\n newTokenId: TokenId,\n newRefreshToken: RefreshToken,\n newData: NewTokenData,\n ): Promise<void> {\n const err = await this.db.transaction(async (dbTxn) => {\n const { id, currentRefreshToken } = await tokenHelper\n .forRotateQB(dbTxn, tokenId)\n .executeTakeFirstOrThrow()\n\n if (currentRefreshToken) {\n await usedRefreshTokenHelper\n .insertQB(dbTxn, id, currentRefreshToken)\n .execute()\n }\n\n const { count } = await usedRefreshTokenHelper\n .countQB(dbTxn, newRefreshToken)\n .executeTakeFirstOrThrow()\n\n if (count > 0) {\n // Do NOT throw (we don't want the transaction to be rolled back)\n return new Error('New refresh token already in use')\n }\n\n await tokenHelper\n .rotateQB(dbTxn, id, newTokenId, newRefreshToken, newData)\n .execute()\n })\n\n if (err) throw err\n }\n\n async findTokenByRefreshToken(\n refreshToken: RefreshToken,\n ): Promise<TokenInfo | null> {\n const used = await usedRefreshTokenHelper\n .findByTokenQB(this.db, refreshToken)\n .executeTakeFirst()\n\n const search = used\n ? { id: used.tokenId }\n : { currentRefreshToken: refreshToken }\n\n const row = await tokenHelper.findByQB(this.db, search).executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n async findTokenByCode(code: Code): Promise<TokenInfo | null> {\n const row = await tokenHelper.findByQB(this.db, { code }).executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n private async toTokenInfo(\n row: accountHelper.ActorAccount & Selectable<schemas.Token>,\n ): Promise<TokenInfo> {\n return {\n id: row.tokenId,\n data: tokenHelper.toTokenData(row),\n account: await this.buildAccount(row),\n currentRefreshToken: row.currentRefreshToken,\n }\n }\n\n private async buildAccount(\n row: accountHelper.ActorAccount,\n ): Promise<Account> {\n const account: Account = {\n sub: row.did,\n aud: this.serviceDid,\n email: row.email || undefined,\n email_verified: row.email ? row.emailConfirmedAt != null : undefined,\n preferred_username: row.handle || undefined,\n }\n\n if (!account.name || !account.picture) {\n const did = account.sub\n\n const profile = await this.actorStore\n .read(did, async (store) => {\n return store.record.getProfileRecord()\n })\n .catch((err) => {\n dbLogger.error({ err }, 'Failed to get profile record')\n return null // No need to propagate\n })\n\n if (profile) {\n const { avatar, displayName } = profile\n\n account.name ||= displayName\n account.picture ||= avatar\n ? this.imageUrlBuilder.build('avatar', did, getBlobCidString(avatar))\n : undefined\n }\n }\n\n return account\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../../src/account-manager/oauth-store.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport { Client, createOp as createPlcOp } from '@did-plc/lib'\nimport { Selectable } from 'kysely'\nimport { Keypair, Secp256k1Keypair } from '@atproto/crypto'\nimport {\n HandleString,\n asAtIdentifierString,\n getBlobCidString,\n isDidString,\n isHandleString,\n} from '@atproto/lex'\nimport {\n Account,\n AccountStore,\n AuthenticateAccountData,\n AuthorizedClientData,\n AuthorizedClients,\n ClientId,\n Code,\n DeviceAccount,\n DeviceData,\n DeviceId,\n DeviceStore,\n FoundRequestResult,\n HandleUnavailableError,\n InvalidCredentialsError,\n InvalidInviteCodeError,\n InvalidRequestError,\n LexiconData,\n LexiconStore,\n NewTokenData,\n RefreshToken,\n RequestData,\n RequestId,\n RequestStore,\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n Sub,\n TokenData,\n TokenId,\n TokenInfo,\n TokenStore,\n UpdateEmailConfirmInput,\n UpdateEmailRequestInput,\n UpdateEmailRequestOutput,\n UpdateRequestData,\n VerifyEmailConfirmInput,\n VerifyEmailRequestInput,\n} from '@atproto/oauth-provider'\nimport {\n AuthRequiredError as XrpcAuthRequiredError,\n InvalidRequestError as XrpcInvalidRequestError,\n} from '@atproto/xrpc-server'\nimport { ActorStore } from '../actor-store/actor-store.js'\nimport { BackgroundQueue } from '../background.js'\nimport { fromDateISO } from '../db/index.js'\nimport { ImageUrlBuilder } from '../image/image-url-builder.js'\nimport { dbLogger } from '../logger.js'\nimport { ServerMailer } from '../mailer/index.js'\nimport { Sequencer, syncEvtDataFromCommit } from '../sequencer/index.js'\nimport { AccountManager, InvalidPasswordError } from './account-manager.js'\nimport * as schemas from './db/schema/index.js'\nimport * as accountDeviceHelper from './helpers/account-device.js'\nimport * as accountHelper from './helpers/account.js'\nimport { AccountStatus, UserAlreadyExistsError } from './helpers/account.js'\nimport * as authRequestHelper from './helpers/authorization-request.js'\nimport * as authorizedClientHelper from './helpers/authorized-client.js'\nimport * as deviceHelper from './helpers/device.js'\nimport * as lexiconHelper from './helpers/lexicon.js'\nimport * as tokenHelper from './helpers/token.js'\nimport * as usedRefreshTokenHelper from './helpers/used-refresh-token.js'\n\n/**\n * This class' purpose is to implement the interface needed by the OAuthProvider\n * to interact with the account database (through the {@link AccountManager}).\n *\n * @note The use of this class assumes that there is no entryway.\n */\nexport class OAuthStore\n implements AccountStore, RequestStore, DeviceStore, LexiconStore, TokenStore\n{\n constructor(\n private readonly accountManager: AccountManager,\n private readonly actorStore: ActorStore,\n private readonly imageUrlBuilder: ImageUrlBuilder,\n private readonly backgroundQueue: BackgroundQueue,\n private readonly mailer: ServerMailer,\n private readonly sequencer: Sequencer,\n private readonly plcClient: Client,\n private readonly plcRotationKey: Keypair,\n private readonly publicUrl: string,\n private readonly recoveryDidKey: string | null,\n ) {}\n\n private get db() {\n const { db } = this.accountManager\n if (db.destroyed) throw new Error('Database connection is closed')\n return db\n }\n\n private get serviceDid() {\n return this.accountManager.serviceDid\n }\n\n private async verifyEmailAvailability(email: string): Promise<void> {\n // @NOTE Email validity & disposability check performed by the OAuthProvider\n\n const account = await this.accountManager.getAccountByEmail(email, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (account) {\n throw new InvalidRequestError(`Email already taken`)\n }\n }\n\n private async verifyInviteCode(code: string) {\n try {\n await this.accountManager.ensureInviteIsAvailable(code)\n } catch (err) {\n const message =\n err instanceof XrpcInvalidRequestError ? err.message : undefined\n throw new InvalidInviteCodeError(message, err)\n }\n }\n\n // AccountStore\n\n async createAccount({\n locale: _locale,\n inviteCode,\n handle,\n email,\n password,\n }: SignUpData): Promise<Account> {\n // @TODO Send an account creation confirmation email (+verification link) to the user (in their locale)\n // @NOTE Password strength & length already enforced by the OAuthProvider\n\n assert(isHandleString(handle), 'Handle must be a valid HandleString')\n\n await Promise.all([\n this.verifyEmailAvailability(email),\n this.verifyHandleAvailability(handle),\n !inviteCode || this.verifyInviteCode(inviteCode),\n ])\n\n // @TODO The code bellow should probably be refactored to be common with the\n // code of the `com.atproto.server.createAccount` XRPC endpoint.\n\n const signingKey = await Secp256k1Keypair.create({ exportable: true })\n const signingKeyDid = signingKey.did()\n\n const plcCreate = await createPlcOp({\n signingKey: signingKeyDid,\n rotationKeys: this.recoveryDidKey\n ? [this.recoveryDidKey, this.plcRotationKey.did()]\n : [this.plcRotationKey.did()],\n handle,\n pds: this.publicUrl,\n signer: this.plcRotationKey,\n })\n\n const { did, op } = plcCreate\n assert(isDidString(did), 'Generated DID is not a valid DidString')\n\n try {\n await this.actorStore.create(did, signingKey)\n try {\n const commit = await this.actorStore.transact(did, (actorTxn) =>\n actorTxn.repo.createRepo([]),\n )\n\n await this.plcClient.sendOperation(did, op)\n\n await this.accountManager.createAccount({\n did,\n handle,\n email,\n password,\n inviteCode,\n repoCid: commit.cid,\n repoRev: commit.rev,\n })\n try {\n await this.sequencer.sequenceIdentityEvt(did, handle)\n await this.sequencer.sequenceAccountEvt(did, AccountStatus.Active)\n await this.sequencer.sequenceCommit(did, commit)\n await this.sequencer.sequenceSyncEvt(\n did,\n syncEvtDataFromCommit(commit),\n )\n await this.accountManager.updateRepoRoot(did, commit.cid, commit.rev)\n await this.actorStore.clearReservedKeypair(signingKeyDid, did)\n\n const account = await this.accountManager.getAccount(did)\n if (!account) throw new Error('Account not found')\n\n return await this.buildAccount(account)\n } catch (err) {\n this.accountManager.deleteAccount(did)\n throw err\n }\n } catch (err) {\n await this.actorStore.destroy(did)\n throw err\n }\n } catch (err) {\n // XrpcError => OAuthError\n if (err instanceof XrpcInvalidRequestError) {\n throw new InvalidRequestError(err.message, err)\n }\n throw err\n }\n }\n\n async authenticateAccount({\n locale: _locale,\n username: identifier,\n password,\n // Not supported by the PDS (yet?)\n emailOtp = undefined,\n }: AuthenticateAccountData): Promise<Account> {\n // @TODO (?) Send an email to the user to notify them of the login attempt\n try {\n // Should never happen\n if (emailOtp != null) {\n throw new Error('Email OTP is not supported')\n }\n\n const { user, appPassword, isSoftDeleted } =\n await this.accountManager.login({ identifier, password })\n\n if (isSoftDeleted) {\n throw new InvalidRequestError('Account was taken down')\n }\n\n if (appPassword) {\n throw new InvalidRequestError('App passwords are not allowed')\n }\n\n return this.buildAccount(user)\n } catch (err) {\n // `InvalidPasswordError` is a subclass of `XrpcAuthRequiredError`,\n // so it must be checked first. Surfacing the matched `did` as the\n // `sub` lets the oauth-provider's `onSignInFailed` hook distinguish\n // \"identifier known, credentials wrong\" from \"identifier unknown\".\n if (err instanceof InvalidPasswordError) {\n throw new InvalidCredentialsError(err.message, err.did, err)\n }\n if (err instanceof XrpcAuthRequiredError) {\n throw new InvalidCredentialsError(err.message, undefined, err)\n }\n throw err\n }\n }\n\n async setAuthorizedClient(\n sub: Sub,\n clientId: ClientId,\n data: AuthorizedClientData,\n ): Promise<void> {\n await authorizedClientHelper.upsert(this.db, sub, clientId, data)\n }\n\n async getAccount(sub: Sub): Promise<{\n account: Account\n authorizedClients: AuthorizedClients\n }> {\n const accountRow = await accountHelper.getAccount(\n this.db,\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n asAtIdentifierString(sub),\n { includeDeactivated: true },\n )\n\n assert(accountRow, 'Account not found')\n\n const account = await this.buildAccount(accountRow)\n const authorizedClients = await authorizedClientHelper.getAuthorizedClients(\n this.db,\n sub,\n )\n\n return { account, authorizedClients }\n }\n\n async upsertDeviceAccount(deviceId: DeviceId, sub: string): Promise<void> {\n await this.db.executeWithRetry(\n accountDeviceHelper.upsertQB(this.db, deviceId, sub),\n )\n }\n\n async getDeviceAccount(\n deviceId: DeviceId,\n sub: string,\n ): Promise<DeviceAccount | null> {\n const row = await accountDeviceHelper\n .selectQB(this.db, { deviceId, sub })\n .executeTakeFirst()\n\n if (!row) return null\n\n return {\n deviceId,\n deviceData: deviceHelper.rowToDeviceData(row),\n account: await this.buildAccount(row),\n authorizedClients: await authorizedClientHelper.getAuthorizedClients(\n this.db,\n sub,\n ),\n createdAt: fromDateISO(row.adCreatedAt),\n updatedAt: fromDateISO(row.adUpdatedAt),\n }\n }\n\n async removeDeviceAccount(deviceId: DeviceId, sub: Sub): Promise<void> {\n await this.db.executeWithRetry(\n accountDeviceHelper.removeQB(this.db, deviceId, sub),\n )\n }\n\n async listDeviceAccounts(\n filter: { sub: Sub } | { deviceId: DeviceId },\n ): Promise<DeviceAccount[]> {\n const rows = await accountDeviceHelper.selectQB(this.db, filter).execute()\n\n const uniqueDids: string[] = [...new Set(rows.map((row) => row.did))]\n\n // Enrich all distinct account with their profile data\n const accounts = new Map(\n await Promise.all(\n Array.from(uniqueDids, async (did): Promise<[Sub, Account]> => {\n const row = rows.find((r) => r.did === did)!\n return [did, await this.buildAccount(row)]\n }),\n ),\n )\n\n const authorizedClientsMap =\n await authorizedClientHelper.getAuthorizedClientsMulti(\n this.db,\n uniqueDids,\n )\n\n return rows.map((row) => ({\n deviceId: row.deviceId,\n deviceData: deviceHelper.rowToDeviceData(row),\n account: accounts.get(row.did)!,\n authorizedClients: authorizedClientsMap.get(row.did)!,\n createdAt: fromDateISO(row.adCreatedAt),\n updatedAt: fromDateISO(row.adUpdatedAt),\n }))\n }\n\n async resetPasswordRequest({\n locale: _locale,\n email,\n }: ResetPasswordRequestInput): Promise<Account | null> {\n const account = await this.accountManager.getAccountByEmail(email, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (!account?.email || !account?.handle) return null\n\n const { handle } = account\n const token = await this.accountManager.createEmailToken(\n account.did,\n 'reset_password',\n )\n\n // @TODO Use the locale to send the email in the right language\n await this.mailer.sendResetPassword(\n { handle, token },\n { to: account.email },\n )\n\n return this.buildAccount(account)\n }\n\n async resetPasswordConfirm(\n data: ResetPasswordConfirmInput,\n ): Promise<Account | null> {\n try {\n const did = await this.accountManager.resetPassword(data)\n const account = await this.accountManager.getAccount(did, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n return account ? this.buildAccount(account) : null\n } catch (err) {\n if (err instanceof XrpcInvalidRequestError) {\n return null\n }\n\n throw err\n }\n }\n\n async verifyHandleAvailability(handle: HandleString): Promise<void> {\n // @NOTE Handle validity & normalization already enforced by the OAuthProvider\n try {\n const normalized =\n await this.accountManager.normalizeAndValidateHandle(handle)\n\n // Should never happen (OAuthProvider should have already validated the\n // handle) This check is just a safeguard against future normalization\n // changes.\n if (normalized !== handle) {\n throw new HandleUnavailableError('syntax', 'Invalid handle')\n }\n\n const account = await this.accountManager.getAccount(normalized, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n\n if (account) {\n throw new HandleUnavailableError('taken')\n }\n } catch (err) {\n if (err instanceof XrpcInvalidRequestError) {\n throw err.customErrorName === 'HandleNotAvailable'\n ? new HandleUnavailableError('taken', err.message)\n : new HandleUnavailableError('syntax', err.message)\n }\n\n throw err\n }\n }\n\n // RequestStore\n\n async createRequest(id: RequestId, data: RequestData): Promise<void> {\n await this.db.executeWithRetry(\n authRequestHelper.createQB(this.db, id, data),\n )\n }\n\n async readRequest(id: RequestId): Promise<RequestData | null> {\n try {\n const row = await authRequestHelper.readQB(this.db, id).executeTakeFirst()\n if (!row) return null\n return authRequestHelper.rowToRequestData(row)\n } finally {\n // Take the opportunity to clean up expired requests. Do this after we got\n // the current (potentially expired) request data to allow the provider to\n // handle expired requests.\n this.backgroundQueue.add(async () => {\n await this.db.executeWithRetry(\n authRequestHelper.removeOldExpiredQB(this.db),\n )\n })\n }\n }\n\n async updateRequest(id: RequestId, data: UpdateRequestData): Promise<void> {\n await this.db.executeWithRetry(\n authRequestHelper.updateQB(this.db, id, data),\n )\n }\n\n async deleteRequest(id: RequestId): Promise<void> {\n await this.db.executeWithRetry(authRequestHelper.removeByIdQB(this.db, id))\n }\n\n async consumeRequestCode(code: Code): Promise<FoundRequestResult | null> {\n const row = await authRequestHelper\n .consumeByCodeQB(this.db, code)\n .executeTakeFirst()\n return row ? authRequestHelper.rowToFoundRequestResult(row) : null\n }\n\n // DeviceStore\n\n async createDevice(deviceId: DeviceId, data: DeviceData): Promise<void> {\n await this.db.executeWithRetry(\n deviceHelper.createQB(this.db, deviceId, data),\n )\n }\n\n async readDevice(deviceId: DeviceId): Promise<null | DeviceData> {\n const row = await deviceHelper.readQB(this.db, deviceId).executeTakeFirst()\n return row ? deviceHelper.rowToDeviceData(row) : null\n }\n\n async updateDevice(\n deviceId: DeviceId,\n data: Partial<DeviceData>,\n ): Promise<void> {\n await this.db.executeWithRetry(\n deviceHelper.updateQB(this.db, deviceId, data),\n )\n }\n\n async deleteDevice(deviceId: DeviceId): Promise<void> {\n // Will cascade to device_account (device_account_device_id_fk)\n await this.db.executeWithRetry(deviceHelper.removeQB(this.db, deviceId))\n }\n\n // LexiconStore\n\n async findLexicon(nsid: string): Promise<LexiconData | null> {\n return lexiconHelper.find(this.db, nsid)\n }\n\n async storeLexicon(nsid: string, data: LexiconData): Promise<void> {\n return lexiconHelper.upsert(this.db, nsid, data)\n }\n\n async deleteLexicon(nsid: string): Promise<void> {\n return lexiconHelper.remove(this.db, nsid)\n }\n\n // TokenStore\n\n async createToken(\n id: TokenId,\n data: TokenData,\n refreshToken?: RefreshToken,\n ): Promise<void> {\n await this.db.transaction(async (dbTxn) => {\n if (refreshToken) {\n const { count } = await usedRefreshTokenHelper\n .countQB(dbTxn, refreshToken)\n .executeTakeFirstOrThrow()\n\n if (count > 0) {\n throw new Error('Refresh token already in use')\n }\n }\n\n return tokenHelper.createQB(dbTxn, id, data, refreshToken).execute()\n })\n }\n\n async listAccountTokens(sub: Sub): Promise<TokenInfo[]> {\n const rows = await tokenHelper.findByQB(this.db, { did: sub }).execute()\n return Promise.all(rows.map((row) => this.toTokenInfo(row)))\n }\n\n async readToken(tokenId: TokenId): Promise<TokenInfo | null> {\n const row = await tokenHelper\n .findByQB(this.db, { tokenId })\n .executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n async deleteToken(tokenId: TokenId): Promise<void> {\n // Will cascade to used_refresh_token (used_refresh_token_fk)\n await this.db.executeWithRetry(tokenHelper.removeQB(this.db, tokenId))\n }\n\n async rotateToken(\n tokenId: TokenId,\n newTokenId: TokenId,\n newRefreshToken: RefreshToken,\n newData: NewTokenData,\n ): Promise<void> {\n const err = await this.db.transaction(async (dbTxn) => {\n const { id, currentRefreshToken } = await tokenHelper\n .forRotateQB(dbTxn, tokenId)\n .executeTakeFirstOrThrow()\n\n if (currentRefreshToken) {\n await usedRefreshTokenHelper\n .insertQB(dbTxn, id, currentRefreshToken)\n .execute()\n }\n\n const { count } = await usedRefreshTokenHelper\n .countQB(dbTxn, newRefreshToken)\n .executeTakeFirstOrThrow()\n\n if (count > 0) {\n // Do NOT throw (we don't want the transaction to be rolled back)\n return new Error('New refresh token already in use')\n }\n\n await tokenHelper\n .rotateQB(dbTxn, id, newTokenId, newRefreshToken, newData)\n .execute()\n })\n\n if (err) throw err\n }\n\n async findTokenByRefreshToken(\n refreshToken: RefreshToken,\n ): Promise<TokenInfo | null> {\n const used = await usedRefreshTokenHelper\n .findByTokenQB(this.db, refreshToken)\n .executeTakeFirst()\n\n const search = used\n ? { id: used.tokenId }\n : { currentRefreshToken: refreshToken }\n\n const row = await tokenHelper.findByQB(this.db, search).executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n async findTokenByCode(code: Code): Promise<TokenInfo | null> {\n const row = await tokenHelper.findByQB(this.db, { code }).executeTakeFirst()\n return row ? this.toTokenInfo(row) : null\n }\n\n async verifyEmailRequest({\n sub: did,\n locale,\n }: VerifyEmailRequestInput): Promise<void> {\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n assert(isDidString(did), 'sub must be a valid DID string')\n\n try {\n await this.accountManager.requestEmailConfirmation(did, { locale })\n } catch (err) {\n if (err instanceof XrpcAuthRequiredError) {\n throw new InvalidRequestError(err.message, err)\n }\n\n throw err\n }\n }\n\n async verifyEmailConfirm({\n sub: did,\n email,\n token,\n }: VerifyEmailConfirmInput): Promise<Account | null> {\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n assert(isDidString(did), 'sub must be a valid DID string')\n\n try {\n const account = await this.accountManager.confirmEmail(did, email, token)\n\n return this.buildAccount(account)\n } catch (err) {\n if (err instanceof XrpcInvalidRequestError) {\n return null\n }\n\n throw err\n }\n }\n\n async updateEmailRequest({\n sub: did,\n locale,\n }: UpdateEmailRequestInput): Promise<UpdateEmailRequestOutput> {\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n assert(isDidString(did), 'sub must be a valid DID string')\n\n return this.accountManager.requestEmailUpdate(did, { locale })\n }\n\n async updateEmailConfirm({\n sub: did,\n token,\n email,\n locale,\n }: UpdateEmailConfirmInput): Promise<Account | null> {\n // @TODO @atproto/oauth-provider should strongly type `Sub` as `DidString`\n assert(isDidString(did), 'sub must be a valid DID string')\n\n try {\n const account = await this.accountManager.updateEmail(did, email, token, {\n sendConfirmationEmail: true,\n locale,\n })\n\n return this.buildAccount(account)\n } catch (cause) {\n if (cause instanceof UserAlreadyExistsError) {\n throw new InvalidRequestError(cause.message, cause)\n }\n\n throw cause\n }\n }\n\n private async toTokenInfo(\n row: accountHelper.ActorAccount & Selectable<schemas.Token>,\n ): Promise<TokenInfo> {\n return {\n id: row.tokenId,\n data: tokenHelper.toTokenData(row),\n account: await this.buildAccount(row),\n currentRefreshToken: row.currentRefreshToken,\n }\n }\n\n private async buildAccount(\n row: accountHelper.ActorAccount,\n ): Promise<Account> {\n const account: Account = {\n sub: row.did,\n aud: this.serviceDid,\n email: row.email || undefined,\n email_verified: row.email ? row.emailConfirmedAt != null : undefined,\n preferred_username: row.handle || undefined,\n }\n\n if (!account.name || !account.picture) {\n const did = account.sub\n\n const profile = await this.actorStore\n .read(did, async (store) => {\n return store.record.getProfileRecord()\n })\n .catch((err) => {\n dbLogger.error({ err }, 'Failed to get profile record')\n return null // No need to propagate\n })\n\n if (profile) {\n const { avatar, displayName } = profile\n\n account.name ||= displayName\n account.picture ||= avatar\n ? this.imageUrlBuilder.build('avatar', did, getBlobCidString(avatar))\n : undefined\n }\n }\n\n return account\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreferences.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/getPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"getPreferences.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/getPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAQnD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA8CvD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AuthScope, isAccessFull } from '../../../../auth-scope.js';
|
|
2
2
|
import { app } from '../../../../lexicons/index.js';
|
|
3
|
-
import { computeProxyTo, pipethrough } from '../../../../pipethrough.js';
|
|
3
|
+
import { bareDidFromProxyTo, computeProxyTo, pipethrough, } from '../../../../pipethrough.js';
|
|
4
4
|
export default function (server, ctx) {
|
|
5
5
|
const { bskyAppView } = ctx;
|
|
6
6
|
if (!bskyAppView)
|
|
@@ -22,7 +22,12 @@ export default function (server, ctx) {
|
|
|
22
22
|
const lxm = app.bsky.actor.getPreferences.$lxm;
|
|
23
23
|
const aud = computeProxyTo(ctx, req, lxm);
|
|
24
24
|
if (aud !== `${bskyAppView.did}#bsky_appview`) {
|
|
25
|
-
|
|
25
|
+
// Phase 1 of service auth updates: outbound JWT keeps bare-DID aud.
|
|
26
|
+
return pipethrough(ctx, req, {
|
|
27
|
+
iss: did,
|
|
28
|
+
aud: bareDidFromProxyTo(aud),
|
|
29
|
+
lxm,
|
|
30
|
+
});
|
|
26
31
|
}
|
|
27
32
|
const hasAccessFull = auth.credentials.type === 'access' &&
|
|
28
33
|
isAccessFull(auth.credentials.scope);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPreferences.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/getPreferences.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAEnE,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"getPreferences.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/getPreferences.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAEnE,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,GACZ,MAAM,4BAA4B,CAAA;AAEnC,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,CAAA;IAC3B,IAAI,CAAC,WAAW;QAAE,OAAM;IAExB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;QACxC,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;YACnC,UAAU,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC;YACjC,SAAS,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;gBAClC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAA;gBAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;gBACzC,WAAW,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;YACrC,CAAC;SACF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;YAC/B,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAA;YAEhC,sEAAsE;YACtE,0DAA0D;YAC1D,8EAA8E;YAC9E,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAA;YAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACzC,IAAI,GAAG,KAAK,GAAG,WAAW,CAAC,GAAG,eAAe,EAAE,CAAC;gBAC9C,oEAAoE;gBACpE,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;oBAC3B,GAAG,EAAE,GAAG;oBACR,GAAG,EAAE,kBAAkB,CAAC,GAAG,CAAC;oBAC5B,GAAG;iBACJ,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,aAAa,GACjB,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ;gBAClC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;YAEtC,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;oBAC3C,aAAa;iBACd,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YAEF,OAAO;gBACL,QAAQ,EAAE,kBAA2B;gBACrC,IAAI,EAAE,EAAE,WAAW,EAAE;aACtB,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Server } from '@atproto/xrpc-server'\nimport { AuthScope, isAccessFull } from '../../../../auth-scope.js'\nimport { AppContext } from '../../../../context.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n bareDidFromProxyTo,\n computeProxyTo,\n pipethrough,\n} from '../../../../pipethrough.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const { bskyAppView } = ctx\n if (!bskyAppView) return\n\n server.add(app.bsky.actor.getPreferences, {\n auth: ctx.authVerifier.authorization({\n additional: [AuthScope.Takendown],\n authorize: (permissions, { req }) => {\n const lxm = app.bsky.actor.getPreferences.$lxm\n const aud = computeProxyTo(ctx, req, lxm)\n permissions.assertRpc({ aud, lxm })\n },\n }),\n handler: async ({ auth, req }) => {\n const { did } = auth.credentials\n\n // If the request has a proxy header different from the bsky app view,\n // we need to proxy the request to the requested app view.\n // @TODO This behavior should not be implemented as part of the XRPC framework\n const lxm = app.bsky.actor.getPreferences.$lxm\n const aud = computeProxyTo(ctx, req, lxm)\n if (aud !== `${bskyAppView.did}#bsky_appview`) {\n // Phase 1 of service auth updates: outbound JWT keeps bare-DID aud.\n return pipethrough(ctx, req, {\n iss: did,\n aud: bareDidFromProxyTo(aud),\n lxm,\n })\n }\n\n const hasAccessFull =\n auth.credentials.type === 'access' &&\n isAccessFull(auth.credentials.scope)\n\n const preferences = await ctx.actorStore.read(did, (store) => {\n return store.pref.getPreferences('app.bsky', {\n hasAccessFull,\n })\n })\n\n return {\n encoding: 'application/json' as const,\n body: { preferences },\n }\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"putPreferences.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/putPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAGlE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"putPreferences.d.ts","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/putPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAGlE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAQnD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAkDvD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InvalidRequestError } from '@atproto/xrpc-server';
|
|
2
2
|
import { isAccessFull } from '../../../../auth-scope.js';
|
|
3
3
|
import { app } from '../../../../lexicons/index.js';
|
|
4
|
-
import { computeProxyTo, pipethrough } from '../../../../pipethrough.js';
|
|
4
|
+
import { bareDidFromProxyTo, computeProxyTo, pipethrough, } from '../../../../pipethrough.js';
|
|
5
5
|
export default function (server, ctx) {
|
|
6
6
|
const { bskyAppView } = ctx;
|
|
7
7
|
if (!bskyAppView)
|
|
@@ -23,7 +23,12 @@ export default function (server, ctx) {
|
|
|
23
23
|
const lxm = app.bsky.actor.putPreferences.$lxm;
|
|
24
24
|
const aud = computeProxyTo(ctx, req, lxm);
|
|
25
25
|
if (aud !== `${bskyAppView.did}#bsky_appview`) {
|
|
26
|
-
|
|
26
|
+
// Phase 1 of service auth updates: outbound JWT keeps bare-DID aud.
|
|
27
|
+
return pipethrough(ctx, req, {
|
|
28
|
+
iss: did,
|
|
29
|
+
aud: bareDidFromProxyTo(aud),
|
|
30
|
+
lxm,
|
|
31
|
+
});
|
|
27
32
|
}
|
|
28
33
|
const checkedPreferences = [];
|
|
29
34
|
for (const pref of input.body.preferences) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"putPreferences.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/putPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAU,MAAM,sBAAsB,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAExD,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"putPreferences.js","sourceRoot":"","sources":["../../../../../src/api/app/bsky/actor/putPreferences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAU,MAAM,sBAAsB,CAAA;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAExD,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,GACZ,MAAM,4BAA4B,CAAA;AAEnC,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,CAAA;IAC3B,IAAI,CAAC,WAAW;QAAE,OAAM;IAExB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;QACxC,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;YACnC,aAAa,EAAE,IAAI;YACnB,SAAS,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;gBAClC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAA;gBAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;gBACzC,WAAW,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;YACrC,CAAC;SACF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;YACtC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAA;YAEhC,sEAAsE;YACtE,0DAA0D;YAC1D,8EAA8E;YAC9E,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAA;YAC9C,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;YACzC,IAAI,GAAG,KAAK,GAAG,WAAW,CAAC,GAAG,eAAe,EAAE,CAAC;gBAC9C,oEAAoE;gBACpE,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;oBAC3B,GAAG,EAAE,GAAG;oBACR,GAAG,EAAE,kBAAkB,CAAC,GAAG,CAAC;oBAC5B,GAAG;iBACJ,CAAC,CAAA;YACJ,CAAC;YAED,MAAM,kBAAkB,GAAwB,EAAE,CAAA;YAClD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1C,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACnC,kBAAkB,CAAC,IAAI,CAAC,IAAyB,CAAC,CAAA;gBACpD,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,mBAAmB,CAAC,+BAA+B,CAAC,CAAA;gBAChE,CAAC;YACH,CAAC;YAED,MAAM,aAAa,GACjB,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,QAAQ;gBAClC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;YAEtC,MAAM,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACpD,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,UAAU,EAAE;oBACjE,aAAa;iBACd,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { InvalidRequestError, Server } from '@atproto/xrpc-server'\nimport { AccountPreference } from '../../../../actor-store/preference/reader.js'\nimport { isAccessFull } from '../../../../auth-scope.js'\nimport { AppContext } from '../../../../context.js'\nimport { app } from '../../../../lexicons/index.js'\nimport {\n bareDidFromProxyTo,\n computeProxyTo,\n pipethrough,\n} from '../../../../pipethrough.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const { bskyAppView } = ctx\n if (!bskyAppView) return\n\n server.add(app.bsky.actor.putPreferences, {\n auth: ctx.authVerifier.authorization({\n checkTakedown: true,\n authorize: (permissions, { req }) => {\n const lxm = app.bsky.actor.putPreferences.$lxm\n const aud = computeProxyTo(ctx, req, lxm)\n permissions.assertRpc({ aud, lxm })\n },\n }),\n handler: async ({ req, auth, input }) => {\n const { did } = auth.credentials\n\n // If the request has a proxy header different from the bsky app view,\n // we need to proxy the request to the requested app view.\n // @TODO This behavior should not be implemented as part of the XRPC framework\n const lxm = app.bsky.actor.putPreferences.$lxm\n const aud = computeProxyTo(ctx, req, lxm)\n if (aud !== `${bskyAppView.did}#bsky_appview`) {\n // Phase 1 of service auth updates: outbound JWT keeps bare-DID aud.\n return pipethrough(ctx, req, {\n iss: did,\n aud: bareDidFromProxyTo(aud),\n lxm,\n })\n }\n\n const checkedPreferences: AccountPreference[] = []\n for (const pref of input.body.preferences) {\n if (typeof pref.$type === 'string') {\n checkedPreferences.push(pref as AccountPreference)\n } else {\n throw new InvalidRequestError('Preference is missing a $type')\n }\n }\n\n const hasAccessFull =\n auth.credentials.type === 'access' &&\n isAccessFull(auth.credentials.scope)\n\n await ctx.actorStore.transact(did, async (actorTxn) => {\n await actorTxn.pref.putPreferences(checkedPreferences, 'app.bsky', {\n hasAccessFull,\n })\n })\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateAccountEmail.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/admin/updateAccountEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAU,MAAM,sBAAsB,CAAA;AAElE,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AAEnD,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC/C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,UAAU;QACjC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE;gBAChE,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAA;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,mBAAmB,CAAC,2BAA2B,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;YAC1E,CAAC;YAED,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACvB,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;gBACpD,MAAM,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE;oBAClE,OAAO;oBACP,IAAI;iBACL,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,MAAM,GAAG,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"updateAccountEmail.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/admin/updateAccountEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAU,MAAM,sBAAsB,CAAA;AAElE,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AAEnD,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE;QAC/C,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,UAAU;QACjC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YAC1C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE;gBAChE,kBAAkB,EAAE,IAAI;gBACxB,gBAAgB,EAAE,IAAI;aACvB,CAAC,CAAA;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,mBAAmB,CAAC,2BAA2B,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;YAC1E,CAAC;YAED,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACvB,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;gBACpD,MAAM,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE;oBAClE,OAAO;oBACP,IAAI;iBACL,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,MAAM,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC;gBAC1C,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { InvalidRequestError, Server } from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context.js'\nimport { com } from '../../../../lexicons/index.js'\n\nexport default function (server: Server, ctx: AppContext) {\n server.add(com.atproto.admin.updateAccountEmail, {\n auth: ctx.authVerifier.adminToken,\n handler: async ({ input: { body }, req }) => {\n const account = await ctx.accountManager.getAccount(body.account, {\n includeDeactivated: true,\n includeTakenDown: true,\n })\n if (!account) {\n throw new InvalidRequestError(`Account does not exist: ${body.account}`)\n }\n\n if (ctx.entrywayClient) {\n const { headers } = ctx.entrywayPassthruHeaders(req)\n await ctx.entrywayClient.xrpc(com.atproto.admin.updateAccountEmail, {\n headers,\n body,\n })\n return\n }\n\n await ctx.accountManager.updateAccountEmail({\n did: account.did,\n email: body.email,\n })\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmEmail.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/confirmEmail.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"confirmEmail.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/confirmEmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAInD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAiCvD"}
|
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
import { InvalidRequestError } from '@atproto/xrpc-server';
|
|
2
1
|
import { com } from '../../../../lexicons/index.js';
|
|
2
|
+
import { requestEmailConfirmationAuth } from './requestEmailConfirmation.js';
|
|
3
3
|
export default function (server, ctx) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
handler: async ({ auth, input: { body }, req }) => {
|
|
12
|
-
const { did } = auth.credentials;
|
|
13
|
-
const user = await ctx.accountManager.getAccount(did, {
|
|
14
|
-
includeDeactivated: true,
|
|
15
|
-
});
|
|
16
|
-
if (!user) {
|
|
17
|
-
throw new InvalidRequestError('user not found', 'AccountNotFound');
|
|
18
|
-
}
|
|
19
|
-
if (ctx.entrywayClient) {
|
|
4
|
+
const { entrywayClient } = ctx;
|
|
5
|
+
// @NOTE Ensure that both endpoints use the same authentication logic
|
|
6
|
+
const auth = requestEmailConfirmationAuth(ctx);
|
|
7
|
+
if (entrywayClient) {
|
|
8
|
+
server.add(com.atproto.server.confirmEmail, {
|
|
9
|
+
auth,
|
|
10
|
+
handler: async ({ auth, input: { body }, req }) => {
|
|
20
11
|
const { headers } = await ctx.entrywayAuthHeaders(req, auth.credentials.did, com.atproto.server.confirmEmail.$lxm);
|
|
21
|
-
await
|
|
12
|
+
await entrywayClient.xrpc(com.atproto.server.confirmEmail, {
|
|
22
13
|
headers,
|
|
23
14
|
body,
|
|
24
15
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
server.add(com.atproto.server.confirmEmail, {
|
|
21
|
+
auth,
|
|
22
|
+
handler: async ({ auth, input: { body } }) => {
|
|
23
|
+
await ctx.accountManager.confirmEmail(auth.credentials.did, body.email, body.token);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
34
27
|
}
|
|
35
28
|
//# sourceMappingURL=confirmEmail.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmEmail.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/confirmEmail.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"confirmEmail.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/confirmEmail.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AACnD,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAE5E,MAAM,CAAC,OAAO,WAAW,MAAc,EAAE,GAAe;IACtD,MAAM,EAAE,cAAc,EAAE,GAAG,GAAG,CAAA;IAE9B,qEAAqE;IACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,GAAG,CAAC,CAAA;IAE9C,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE;YAC1C,IAAI;YACJ,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;gBAChD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAC,mBAAmB,CAC/C,GAAG,EACH,IAAI,CAAC,WAAW,CAAC,GAAG,EACpB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CACrC,CAAA;gBACD,MAAM,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE;oBACzD,OAAO;oBACP,IAAI;iBACL,CAAC,CAAA;YACJ,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE;YAC1C,IAAI;YACJ,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBAC3C,MAAM,GAAG,CAAC,cAAc,CAAC,YAAY,CACnC,IAAI,CAAC,WAAW,CAAC,GAAG,EACpB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,KAAK,CACX,CAAA;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;AACH,CAAC","sourcesContent":["import { Server } from '@atproto/xrpc-server'\nimport { AppContext } from '../../../../context.js'\nimport { com } from '../../../../lexicons/index.js'\nimport { requestEmailConfirmationAuth } from './requestEmailConfirmation.js'\n\nexport default function (server: Server, ctx: AppContext) {\n const { entrywayClient } = ctx\n\n // @NOTE Ensure that both endpoints use the same authentication logic\n const auth = requestEmailConfirmationAuth(ctx)\n\n if (entrywayClient) {\n server.add(com.atproto.server.confirmEmail, {\n auth,\n handler: async ({ auth, input: { body }, req }) => {\n const { headers } = await ctx.entrywayAuthHeaders(\n req,\n auth.credentials.did,\n com.atproto.server.confirmEmail.$lxm,\n )\n await entrywayClient.xrpc(com.atproto.server.confirmEmail, {\n headers,\n body,\n })\n },\n })\n } else {\n server.add(com.atproto.server.confirmEmail, {\n auth,\n handler: async ({ auth, input: { body } }) => {\n await ctx.accountManager.confirmEmail(\n auth.credentials.did,\n body.email,\n body.token,\n )\n },\n })\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getServiceAuth.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/getServiceAuth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getServiceAuth.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/getServiceAuth.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,MAAM,EAEP,MAAM,sBAAsB,CAAA;AAM7B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAOnD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QA0FvD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HOUR, MINUTE } from '@atproto/common';
|
|
2
|
+
import { isAtprotoDid, isAtprotoDidRefAbsolute } from '@atproto/did';
|
|
2
3
|
import { InvalidRequestError, createServiceJwt, } from '@atproto/xrpc-server';
|
|
3
4
|
import { AuthScope, isAccessPrivileged, isTakendown, } from '../../../../auth-scope.js';
|
|
4
5
|
import { com } from '../../../../lexicons/index.js';
|
|
@@ -16,6 +17,9 @@ export default function (server, ctx) {
|
|
|
16
17
|
const did = auth.credentials.did;
|
|
17
18
|
// @NOTE "exp" is expressed in seconds since epoch, not milliseconds
|
|
18
19
|
const { aud, exp, lxm = null } = params;
|
|
20
|
+
if (!isAtprotoDid(aud) && !isAtprotoDidRefAbsolute(aud)) {
|
|
21
|
+
throw new InvalidRequestError('aud must be a valid atproto DID or did#serviceId reference');
|
|
22
|
+
}
|
|
19
23
|
// Takendown accounts should not be able to generate service auth tokens except for methods necessary for account migration
|
|
20
24
|
if (auth.credentials.type === 'access') {
|
|
21
25
|
// @NOTE We should probably use "ForbiddenError" here. Using
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getServiceAuth.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/getServiceAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"getServiceAuth.js","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/getServiceAuth.ts"],"names":[],"mappings":"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","sourcesContent":["import { HOUR, MINUTE } from '@atproto/common'\nimport { isAtprotoDid, isAtprotoDidRefAbsolute } from '@atproto/did'\nimport { l } from '@atproto/lex'\nimport {\n InvalidRequestError,\n Server,\n createServiceJwt,\n} from '@atproto/xrpc-server'\nimport {\n AuthScope,\n isAccessPrivileged,\n isTakendown,\n} from '../../../../auth-scope.js'\nimport { AppContext } from '../../../../context.js'\nimport { com } from '../../../../lexicons/index.js'\nimport {\n PRIVILEGED_METHODS,\n PROTECTED_METHODS,\n} from '../../../../pipethrough.js'\n\nexport default function (server: Server, ctx: AppContext) {\n server.add(com.atproto.server.getServiceAuth, {\n auth: ctx.authVerifier.authorization<\n l.InferMethodParams<typeof com.atproto.server.getServiceAuth.main>\n >({\n additional: [AuthScope.Takendown],\n authorize: (permissions, { params }) => {\n const { aud, lxm = '*' } = params\n permissions.assertRpc({ aud, lxm })\n },\n }),\n handler: async ({ params, auth }) => {\n const did = auth.credentials.did\n\n // @NOTE \"exp\" is expressed in seconds since epoch, not milliseconds\n const { aud, exp, lxm = null } = params\n\n if (!isAtprotoDid(aud) && !isAtprotoDidRefAbsolute(aud)) {\n throw new InvalidRequestError(\n 'aud must be a valid atproto DID or did#serviceId reference',\n )\n }\n\n // Takendown accounts should not be able to generate service auth tokens except for methods necessary for account migration\n if (auth.credentials.type === 'access') {\n // @NOTE We should probably use \"ForbiddenError\" here. Using\n // \"InvalidRequestError\" for legacy reasons.\n if (\n isTakendown(auth.credentials.scope) &&\n lxm !== com.atproto.server.createAccount.$lxm\n ) {\n throw new InvalidRequestError('Bad token scope', 'InvalidToken')\n }\n\n // @NOTE \"oauth\" based credentials already checked through permission\n // set in \"authorize\" method above.\n if (\n lxm != null &&\n PRIVILEGED_METHODS.has(lxm) &&\n !isAccessPrivileged(auth.credentials.scope)\n ) {\n throw new InvalidRequestError(\n `insufficient access to request a service auth token for the following method: ${lxm}`,\n )\n }\n }\n\n if (exp) {\n const diff = exp * 1000 - Date.now()\n if (diff < 0) {\n throw new InvalidRequestError(\n 'expiration is in past',\n 'BadExpiration',\n )\n } else if (diff > HOUR) {\n throw new InvalidRequestError(\n 'cannot request a token with an expiration more than an hour in the future',\n 'BadExpiration',\n )\n } else if (!lxm && diff > MINUTE) {\n throw new InvalidRequestError(\n 'cannot request a method-less token with an expiration more than a minute in the future',\n 'BadExpiration',\n )\n }\n }\n\n if (lxm && PROTECTED_METHODS.has(lxm)) {\n throw new InvalidRequestError(\n `cannot request a service auth token for the following protected method: ${lxm}`,\n )\n }\n\n const keypair = await ctx.actorStore.keypair(did)\n\n const token = await createServiceJwt({\n iss: did,\n aud,\n exp,\n lxm,\n keypair,\n })\n return {\n encoding: 'application/json' as const,\n body: {\n token,\n },\n }\n },\n })\n}\n"]}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { Server } from '@atproto/xrpc-server';
|
|
1
|
+
import { MethodAuthVerifier, Server } from '@atproto/xrpc-server';
|
|
2
|
+
import { AccessOutput, OAuthOutput } from '../../../../auth-output.js';
|
|
2
3
|
import { AppContext } from '../../../../context.js';
|
|
4
|
+
export declare function requestEmailConfirmationAuth(ctx: AppContext): MethodAuthVerifier<AccessOutput | OAuthOutput>;
|
|
3
5
|
export default function (server: Server, ctx: AppContext): void;
|
|
4
6
|
//# sourceMappingURL=requestEmailConfirmation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestEmailConfirmation.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/requestEmailConfirmation.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"requestEmailConfirmation.d.ts","sourceRoot":"","sources":["../../../../../src/api/com/atproto/server/requestEmailConfirmation.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAElB,MAAM,EACP,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAInD,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,UAAU,GACd,kBAAkB,CAAC,YAAY,GAAG,WAAW,CAAC,CAOhD;AAeD,MAAM,CAAC,OAAO,WAAW,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,QAgCvD"}
|