@atproto/oauth-provider 0.13.2 → 0.13.4
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 +25 -0
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +20 -2
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +2 -2
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +23 -52
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-utils.d.ts.map +1 -1
- package/dist/client/client-utils.js +1 -2
- package/dist/client/client-utils.js.map +1 -1
- package/dist/metadata/build-metadata.js +4 -3
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-hooks.d.ts +20 -0
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/router/assets/send-authorization-page.d.ts.map +1 -1
- package/dist/router/assets/send-authorization-page.js +3 -0
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/package.json +7 -7
- package/src/account/account-manager.ts +24 -2
- package/src/account/account-store.ts +7 -2
- package/src/client/client-manager.ts +25 -69
- package/src/client/client-utils.ts +1 -1
- package/src/metadata/build-metadata.ts +4 -4
- package/src/oauth-hooks.ts +22 -0
- package/src/router/assets/send-authorization-page.ts +3 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/client/client-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { Jwks, Keyset, jwksPubSchema } from '@atproto/jwk'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthClientIdDiscoverable,\n OAuthClientIdLoopback,\n OAuthClientMetadata,\n OAuthClientMetadataInput,\n isLoopbackHost,\n isOAuthClientIdDiscoverable,\n isOAuthClientIdLoopback,\n oauthClientMetadataSchema,\n} from '@atproto/oauth-types'\nimport {\n Fetch,\n bindFetch,\n fetchJsonProcessor,\n fetchJsonZodProcessor,\n fetchOkProcessor,\n} from '@atproto-labs/fetch'\nimport { isLocalHostname } from '@atproto-labs/fetch-node'\nimport { pipe } from '@atproto-labs/pipe'\nimport {\n CachedGetter,\n GetCachedOptions,\n SimpleStore,\n} from '@atproto-labs/simple-store'\nimport { InvalidClientMetadataError } from '../errors/invalid-client-metadata-error.js'\nimport { InvalidRedirectUriError } from '../errors/invalid-redirect-uri-error.js'\nimport { callAsync } from '../lib/util/function.js'\nimport { Awaitable } from '../lib/util/type.js'\nimport { OAuthHooks } from '../oauth-hooks.js'\nimport { ClientId } from './client-id.js'\nimport { ClientStore } from './client-store.js'\nimport { parseDiscoverableClientId, parseRedirectUri } from './client-utils.js'\nimport { Client } from './client.js'\n\nconst fetchMetadataHandler = pipe(\n fetchOkProcessor(),\n // https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html#section-4.1\n fetchJsonProcessor('application/json', true),\n fetchJsonZodProcessor(oauthClientMetadataSchema),\n)\n\nconst fetchJwksHandler = pipe(\n fetchOkProcessor(),\n fetchJsonProcessor('application/json', false),\n fetchJsonZodProcessor(jwksPubSchema),\n)\n\nexport type LoopbackMetadataGetter = (\n url: string,\n) => Awaitable<OAuthClientMetadataInput>\n\nexport class ClientManager {\n protected readonly jwks: CachedGetter<string, Jwks>\n protected readonly metadataGetter: CachedGetter<string, OAuthClientMetadata>\n\n constructor(\n protected readonly serverMetadata: OAuthAuthorizationServerMetadata,\n protected readonly keyset: Keyset,\n protected readonly hooks: OAuthHooks,\n protected readonly store: ClientStore | null,\n protected readonly loopbackMetadata: LoopbackMetadataGetter | null = null,\n safeFetch: Fetch,\n clientJwksCache: SimpleStore<string, Jwks>,\n clientMetadataCache: SimpleStore<string, OAuthClientMetadata>,\n ) {\n const fetch = bindFetch(safeFetch)\n\n this.jwks = new CachedGetter(async (uri, options) => {\n const jwks = await fetch(buildJsonGetRequest(uri, options)).then(\n fetchJwksHandler,\n )\n\n return jwks\n }, clientJwksCache)\n\n this.metadataGetter = new CachedGetter(async (uri, options) => {\n const metadata = await fetch(buildJsonGetRequest(uri, options)).then(\n fetchMetadataHandler,\n )\n\n // Validate within the getter to avoid caching invalid metadata\n return this.validateClientMetadata(uri, metadata)\n }, clientMetadataCache)\n }\n\n /**\n *\n * @see {@link https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2 OIDC Client Registration}\n */\n public async getClient(clientId: ClientId) {\n const metadata = await this.getClientMetadata(clientId).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Unable to obtain client metadata for \"${clientId}\"`,\n )\n })\n\n const jwks = metadata.jwks_uri\n ? await this.jwks.get(metadata.jwks_uri).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Unable to obtain jwks from \"${metadata.jwks_uri}\" for \"${clientId}\"`,\n )\n })\n : undefined\n\n const partialInfo = await callAsync(this.hooks.getClientInfo, clientId, {\n metadata,\n jwks,\n }).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Rejected client information for \"${clientId}\"`,\n )\n })\n\n const isFirstParty = partialInfo?.isFirstParty ?? false\n const isTrusted = partialInfo?.isTrusted ?? isFirstParty\n\n return new Client(clientId, metadata, jwks, { isFirstParty, isTrusted })\n }\n\n public async loadClients(\n clientIds: Iterable<ClientId>,\n {\n onError = (err) => {\n throw err\n },\n }: {\n onError?: (\n err: unknown,\n clientId: ClientId,\n ) => Awaitable<Client | null | undefined>\n } = {},\n ): Promise<Map<ClientId, Client>> {\n // Make sure we don't load the same client multiple times\n const uniqueClientIds =\n clientIds instanceof Set ? clientIds : new Set(clientIds)\n\n // Load all (unique) clients in parallel\n const clients = await Promise.all(\n Array.from(uniqueClientIds, async (clientId) =>\n this.getClient(clientId).catch((err) => onError(err, clientId)),\n ),\n )\n\n // Return a map for easy lookups\n return new Map(\n clients\n .filter((c) => c != null && c instanceof Client)\n .map((c) => [c.id, c]),\n )\n }\n\n protected async getClientMetadata(\n clientId: ClientId,\n ): Promise<OAuthClientMetadata> {\n if (isOAuthClientIdLoopback(clientId)) {\n return this.getLoopbackClientMetadata(clientId)\n } else if (isOAuthClientIdDiscoverable(clientId)) {\n return this.getDiscoverableClientMetadata(clientId)\n } else if (this.store) {\n return this.getStoredClientMetadata(clientId)\n }\n\n throw new InvalidClientMetadataError(`Invalid client ID \"${clientId}\"`)\n }\n\n protected async getLoopbackClientMetadata(\n clientId: OAuthClientIdLoopback,\n ): Promise<OAuthClientMetadata> {\n const { loopbackMetadata } = this\n if (!loopbackMetadata) {\n throw new InvalidClientMetadataError('Loopback clients are not allowed')\n }\n\n const metadataRaw = await callAsync(loopbackMetadata, clientId).catch(\n (err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Invalid loopback client id \"${clientId}\"`,\n )\n },\n )\n\n const metadata = await oauthClientMetadataSchema\n .parseAsync(metadataRaw)\n .catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Invalid loopback client metadata for \"${clientId}\"`,\n )\n })\n\n return this.validateClientMetadata(clientId, metadata)\n }\n\n protected async getDiscoverableClientMetadata(\n clientId: OAuthClientIdDiscoverable,\n ): Promise<OAuthClientMetadata> {\n const metadataUrl = parseDiscoverableClientId(clientId)\n\n const metadata = await this.metadataGetter.get(metadataUrl.href)\n\n // Note: we do *not* re-validate the metadata here, as the metadata is\n // validated within the getter. This is to avoid double validation.\n //\n // return this.validateClientMetadata(metadataUrl.href, metadata)\n return metadata\n }\n\n protected async getStoredClientMetadata(\n clientId: ClientId,\n ): Promise<OAuthClientMetadata> {\n if (this.store) {\n const metadata = await this.store.findClient(clientId)\n return this.validateClientMetadata(clientId, metadata)\n }\n\n throw new InvalidClientMetadataError(`Invalid client ID \"${clientId}\"`)\n }\n\n /**\n * This method will ensure that the client metadata is valid w.r.t. the OAuth\n * and OIDC specifications. It will also ensure that the metadata is\n * compatible with the implementation of this library, and ATPROTO's\n * requirements.\n */\n protected validateClientMetadata(\n clientId: ClientId,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n if (metadata.jwks && metadata.jwks_uri) {\n throw new InvalidClientMetadataError(\n 'jwks_uri and jwks are mutually exclusive',\n )\n }\n\n // Known OIDC specific parameters\n for (const k of [\n 'default_max_age',\n 'userinfo_signed_response_alg',\n 'id_token_signed_response_alg',\n 'userinfo_encrypted_response_alg',\n ] as const) {\n if (metadata[k] != null) {\n throw new InvalidClientMetadataError(`Unsupported \"${k}\" parameter`)\n }\n }\n\n const clientUriUrl = metadata.client_uri\n ? new URL(metadata.client_uri)\n : null\n\n if (clientUriUrl && isLocalHostname(clientUriUrl.hostname)) {\n throw new InvalidClientMetadataError('client_uri hostname is invalid')\n }\n\n const scopes = metadata.scope?.split(' ')\n\n if (!scopes) {\n throw new InvalidClientMetadataError('Missing scope property')\n }\n\n if (!scopes.includes('atproto')) {\n throw new InvalidClientMetadataError('Missing \"atproto\" scope')\n }\n\n const dupScope = scopes?.find(isDuplicate)\n if (dupScope) {\n throw new InvalidClientMetadataError(`Duplicate scope \"${dupScope}\"`)\n }\n\n const dupGrantType = metadata.grant_types.find(isDuplicate)\n if (dupGrantType) {\n throw new InvalidClientMetadataError(\n `Duplicate grant type \"${dupGrantType}\"`,\n )\n }\n\n for (const grantType of metadata.grant_types) {\n switch (grantType) {\n case 'implicit':\n // Never allowed (unsafe)\n throw new InvalidClientMetadataError(\n `Grant type \"${grantType}\" is not allowed`,\n )\n\n // @TODO Add support (e.g. for first party client)\n // case 'client_credentials':\n // case 'password':\n case 'authorization_code':\n case 'refresh_token':\n if (!this.serverMetadata.grant_types_supported?.includes(grantType)) {\n throw new InvalidClientMetadataError(\n `Unsupported grant type \"${grantType}\"`,\n )\n }\n break\n\n default:\n throw new InvalidClientMetadataError(\n `Grant type \"${grantType}\" is not supported`,\n )\n }\n }\n\n if (metadata.client_id && metadata.client_id !== clientId) {\n throw new InvalidClientMetadataError('client_id does not match')\n }\n\n if (metadata.subject_type && metadata.subject_type !== 'public') {\n throw new InvalidClientMetadataError(\n 'Only \"public\" subject_type is supported',\n )\n }\n\n switch (metadata.token_endpoint_auth_method) {\n case 'none':\n if (metadata.token_endpoint_auth_signing_alg) {\n throw new InvalidClientMetadataError(\n `token_endpoint_auth_method \"none\" must not have token_endpoint_auth_signing_alg`,\n )\n }\n break\n\n case 'private_key_jwt':\n if (!metadata.jwks && !metadata.jwks_uri) {\n throw new InvalidClientMetadataError(\n `private_key_jwt auth method requires jwks or jwks_uri`,\n )\n }\n if (metadata.jwks?.keys.length === 0) {\n throw new InvalidClientMetadataError(\n `private_key_jwt auth method requires at least one key in jwks`,\n )\n }\n if (!metadata.token_endpoint_auth_signing_alg) {\n throw new InvalidClientMetadataError(\n `Missing token_endpoint_auth_signing_alg client metadata`,\n )\n }\n break\n\n default:\n throw new InvalidClientMetadataError(\n `Unsupported client authentication method \"${metadata.token_endpoint_auth_method}\". Make sure \"token_endpoint_auth_method\" is set to one of: \"${Client.AUTH_METHODS_SUPPORTED.join('\", \"')}\"`,\n )\n }\n\n if (metadata.authorization_encrypted_response_enc) {\n throw new InvalidClientMetadataError(\n 'Encrypted authorization response is not supported',\n )\n }\n\n if (metadata.tls_client_certificate_bound_access_tokens) {\n throw new InvalidClientMetadataError(\n 'Mutual-TLS bound access tokens are not supported',\n )\n }\n\n if (\n metadata.authorization_encrypted_response_enc &&\n !metadata.authorization_encrypted_response_alg\n ) {\n throw new InvalidClientMetadataError(\n 'authorization_encrypted_response_enc requires authorization_encrypted_response_alg',\n )\n }\n\n // ATPROTO spec requires the use of DPoP (OAuth spec defaults to false)\n if (metadata.dpop_bound_access_tokens !== true) {\n throw new InvalidClientMetadataError(\n '\"dpop_bound_access_tokens\" must be true',\n )\n }\n\n // ATPROTO spec requires the use of PKCE, does not support OIDC\n if (!metadata.response_types.includes('code')) {\n throw new InvalidClientMetadataError('response_types must include \"code\"')\n } else if (!metadata.grant_types.includes('authorization_code')) {\n // Consistency check\n throw new InvalidClientMetadataError(\n `The \"code\" response type requires that \"grant_types\" contains \"authorization_code\"`,\n )\n }\n\n if (metadata.authorization_details_types?.length) {\n const dupAuthDetailsType =\n metadata.authorization_details_types.find(isDuplicate)\n if (dupAuthDetailsType) {\n throw new InvalidClientMetadataError(\n `Duplicate authorization_details_type \"${dupAuthDetailsType}\"`,\n )\n }\n\n const authorizationDetailsTypesSupported =\n this.serverMetadata.authorization_details_types_supported\n if (!authorizationDetailsTypesSupported) {\n throw new InvalidClientMetadataError(\n 'authorization_details_types are not supported',\n )\n }\n for (const type of metadata.authorization_details_types) {\n if (!authorizationDetailsTypesSupported.includes(type)) {\n throw new InvalidClientMetadataError(\n `Unsupported authorization_details_type \"${type}\"`,\n )\n }\n }\n }\n\n if (!metadata.redirect_uris?.length) {\n // ATPROTO spec requires that at least one redirect URI is provided\n\n throw new InvalidClientMetadataError(\n 'At least one redirect_uri is required',\n )\n }\n\n if (\n metadata.application_type === 'native' &&\n metadata.token_endpoint_auth_method !== 'none'\n ) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > Except when using a mechanism like Dynamic Client Registration\n // > [RFC7591] to provision per-instance secrets, native apps are\n // > classified as public clients, as defined by Section 2.1 of OAuth 2.0\n // > [RFC6749]; they MUST be registered with the authorization server as\n // > such. Authorization servers MUST record the client type in the client\n // > registration details in order to identify and process requests\n // > accordingly.\n\n // @NOTE We may want to remove this restriction in the future, for example\n // if https://github.com/bluesky-social/proposals/tree/main/0010-client-assertion-backend\n // gets adopted\n\n throw new InvalidClientMetadataError(\n 'Native clients must authenticate using \"none\" method',\n )\n }\n\n if (\n metadata.application_type === 'web' &&\n metadata.grant_types.includes('implicit')\n ) {\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Web Clients [as defined by \"application_type\"] using the OAuth\n // > Implicit Grant Type MUST only register URLs using the https\n // > scheme as redirect_uris; they MUST NOT use localhost as the\n // > hostname.\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n if (url.protocol !== 'https:') {\n throw new InvalidRedirectUriError(\n `Web clients must use HTTPS redirect URIs`,\n )\n }\n\n if (url.hostname === 'localhost') {\n throw new InvalidRedirectUriError(\n `Web clients must not use localhost as the hostname`,\n )\n }\n }\n }\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n\n if (url.username || url.password) {\n // Is this a valid concern? Should we allow credentials in the URI?\n throw new InvalidRedirectUriError(\n `Redirect URI ${url} must not contain credentials`,\n )\n }\n\n switch (true) {\n // FIRST: Loopback redirect URI exception (only for native apps)\n\n case url.hostname === 'localhost': {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.3\n //\n // > While redirect URIs using localhost (i.e.,\n // > \"http://localhost:{port}/{path}\") function similarly to loopback IP\n // > redirects described in Section 7.3, the use of localhost is NOT\n // > RECOMMENDED. Specifying a redirect URI with the loopback IP literal\n // > rather than localhost avoids inadvertently listening on network\n // > interfaces other than the loopback interface. It is also less\n // > susceptible to client-side firewalls and misconfigured host name\n // > resolution on the user's device.\n throw new InvalidRedirectUriError(\n `Loopback redirect URI ${url} is not allowed (use explicit IPs instead)`,\n )\n }\n\n case url.hostname === '127.0.0.1':\n case url.hostname === '[::1]': {\n // Only allowed for native apps\n if (metadata.application_type !== 'native') {\n throw new InvalidRedirectUriError(\n `Loopback redirect URIs are only allowed for native apps`,\n )\n }\n\n if (url.port) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3\n //\n // > The authorization server MUST allow any port to be specified at\n // > the time of the request for loopback IP redirect URIs, to\n // > accommodate clients that obtain an available ephemeral port\n // > from the operating system at the time of the request.\n //\n // Note: although validation of the redirect_uri will ignore the\n // port we still allow it to be specified, as the spec does not\n // forbid it. If a port number is specified, ports will need to\n // match when validating authorization requests. See\n // \"compareRedirectUri()\".\n }\n\n if (url.protocol !== 'http:') {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3\n //\n // > Loopback redirect URIs use the \"http\" scheme and are constructed\n // > with the loopback IP literal and whatever port the client is\n // > listening on. That is, \"http://127.0.0.1:{port}/{path}\" for IPv4,\n // > and \"http://[::1]:{port}/{path}\" for IPv6.\n throw new InvalidRedirectUriError(\n `Loopback redirect URI ${url} must use HTTP`,\n )\n }\n\n break\n }\n\n // SECOND: Protocol-based URI Redirection\n\n case url.protocol === 'http:': {\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > request_uri [...] URLs MUST use the https scheme unless the\n // > target Request Object is signed in a way that is verifiable by\n // > the OP.\n //\n // OIDC/Request Object are not supported. ATproto spec should not\n // allow HTTP redirect URIs either.\n\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Authorization Servers MAY reject Redirection URI values using\n // > the http scheme, other than the loopback case for Native\n // > Clients.\n throw new InvalidRedirectUriError(\n 'Only loopback redirect URIs are allowed to use the \"http\" scheme',\n )\n }\n\n case url.protocol === 'https:': {\n if (isLocalHostname(url.hostname)) {\n throw new InvalidRedirectUriError(\n `Redirect URI \"${url}\"'s domain name must not be a local hostname`,\n )\n }\n\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > In addition to the collision-resistant properties, requiring a\n // > URI scheme based on a domain name that is under the control of\n // > the app can help to prove ownership in the event of a dispute\n // > where two apps claim the same private-use URI scheme (where one\n // > app is acting maliciously).\n //\n // We can't enforce this here (in generic client validation) because\n // we don't have a concept of generic proven ownership.\n //\n // Discoverable clients, however, will have this check covered in the\n // `validateDiscoverableClientMetadata`, by using the client_id's\n // domain as \"proven ownership\".\n\n // The following restriction from OIDC is *not* enforced for clients\n // as it prevents \"App Links\" / \"Apple Universal Links\" from being\n // used as redirect URIs.\n //\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Native Clients [as defined by \"application_type\"] MUST only\n // > register redirect_uris using custom URI schemes or loopback URLs\n // > using the http scheme; loopback URLs use localhost or the IP\n // > loopback literals 127.0.0.1 or [::1] as the hostname.\n //\n // if (metadata.application_type === 'native') {\n // throw new InvalidRedirectUriError(\n // `Native clients must use custom URI schemes or loopback URLs`,\n // )\n // }\n\n break\n }\n\n case isPrivateUseUriScheme(url): {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.1\n //\n // > When choosing a URI scheme to associate with the app, apps MUST\n // > use a URI scheme based on a domain name under their control,\n // > expressed in reverse order, as recommended by Section 3.8 of\n // > [RFC7595] for private-use URI schemes.\n\n if (metadata.application_type !== 'native') {\n throw new InvalidRedirectUriError(\n `Private-Use URI Scheme redirect URI are only allowed for native apps`,\n )\n }\n\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > In addition to the collision-resistant properties, requiring a\n // > URI scheme based on a domain name that is under the control of\n // > the app can help to prove ownership in the event of a dispute\n // > where two apps claim the same private-use URI scheme (where one\n // > app is acting maliciously).\n //\n // We can't check for ownership here (as there is no concept of\n // proven ownership in the generic client validation), but we can\n // check that the domain is a valid domain name.\n\n const urlDomain = reverseDomain(url.protocol.slice(0, -1))\n\n if (isLocalHostname(urlDomain)) {\n throw new InvalidRedirectUriError(\n `Private-use URI Scheme redirect URI must not be a local hostname`,\n )\n }\n\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.1\n //\n // > Following the requirements of Section 3.2 of [RFC3986], as there\n // > is no naming authority for private-use URI scheme redirects, only\n // > a single slash (\"/\") appears after the scheme component.\n if (\n url.href.startsWith(`${url.protocol}//`) ||\n url.username ||\n url.password ||\n url.hostname ||\n url.port\n ) {\n throw new InvalidRedirectUriError(\n `Private-Use URI Scheme must be in the form ${url.protocol}/<path>`,\n )\n }\n\n break\n }\n\n default:\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > At a minimum, any private-use URI scheme that doesn't contain a\n // > period character (\".\") SHOULD be rejected.\n throw new InvalidRedirectUriError(\n `Invalid redirect URI scheme \"${url.protocol}\"`,\n )\n }\n }\n\n if (isOAuthClientIdLoopback(clientId)) {\n return this.validateLoopbackClientMetadata(clientId, metadata)\n } else if (isOAuthClientIdDiscoverable(clientId)) {\n return this.validateDiscoverableClientMetadata(clientId, metadata)\n } else {\n return metadata\n }\n }\n\n validateLoopbackClientMetadata(\n clientId: OAuthClientIdLoopback,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n if (metadata.client_uri) {\n throw new InvalidClientMetadataError(\n 'client_uri is not allowed for loopback clients',\n )\n }\n\n if (metadata.application_type !== 'native') {\n throw new InvalidClientMetadataError(\n 'Loopback clients must have application_type \"native\"',\n )\n }\n\n const method = metadata.token_endpoint_auth_method\n if (method !== 'none') {\n throw new InvalidClientMetadataError(\n `Loopback clients are not allowed to use \"token_endpoint_auth_method\" ${method}`,\n )\n }\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n\n if (url.protocol !== 'http:') {\n throw new InvalidRedirectUriError(\n `Loopback clients must use HTTP redirect URIs`,\n )\n }\n\n if (!isLoopbackHost(url.hostname)) {\n throw new InvalidRedirectUriError(\n `Loopback clients must use loopback redirect URIs`,\n )\n }\n }\n\n return metadata\n }\n\n validateDiscoverableClientMetadata(\n clientId: OAuthClientIdDiscoverable,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n if (!metadata.client_id) {\n // https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html\n throw new InvalidClientMetadataError(\n `client_id is required for discoverable clients`,\n )\n }\n\n const clientIdUrl = parseDiscoverableClientId(clientId)\n\n if (metadata.client_uri) {\n // https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html\n //\n // The client_uri must be a parent of the client_id URL. This might be\n // relaxed in the future.\n\n const clientUriUrl = new URL(metadata.client_uri)\n\n if (clientUriUrl.origin !== clientIdUrl.origin) {\n throw new InvalidClientMetadataError(\n `client_uri must have the same origin as the client_id`,\n )\n }\n\n if (clientIdUrl.pathname !== clientUriUrl.pathname) {\n if (\n !clientIdUrl.pathname.startsWith(\n clientUriUrl.pathname.endsWith('/')\n ? clientUriUrl.pathname\n : `${clientUriUrl.pathname}/`,\n )\n ) {\n throw new InvalidClientMetadataError(\n `client_uri must be a parent URL of the client_id`,\n )\n }\n }\n }\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n\n if (isPrivateUseUriScheme(url)) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > In addition to the collision-resistant properties, requiring a\n // > URI scheme based on a domain name that is under the control of\n // > the app can help to prove ownership in the event of a dispute\n // > where two apps claim the same private-use URI scheme (where one\n // > app is acting maliciously).\n\n // https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html\n //\n // Fully qualified domain name (FQDN) of the client_id, in reverse\n // order. This could be relaxed to allow same apex domain names, or\n // parent domains, but for now we require an exact match.\n const protocol = `${reverseDomain(clientIdUrl.hostname)}:`\n if (url.protocol !== protocol) {\n throw new InvalidRedirectUriError(\n `Private-Use URI Scheme redirect URI, for discoverable client metadata, must be the fully qualified domain name (FQDN) of the client_id, in reverse order (${protocol})`,\n )\n }\n }\n }\n\n return metadata\n }\n}\n\nfunction isDuplicate<\n T extends string | number | boolean | null | undefined | symbol,\n>(value: T, index: number, array: T[]) {\n return array.includes(value, index + 1)\n}\n\nfunction reverseDomain(domain: string) {\n return domain.split('.').reverse().join('.')\n}\n\nfunction isPrivateUseUriScheme(uri: URL) {\n return uri.protocol.includes('.')\n}\n\nfunction buildJsonGetRequest(uri: string, options?: GetCachedOptions) {\n return new Request(uri, {\n headers: { accept: 'application/json' },\n // @ts-expect-error invalid types in \"undici-types\"\n cache: options?.noCache ? 'no-cache' : undefined,\n signal: options?.signal,\n redirect: 'error',\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/client/client-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { Jwks, Keyset, jwksPubSchema } from '@atproto/jwk'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthClientIdDiscoverable,\n OAuthClientIdLoopback,\n OAuthClientMetadata,\n OAuthClientMetadataInput,\n isLocalHostname,\n isOAuthClientIdDiscoverable,\n isOAuthClientIdLoopback,\n oauthClientMetadataSchema,\n} from '@atproto/oauth-types'\nimport {\n Fetch,\n bindFetch,\n fetchJsonProcessor,\n fetchJsonZodProcessor,\n fetchOkProcessor,\n} from '@atproto-labs/fetch'\nimport { pipe } from '@atproto-labs/pipe'\nimport {\n CachedGetter,\n GetCachedOptions,\n SimpleStore,\n} from '@atproto-labs/simple-store'\nimport { InvalidClientMetadataError } from '../errors/invalid-client-metadata-error.js'\nimport { InvalidRedirectUriError } from '../errors/invalid-redirect-uri-error.js'\nimport { callAsync } from '../lib/util/function.js'\nimport { Awaitable } from '../lib/util/type.js'\nimport { OAuthHooks } from '../oauth-hooks.js'\nimport { ClientId } from './client-id.js'\nimport { ClientStore } from './client-store.js'\nimport { parseDiscoverableClientId, parseRedirectUri } from './client-utils.js'\nimport { Client } from './client.js'\n\nconst fetchMetadataHandler = pipe(\n fetchOkProcessor(),\n // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-4.1\n fetchJsonProcessor('application/json', true),\n fetchJsonZodProcessor(oauthClientMetadataSchema),\n)\n\nconst fetchJwksHandler = pipe(\n fetchOkProcessor(),\n fetchJsonProcessor('application/json', false),\n fetchJsonZodProcessor(jwksPubSchema),\n)\n\nexport type LoopbackMetadataGetter = (\n url: string,\n) => Awaitable<OAuthClientMetadataInput>\n\nexport class ClientManager {\n protected readonly jwks: CachedGetter<string, Jwks>\n protected readonly metadataGetter: CachedGetter<string, OAuthClientMetadata>\n\n constructor(\n protected readonly serverMetadata: OAuthAuthorizationServerMetadata,\n protected readonly keyset: Keyset,\n protected readonly hooks: OAuthHooks,\n protected readonly store: ClientStore | null,\n protected readonly loopbackMetadata: LoopbackMetadataGetter | null = null,\n safeFetch: Fetch,\n clientJwksCache: SimpleStore<string, Jwks>,\n clientMetadataCache: SimpleStore<string, OAuthClientMetadata>,\n ) {\n const fetch = bindFetch(safeFetch)\n\n this.jwks = new CachedGetter(async (uri, options) => {\n const jwks = await fetch(buildJsonGetRequest(uri, options)).then(\n fetchJwksHandler,\n )\n\n return jwks\n }, clientJwksCache)\n\n this.metadataGetter = new CachedGetter(async (uri, options) => {\n const metadata = await fetch(buildJsonGetRequest(uri, options)).then(\n fetchMetadataHandler,\n )\n\n // Validate within the getter to avoid caching invalid metadata\n return this.validateClientMetadata(uri, metadata)\n }, clientMetadataCache)\n }\n\n /**\n *\n * @see {@link https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2 OIDC Client Registration}\n */\n public async getClient(clientId: ClientId) {\n const metadata = await this.getClientMetadata(clientId).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Unable to obtain client metadata for \"${clientId}\"`,\n )\n })\n\n const jwks = metadata.jwks_uri\n ? await this.jwks.get(metadata.jwks_uri).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Unable to obtain jwks from \"${metadata.jwks_uri}\" for \"${clientId}\"`,\n )\n })\n : undefined\n\n const partialInfo = await callAsync(this.hooks.getClientInfo, clientId, {\n metadata,\n jwks,\n }).catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Rejected client information for \"${clientId}\"`,\n )\n })\n\n const isFirstParty = partialInfo?.isFirstParty ?? false\n const isTrusted = partialInfo?.isTrusted ?? isFirstParty\n\n return new Client(clientId, metadata, jwks, { isFirstParty, isTrusted })\n }\n\n public async loadClients(\n clientIds: Iterable<ClientId>,\n {\n onError = (err) => {\n throw err\n },\n }: {\n onError?: (\n err: unknown,\n clientId: ClientId,\n ) => Awaitable<Client | null | undefined>\n } = {},\n ): Promise<Map<ClientId, Client>> {\n // Make sure we don't load the same client multiple times\n const uniqueClientIds =\n clientIds instanceof Set ? clientIds : new Set(clientIds)\n\n // Load all (unique) clients in parallel\n const clients = await Promise.all(\n Array.from(uniqueClientIds, async (clientId) =>\n this.getClient(clientId).catch((err) => onError(err, clientId)),\n ),\n )\n\n // Return a map for easy lookups\n return new Map(\n clients\n .filter((c) => c != null && c instanceof Client)\n .map((c) => [c.id, c]),\n )\n }\n\n protected async getClientMetadata(\n clientId: ClientId,\n ): Promise<OAuthClientMetadata> {\n if (isOAuthClientIdLoopback(clientId)) {\n return this.getLoopbackClientMetadata(clientId)\n } else if (isOAuthClientIdDiscoverable(clientId)) {\n return this.getDiscoverableClientMetadata(clientId)\n } else if (this.store) {\n return this.getStoredClientMetadata(clientId)\n }\n\n throw new InvalidClientMetadataError(`Invalid client ID \"${clientId}\"`)\n }\n\n protected async getLoopbackClientMetadata(\n clientId: OAuthClientIdLoopback,\n ): Promise<OAuthClientMetadata> {\n const { loopbackMetadata } = this\n if (!loopbackMetadata) {\n throw new InvalidClientMetadataError('Loopback clients are not allowed')\n }\n\n const metadataRaw = await callAsync(loopbackMetadata, clientId).catch(\n (err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Invalid loopback client id \"${clientId}\"`,\n )\n },\n )\n\n const metadata = await oauthClientMetadataSchema\n .parseAsync(metadataRaw)\n .catch((err) => {\n throw InvalidClientMetadataError.from(\n err,\n `Invalid loopback client metadata for \"${clientId}\"`,\n )\n })\n\n return this.validateClientMetadata(clientId, metadata)\n }\n\n protected async getDiscoverableClientMetadata(\n clientId: OAuthClientIdDiscoverable,\n ): Promise<OAuthClientMetadata> {\n const metadataUrl = parseDiscoverableClientId(clientId)\n\n const metadata = await this.metadataGetter.get(metadataUrl.href)\n\n // Note: we do *not* re-validate the metadata here, as the metadata is\n // validated within the getter. This is to avoid double validation.\n //\n // return this.validateClientMetadata(metadataUrl.href, metadata)\n return metadata\n }\n\n protected async getStoredClientMetadata(\n clientId: ClientId,\n ): Promise<OAuthClientMetadata> {\n if (this.store) {\n const metadata = await this.store.findClient(clientId)\n return this.validateClientMetadata(clientId, metadata)\n }\n\n throw new InvalidClientMetadataError(`Invalid client ID \"${clientId}\"`)\n }\n\n /**\n * This method will ensure that the client metadata is valid w.r.t. the OAuth\n * and OIDC specifications. It will also ensure that the metadata is\n * compatible with the implementation of this library, and ATPROTO's\n * requirements.\n */\n protected validateClientMetadata(\n clientId: ClientId,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n // @TODO This method should only check for rules that are specific to this\n // implementation or the ATPROTO specification. All generic validation rules\n // should be moved to the @atproto/oauth-types package.\n\n if (metadata.jwks && metadata.jwks_uri) {\n throw new InvalidClientMetadataError(\n 'jwks_uri and jwks are mutually exclusive',\n )\n }\n\n // Known OIDC specific parameters\n for (const k of [\n 'default_max_age',\n 'userinfo_signed_response_alg',\n 'id_token_signed_response_alg',\n 'userinfo_encrypted_response_alg',\n ] as const) {\n if (metadata[k] != null) {\n throw new InvalidClientMetadataError(`Unsupported \"${k}\" parameter`)\n }\n }\n\n const clientUriUrl = metadata.client_uri\n ? new URL(metadata.client_uri)\n : null\n\n if (clientUriUrl && isLocalHostname(clientUriUrl.hostname)) {\n throw new InvalidClientMetadataError('client_uri hostname is invalid')\n }\n\n const scopes = metadata.scope?.split(' ')\n\n if (!scopes) {\n throw new InvalidClientMetadataError('Missing scope property')\n }\n\n if (!scopes.includes('atproto')) {\n throw new InvalidClientMetadataError('Missing \"atproto\" scope')\n }\n\n const dupScope = scopes?.find(isDuplicate)\n if (dupScope) {\n throw new InvalidClientMetadataError(`Duplicate scope \"${dupScope}\"`)\n }\n\n const dupGrantType = metadata.grant_types.find(isDuplicate)\n if (dupGrantType) {\n throw new InvalidClientMetadataError(\n `Duplicate grant type \"${dupGrantType}\"`,\n )\n }\n\n for (const grantType of metadata.grant_types) {\n switch (grantType) {\n case 'implicit':\n // Never allowed (unsafe)\n throw new InvalidClientMetadataError(\n `Grant type \"${grantType}\" is not allowed`,\n )\n\n // @TODO Add support (e.g. for first party client)\n // case 'client_credentials':\n // case 'password':\n case 'authorization_code':\n case 'refresh_token':\n if (!this.serverMetadata.grant_types_supported?.includes(grantType)) {\n throw new InvalidClientMetadataError(\n `Unsupported grant type \"${grantType}\"`,\n )\n }\n break\n\n default:\n throw new InvalidClientMetadataError(\n `Grant type \"${grantType}\" is not supported`,\n )\n }\n }\n\n if (metadata.client_id && metadata.client_id !== clientId) {\n throw new InvalidClientMetadataError('client_id does not match')\n }\n\n if (metadata.subject_type && metadata.subject_type !== 'public') {\n throw new InvalidClientMetadataError(\n 'Only \"public\" subject_type is supported',\n )\n }\n\n switch (metadata.token_endpoint_auth_method) {\n case 'none':\n if (metadata.token_endpoint_auth_signing_alg) {\n throw new InvalidClientMetadataError(\n `token_endpoint_auth_method \"none\" must not have token_endpoint_auth_signing_alg`,\n )\n }\n break\n\n case 'private_key_jwt':\n if (!metadata.jwks && !metadata.jwks_uri) {\n throw new InvalidClientMetadataError(\n `private_key_jwt auth method requires jwks or jwks_uri`,\n )\n }\n if (metadata.jwks?.keys.length === 0) {\n throw new InvalidClientMetadataError(\n `private_key_jwt auth method requires at least one key in jwks`,\n )\n }\n if (!metadata.token_endpoint_auth_signing_alg) {\n throw new InvalidClientMetadataError(\n `Missing token_endpoint_auth_signing_alg client metadata`,\n )\n }\n break\n\n default:\n throw new InvalidClientMetadataError(\n `Unsupported client authentication method \"${metadata.token_endpoint_auth_method}\". Make sure \"token_endpoint_auth_method\" is set to one of: \"${Client.AUTH_METHODS_SUPPORTED.join('\", \"')}\"`,\n )\n }\n\n if (metadata.authorization_encrypted_response_enc) {\n throw new InvalidClientMetadataError(\n 'Encrypted authorization response is not supported',\n )\n }\n\n if (metadata.tls_client_certificate_bound_access_tokens) {\n throw new InvalidClientMetadataError(\n 'Mutual-TLS bound access tokens are not supported',\n )\n }\n\n if (\n metadata.authorization_encrypted_response_enc &&\n !metadata.authorization_encrypted_response_alg\n ) {\n throw new InvalidClientMetadataError(\n 'authorization_encrypted_response_enc requires authorization_encrypted_response_alg',\n )\n }\n\n // ATPROTO spec requires the use of DPoP (OAuth spec defaults to false)\n if (metadata.dpop_bound_access_tokens !== true) {\n throw new InvalidClientMetadataError(\n '\"dpop_bound_access_tokens\" must be true',\n )\n }\n\n // ATPROTO spec requires the use of PKCE, does not support OIDC\n if (!metadata.response_types.includes('code')) {\n throw new InvalidClientMetadataError('response_types must include \"code\"')\n } else if (!metadata.grant_types.includes('authorization_code')) {\n // Consistency check\n throw new InvalidClientMetadataError(\n `The \"code\" response type requires that \"grant_types\" contains \"authorization_code\"`,\n )\n }\n\n if (metadata.authorization_details_types?.length) {\n const dupAuthDetailsType =\n metadata.authorization_details_types.find(isDuplicate)\n if (dupAuthDetailsType) {\n throw new InvalidClientMetadataError(\n `Duplicate authorization_details_type \"${dupAuthDetailsType}\"`,\n )\n }\n\n const authorizationDetailsTypesSupported =\n this.serverMetadata.authorization_details_types_supported\n if (!authorizationDetailsTypesSupported) {\n throw new InvalidClientMetadataError(\n 'authorization_details_types are not supported',\n )\n }\n for (const type of metadata.authorization_details_types) {\n if (!authorizationDetailsTypesSupported.includes(type)) {\n throw new InvalidClientMetadataError(\n `Unsupported authorization_details_type \"${type}\"`,\n )\n }\n }\n }\n\n if (!metadata.redirect_uris?.length) {\n // ATPROTO spec requires that at least one redirect URI is provided\n\n throw new InvalidClientMetadataError(\n 'At least one redirect_uri is required',\n )\n }\n\n if (\n metadata.application_type === 'native' &&\n metadata.token_endpoint_auth_method !== 'none'\n ) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > Except when using a mechanism like Dynamic Client Registration\n // > [RFC7591] to provision per-instance secrets, native apps are\n // > classified as public clients, as defined by Section 2.1 of OAuth 2.0\n // > [RFC6749]; they MUST be registered with the authorization server as\n // > such. Authorization servers MUST record the client type in the client\n // > registration details in order to identify and process requests\n // > accordingly.\n\n // @NOTE We may want to remove this restriction in the future, for example\n // if https://github.com/bluesky-social/proposals/tree/main/0010-client-assertion-backend\n // gets adopted\n\n throw new InvalidClientMetadataError(\n 'Native clients must authenticate using \"none\" method',\n )\n }\n\n if (\n metadata.application_type === 'web' &&\n metadata.grant_types.includes('implicit')\n ) {\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Web Clients [as defined by \"application_type\"] using the OAuth\n // > Implicit Grant Type MUST only register URLs using the https\n // > scheme as redirect_uris; they MUST NOT use localhost as the\n // > hostname.\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n if (url.protocol !== 'https:') {\n throw new InvalidRedirectUriError(\n `Web clients must use HTTPS redirect URIs`,\n )\n }\n\n if (url.hostname === 'localhost') {\n throw new InvalidRedirectUriError(\n `Web clients must not use localhost as the hostname`,\n )\n }\n }\n }\n\n for (const redirectUri of metadata.redirect_uris) {\n const url = parseRedirectUri(redirectUri)\n\n if (url.username || url.password) {\n // Is this a valid concern? Should we allow credentials in the URI?\n throw new InvalidRedirectUriError(\n `Redirect URI ${url} must not contain credentials`,\n )\n }\n\n switch (true) {\n // FIRST: Loopback redirect URI exception (only for native apps)\n\n case url.hostname === 'localhost': {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.3\n //\n // > While redirect URIs using localhost (i.e.,\n // > \"http://localhost:{port}/{path}\") function similarly to loopback IP\n // > redirects described in Section 7.3, the use of localhost is NOT\n // > RECOMMENDED. Specifying a redirect URI with the loopback IP literal\n // > rather than localhost avoids inadvertently listening on network\n // > interfaces other than the loopback interface. It is also less\n // > susceptible to client-side firewalls and misconfigured host name\n // > resolution on the user's device.\n throw new InvalidRedirectUriError(\n `Loopback redirect URI ${url} is not allowed (use explicit IPs instead)`,\n )\n }\n\n case url.hostname === '127.0.0.1':\n case url.hostname === '[::1]': {\n // Only allowed for native apps\n if (metadata.application_type !== 'native') {\n throw new InvalidRedirectUriError(\n `Loopback redirect URIs are only allowed for native apps`,\n )\n }\n\n if (url.port) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3\n //\n // > The authorization server MUST allow any port to be specified at\n // > the time of the request for loopback IP redirect URIs, to\n // > accommodate clients that obtain an available ephemeral port\n // > from the operating system at the time of the request.\n //\n // Note: although validation of the redirect_uri will ignore the\n // port we still allow it to be specified, as the spec does not\n // forbid it. If a port number is specified, ports will need to\n // match when validating authorization requests. See\n // \"compareRedirectUri()\".\n }\n\n if (url.protocol !== 'http:') {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3\n //\n // > Loopback redirect URIs use the \"http\" scheme and are constructed\n // > with the loopback IP literal and whatever port the client is\n // > listening on. That is, \"http://127.0.0.1:{port}/{path}\" for IPv4,\n // > and \"http://[::1]:{port}/{path}\" for IPv6.\n throw new InvalidRedirectUriError(\n `Loopback redirect URI ${url} must use HTTP`,\n )\n }\n\n break\n }\n\n // SECOND: Protocol-based URI Redirection\n\n case url.protocol === 'http:': {\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > request_uri [...] URLs MUST use the https scheme unless the\n // > target Request Object is signed in a way that is verifiable by\n // > the OP.\n //\n // OIDC/Request Object are not supported. ATproto spec should not\n // allow HTTP redirect URIs either.\n\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Authorization Servers MAY reject Redirection URI values using\n // > the http scheme, other than the loopback case for Native\n // > Clients.\n throw new InvalidRedirectUriError(\n 'Only loopback redirect URIs are allowed to use the \"http\" scheme',\n )\n }\n\n case url.protocol === 'https:': {\n if (isLocalHostname(url.hostname)) {\n throw new InvalidRedirectUriError(\n `Redirect URI \"${url}\"'s domain name must not be a local hostname`,\n )\n }\n\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > In addition to the collision-resistant properties, requiring a\n // > URI scheme based on a domain name that is under the control of\n // > the app can help to prove ownership in the event of a dispute\n // > where two apps claim the same private-use URI scheme (where one\n // > app is acting maliciously).\n //\n // We can't enforce this here (in generic client validation) because\n // we don't have a concept of generic proven ownership.\n //\n // Discoverable clients, however, will have this check covered in the\n // `validateDiscoverableClientMetadata`, by using the client_id's\n // domain as \"proven ownership\".\n\n // The following restriction from OIDC is *not* enforced for clients\n // as it prevents \"App Links\" / \"Apple Universal Links\" from being\n // used as redirect URIs.\n //\n // https://openid.net/specs/openid-connect-registration-1_0.html#rfc.section.2\n //\n // > Native Clients [as defined by \"application_type\"] MUST only\n // > register redirect_uris using custom URI schemes or loopback URLs\n // > using the http scheme; loopback URLs use localhost or the IP\n // > loopback literals 127.0.0.1 or [::1] as the hostname.\n //\n // if (metadata.application_type === 'native') {\n // throw new InvalidRedirectUriError(\n // `Native clients must use custom URI schemes or loopback URLs`,\n // )\n // }\n\n break\n }\n\n case isPrivateUseUriScheme(url): {\n if (metadata.application_type !== 'native') {\n throw new InvalidRedirectUriError(\n `Private-Use URI Scheme redirect URI are only allowed for native apps`,\n )\n }\n\n break\n }\n\n default:\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > At a minimum, any private-use URI scheme that doesn't contain a\n // > period character (\".\") SHOULD be rejected.\n throw new InvalidRedirectUriError(\n `Invalid redirect URI scheme \"${url.protocol}\"`,\n )\n }\n }\n\n if (isOAuthClientIdLoopback(clientId)) {\n return this.validateLoopbackClientMetadata(clientId, metadata)\n } else if (isOAuthClientIdDiscoverable(clientId)) {\n return this.validateDiscoverableClientMetadata(clientId, metadata)\n } else {\n return metadata\n }\n }\n\n validateLoopbackClientMetadata(\n clientId: OAuthClientIdLoopback,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n if (metadata.client_uri) {\n throw new InvalidClientMetadataError(\n 'client_uri is not allowed for loopback clients',\n )\n }\n\n if (metadata.application_type !== 'native') {\n throw new InvalidClientMetadataError(\n 'Loopback clients must have application_type \"native\"',\n )\n }\n\n const method = metadata.token_endpoint_auth_method\n if (method !== 'none') {\n throw new InvalidClientMetadataError(\n `Loopback clients are not allowed to use \"token_endpoint_auth_method\" ${method}`,\n )\n }\n\n return metadata\n }\n\n validateDiscoverableClientMetadata(\n clientId: OAuthClientIdDiscoverable,\n metadata: OAuthClientMetadata,\n ): OAuthClientMetadata {\n if (!metadata.client_id) {\n // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html\n throw new InvalidClientMetadataError(\n `client_id is required for discoverable clients`,\n )\n }\n\n const clientIdUrl = parseDiscoverableClientId(clientId)\n\n if (metadata.client_uri) {\n // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html\n //\n // The client_uri must be a parent of the client_id URL. This might be\n // relaxed in the future.\n\n const clientUriUrl = new URL(metadata.client_uri)\n\n if (clientUriUrl.origin !== clientIdUrl.origin) {\n throw new InvalidClientMetadataError(\n `client_uri must have the same origin as the client_id`,\n )\n }\n\n if (clientIdUrl.pathname !== clientUriUrl.pathname) {\n if (\n !clientIdUrl.pathname.startsWith(\n clientUriUrl.pathname.endsWith('/')\n ? clientUriUrl.pathname\n : `${clientUriUrl.pathname}/`,\n )\n ) {\n throw new InvalidClientMetadataError(\n `client_uri must be a parent URL of the client_id`,\n )\n }\n }\n }\n\n for (const redirectUri of metadata.redirect_uris) {\n // @NOTE at this point, all redirect URIs have already been validated by\n // oauthRedirectUriSchema\n\n const url = parseRedirectUri(redirectUri)\n\n if (isPrivateUseUriScheme(url)) {\n // https://datatracker.ietf.org/doc/html/rfc8252#section-7.1\n //\n // > When choosing a URI scheme to associate with the app, apps MUST use\n // > a URI scheme based on a domain name under their control, expressed\n // > in reverse order, as recommended by Section 3.8 of [RFC7595] for\n // > private-use URI schemes.\n\n // https://datatracker.ietf.org/doc/html/rfc8252#section-8.4\n //\n // > In addition to the collision-resistant properties, requiring a\n // > URI scheme based on a domain name that is under the control of\n // > the app can help to prove ownership in the event of a dispute\n // > where two apps claim the same private-use URI scheme (where one\n // > app is acting maliciously).\n\n // https://atproto.com/specs/oauth\n //\n // > Any custom scheme must match the client_id hostname in\n // > reverse-domain order. The URI scheme must be followed by a single\n // > colon (:) then a single forward slash (/) and then a URI path\n // > component. For example, an app with client_id\n // > https://app.example.com/client-metadata.json could have a\n // > redirect_uri of com.example.app:/callback.\n const protocol = `${reverseDomain(clientIdUrl.hostname)}:`\n if (url.protocol !== protocol) {\n throw new InvalidRedirectUriError(\n `Private-Use URI Scheme redirect URI, for discoverable client metadata, must be the fully qualified domain name (FQDN) of the client_id, in reverse order (${protocol})`,\n )\n }\n }\n }\n\n return metadata\n }\n}\n\nfunction isDuplicate<\n T extends string | number | boolean | null | undefined | symbol,\n>(value: T, index: number, array: T[]) {\n return array.includes(value, index + 1)\n}\n\nfunction reverseDomain(domain: string) {\n return domain.split('.').reverse().join('.')\n}\n\nfunction isPrivateUseUriScheme(uri: URL) {\n return uri.protocol.includes('.')\n}\n\nfunction buildJsonGetRequest(uri: string, options?: GetCachedOptions) {\n return new Request(uri, {\n headers: { accept: 'application/json' },\n // @ts-expect-error invalid types in \"undici-types\"\n cache: options?.noCache ? 'no-cache' : undefined,\n signal: options?.signal,\n redirect: 'error',\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-utils.d.ts","sourceRoot":"","sources":["../../src/client/client-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,
|
|
1
|
+
{"version":3,"file":"client-utils.d.ts","sourceRoot":"","sources":["../../src/client/client-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAG1B,MAAM,sBAAsB,CAAA;AAI7B,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAMzD;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,yBAAyB,GAClC,GAAG,CAkBL"}
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseRedirectUri = parseRedirectUri;
|
|
4
4
|
exports.parseDiscoverableClientId = parseDiscoverableClientId;
|
|
5
5
|
const oauth_types_1 = require("@atproto/oauth-types");
|
|
6
|
-
const fetch_node_1 = require("@atproto-labs/fetch-node");
|
|
7
6
|
const invalid_client_id_error_js_1 = require("../errors/invalid-client-id-error.js");
|
|
8
7
|
const invalid_redirect_uri_error_js_1 = require("../errors/invalid-redirect-uri-error.js");
|
|
9
8
|
function parseRedirectUri(redirectUri) {
|
|
@@ -18,7 +17,7 @@ function parseDiscoverableClientId(clientId) {
|
|
|
18
17
|
try {
|
|
19
18
|
const url = (0, oauth_types_1.parseOAuthDiscoverableClientId)(clientId);
|
|
20
19
|
// Extra validation, prevent usage of invalid internet domain names.
|
|
21
|
-
if ((0,
|
|
20
|
+
if ((0, oauth_types_1.isLocalHostname)(url.hostname)) {
|
|
22
21
|
throw new invalid_client_id_error_js_1.InvalidClientIdError("The client_id's TLD must not be a local hostname");
|
|
23
22
|
}
|
|
24
23
|
return url;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-utils.js","sourceRoot":"","sources":["../../src/client/client-utils.ts"],"names":[],"mappings":";;AAQA,4CAMC;AAED,8DAoBC;AApCD,
|
|
1
|
+
{"version":3,"file":"client-utils.js","sourceRoot":"","sources":["../../src/client/client-utils.ts"],"names":[],"mappings":";;AAQA,4CAMC;AAED,8DAoBC;AApCD,sDAI6B;AAC7B,qFAA2E;AAC3E,2FAAiF;AAEjF,SAAgB,gBAAgB,CAAC,WAAmB;IAClD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,WAAW,CAAC,CAAA;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,uDAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACzC,CAAC;AACH,CAAC;AAED,SAAgB,yBAAyB,CACvC,QAAmC;IAEnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,4CAA8B,EAAC,QAAQ,CAAC,CAAA;QAEpD,oEAAoE;QACpE,IAAI,IAAA,6BAAe,EAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,iDAAoB,CAC5B,kDAAkD,CACnD,CAAA;QACH,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,iDAAoB,CAAC,IAAI,CAC7B,GAAG,EACH,wCAAwC,CACzC,CAAA;IACH,CAAC;AACH,CAAC","sourcesContent":["import {\n OAuthClientIdDiscoverable,\n isLocalHostname,\n parseOAuthDiscoverableClientId,\n} from '@atproto/oauth-types'\nimport { InvalidClientIdError } from '../errors/invalid-client-id-error.js'\nimport { InvalidRedirectUriError } from '../errors/invalid-redirect-uri-error.js'\n\nexport function parseRedirectUri(redirectUri: string): URL {\n try {\n return new URL(redirectUri)\n } catch (err) {\n throw InvalidRedirectUriError.from(err)\n }\n}\n\nexport function parseDiscoverableClientId(\n clientId: OAuthClientIdDiscoverable,\n): URL {\n try {\n const url = parseOAuthDiscoverableClientId(clientId)\n\n // Extra validation, prevent usage of invalid internet domain names.\n if (isLocalHostname(url.hostname)) {\n throw new InvalidClientIdError(\n \"The client_id's TLD must not be a local hostname\",\n )\n }\n\n return url\n } catch (err) {\n throw InvalidClientIdError.from(\n err,\n 'Invalid discoverable client identifier',\n )\n }\n}\n"]}
|
|
@@ -81,7 +81,8 @@ function buildMetadata(issuer, keyset, customMetadata) {
|
|
|
81
81
|
token_endpoint_auth_methods_supported: [...client_js_1.Client.AUTH_METHODS_SUPPORTED],
|
|
82
82
|
token_endpoint_auth_signing_alg_values_supported: [...crypto_js_1.VERIFY_ALGOS],
|
|
83
83
|
revocation_endpoint: new URL('/oauth/revoke', issuer).href,
|
|
84
|
-
|
|
84
|
+
// @TODO Should we implement these endpoints?
|
|
85
|
+
// introspection_endpoint: new URL('/oauth/introspect', issuer).href,
|
|
85
86
|
// end_session_endpoint: new URL('/oauth/logout', issuer).href,
|
|
86
87
|
// https://datatracker.ietf.org/doc/html/rfc9126#section-5
|
|
87
88
|
pushed_authorization_request_endpoint: new URL('/oauth/par', issuer).href,
|
|
@@ -90,9 +91,9 @@ function buildMetadata(issuer, keyset, customMetadata) {
|
|
|
90
91
|
dpop_signing_alg_values_supported: [...crypto_js_1.VERIFY_ALGOS],
|
|
91
92
|
// https://datatracker.ietf.org/doc/html/rfc9396#section-14.4
|
|
92
93
|
authorization_details_types_supported: customMetadata?.authorization_details_types_supported,
|
|
93
|
-
// https://
|
|
94
|
+
// https://www.rfc-editor.org/rfc/rfc9728.html#section-4
|
|
94
95
|
protected_resources: customMetadata?.protected_resources,
|
|
95
|
-
// https://
|
|
96
|
+
// https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html
|
|
96
97
|
client_id_metadata_document_supported: true,
|
|
97
98
|
});
|
|
98
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-metadata.js","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":";;AAkBA,sCAgHC;AAjID,sDAI6B;AAC7B,mDAA4C;AAC5C,qDAAoD;AAOpD;;;GAGG;AACH,SAAgB,aAAa,CAC3B,MAA6B,EAC7B,MAAc,EACd,cAA+B;IAE/B,OAAO,uDAAyC,CAAC,KAAK,CAAC;QACrD,MAAM;QAEN,gBAAgB,EAAE;YAChB,SAAS;YAET,yEAAyE;YACzE,kCAAkC;YAClC,kBAAkB;YAClB,oBAAoB;YACpB,sBAAsB;YAEtB,gEAAgE;SACjE;QACD,uBAAuB,EAAE;YACvB,EAAE;YACF,QAAQ,EAAE,6CAA6C;YACvD,+DAA+D;SAChE;QACD,wBAAwB,EAAE;YACxB,QAAQ;YACR,MAAM;YACN,WAAW;YAEX,SAAS;YACT,UAAU;YACV,yBAAyB;YACzB,mBAAmB;YACnB,gBAAgB;YAChB,oBAAoB;YACpB,cAAc;SACf;QACD,wBAAwB,EAAE;YACxB,mFAAmF;YACnF,OAAO;YACP,UAAU;YACV,0FAA0F;YAC1F,WAAW;SACZ;QACD,qBAAqB,EAAE;YACrB,EAAE;YACF,oBAAoB;YACpB,eAAe;SAChB;QACD,gCAAgC,EAAE;YAChC,sGAAsG;YACtG,MAAM;YAEN,iCAAiC;YACjC,WAAW;SACZ;QACD,oBAAoB,EAAE;YACpB,EAAE;YACF,OAAO;SACR;QACD,wBAAwB,EAAE;YACxB,EAAE;YACF,MAAM;YACN,OAAO;YACP,OAAO;YACP,aAAa;SACd;QAED,gDAAgD;QAChD,8CAA8C,EAAE,IAAI;QAEpD,0DAA0D;QAC1D,2CAA2C,EAAE,CAAC,GAAG,wBAAY,EAAE,MAAM,CAAC;QACtE,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAC3D,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAE3D,2BAA2B,EAAE,IAAI;QACjC,+BAA+B,EAAE,IAAI;QACrC,gCAAgC,EAAE,IAAI;QAEtC,QAAQ,EAAE,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI;QAE7C,sBAAsB,EAAE,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,IAAI;QAEhE,cAAc,EAAE,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI;QACpD,qCAAqC,EAAE,CAAC,GAAG,kBAAM,CAAC,sBAAsB,CAAC;QACzE,gDAAgD,EAAE,CAAC,GAAG,wBAAY,CAAC;QAEnE,mBAAmB,EAAE,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,IAAI;QAE1D,
|
|
1
|
+
{"version":3,"file":"build-metadata.js","sourceRoot":"","sources":["../../src/metadata/build-metadata.ts"],"names":[],"mappings":";;AAkBA,sCAgHC;AAjID,sDAI6B;AAC7B,mDAA4C;AAC5C,qDAAoD;AAOpD;;;GAGG;AACH,SAAgB,aAAa,CAC3B,MAA6B,EAC7B,MAAc,EACd,cAA+B;IAE/B,OAAO,uDAAyC,CAAC,KAAK,CAAC;QACrD,MAAM;QAEN,gBAAgB,EAAE;YAChB,SAAS;YAET,yEAAyE;YACzE,kCAAkC;YAClC,kBAAkB;YAClB,oBAAoB;YACpB,sBAAsB;YAEtB,gEAAgE;SACjE;QACD,uBAAuB,EAAE;YACvB,EAAE;YACF,QAAQ,EAAE,6CAA6C;YACvD,+DAA+D;SAChE;QACD,wBAAwB,EAAE;YACxB,QAAQ;YACR,MAAM;YACN,WAAW;YAEX,SAAS;YACT,UAAU;YACV,yBAAyB;YACzB,mBAAmB;YACnB,gBAAgB;YAChB,oBAAoB;YACpB,cAAc;SACf;QACD,wBAAwB,EAAE;YACxB,mFAAmF;YACnF,OAAO;YACP,UAAU;YACV,0FAA0F;YAC1F,WAAW;SACZ;QACD,qBAAqB,EAAE;YACrB,EAAE;YACF,oBAAoB;YACpB,eAAe;SAChB;QACD,gCAAgC,EAAE;YAChC,sGAAsG;YACtG,MAAM;YAEN,iCAAiC;YACjC,WAAW;SACZ;QACD,oBAAoB,EAAE;YACpB,EAAE;YACF,OAAO;SACR;QACD,wBAAwB,EAAE;YACxB,EAAE;YACF,MAAM;YACN,OAAO;YACP,OAAO;YACP,aAAa;SACd;QAED,gDAAgD;QAChD,8CAA8C,EAAE,IAAI;QAEpD,0DAA0D;QAC1D,2CAA2C,EAAE,CAAC,GAAG,wBAAY,EAAE,MAAM,CAAC;QACtE,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAC3D,8CAA8C,EAAE,EAAE,EAAE,OAAO;QAE3D,2BAA2B,EAAE,IAAI;QACjC,+BAA+B,EAAE,IAAI;QACrC,gCAAgC,EAAE,IAAI;QAEtC,QAAQ,EAAE,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI;QAE7C,sBAAsB,EAAE,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,IAAI;QAEhE,cAAc,EAAE,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI;QACpD,qCAAqC,EAAE,CAAC,GAAG,kBAAM,CAAC,sBAAsB,CAAC;QACzE,gDAAgD,EAAE,CAAC,GAAG,wBAAY,CAAC;QAEnE,mBAAmB,EAAE,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,IAAI;QAE1D,6CAA6C;QAC7C,qEAAqE;QACrE,+DAA+D;QAE/D,0DAA0D;QAC1D,qCAAqC,EAAE,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI;QAEzE,qCAAqC,EAAE,IAAI;QAE3C,4DAA4D;QAC5D,iCAAiC,EAAE,CAAC,GAAG,wBAAY,CAAC;QAEpD,6DAA6D;QAC7D,qCAAqC,EACnC,cAAc,EAAE,qCAAqC;QAEvD,wDAAwD;QACxD,mBAAmB,EAAE,cAAc,EAAE,mBAAmB;QAExD,uFAAuF;QACvF,qCAAqC,EAAE,IAAI;KAC5C,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Keyset } from '@atproto/jwk'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthIssuerIdentifier,\n oauthAuthorizationServerMetadataValidator,\n} from '@atproto/oauth-types'\nimport { Client } from '../client/client.js'\nimport { VERIFY_ALGOS } from '../lib/util/crypto.js'\n\nexport type CustomMetadata = {\n authorization_details_types_supported?: string[]\n protected_resources?: string[]\n}\n\n/**\n * @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2}\n * @see {@link https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata}\n */\nexport function buildMetadata(\n issuer: OAuthIssuerIdentifier,\n keyset: Keyset,\n customMetadata?: CustomMetadata,\n): OAuthAuthorizationServerMetadata {\n return oauthAuthorizationServerMetadataValidator.parse({\n issuer,\n\n scopes_supported: [\n 'atproto',\n\n // These serve as hint that this server supports the transitional scopes.\n // This is not a specced behavior.\n 'transition:email',\n 'transition:generic',\n 'transition:chat.bsky',\n\n // Other atproto scopes can't be enumerated as they are dynamic.\n ],\n subject_types_supported: [\n //\n 'public', // The same \"sub\" is returned for all clients\n // 'pairwise', // A different \"sub\" is returned for each client\n ],\n response_types_supported: [\n // OAuth\n 'code',\n // 'token',\n\n // OpenID\n // 'none',\n // 'code id_token token',\n // 'code id_token',\n // 'code token',\n // 'id_token token',\n // 'id_token',\n ],\n response_modes_supported: [\n // https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#ResponseModes\n 'query',\n 'fragment',\n // https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html#FormPostResponseMode\n 'form_post',\n ],\n grant_types_supported: [\n //\n 'authorization_code',\n 'refresh_token',\n ],\n code_challenge_methods_supported: [\n // https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#pkce-code-challenge-method\n 'S256',\n\n // atproto does not allow \"plain\"\n // 'plain',\n ],\n ui_locales_supported: [\n //\n 'en-US',\n ],\n display_values_supported: [\n //\n 'page',\n 'popup',\n 'touch',\n // 'wap', LoL\n ],\n\n // https://datatracker.ietf.org/doc/html/rfc9207\n authorization_response_iss_parameter_supported: true,\n\n // https://datatracker.ietf.org/doc/html/rfc9101#section-4\n request_object_signing_alg_values_supported: [...VERIFY_ALGOS, 'none'],\n request_object_encryption_alg_values_supported: [], // None\n request_object_encryption_enc_values_supported: [], // None\n\n request_parameter_supported: true,\n request_uri_parameter_supported: true,\n require_request_uri_registration: true,\n\n jwks_uri: new URL('/oauth/jwks', issuer).href,\n\n authorization_endpoint: new URL('/oauth/authorize', issuer).href,\n\n token_endpoint: new URL('/oauth/token', issuer).href,\n token_endpoint_auth_methods_supported: [...Client.AUTH_METHODS_SUPPORTED],\n token_endpoint_auth_signing_alg_values_supported: [...VERIFY_ALGOS],\n\n revocation_endpoint: new URL('/oauth/revoke', issuer).href,\n\n // @TODO Should we implement these endpoints?\n // introspection_endpoint: new URL('/oauth/introspect', issuer).href,\n // end_session_endpoint: new URL('/oauth/logout', issuer).href,\n\n // https://datatracker.ietf.org/doc/html/rfc9126#section-5\n pushed_authorization_request_endpoint: new URL('/oauth/par', issuer).href,\n\n require_pushed_authorization_requests: true,\n\n // https://datatracker.ietf.org/doc/html/rfc9449#section-5.1\n dpop_signing_alg_values_supported: [...VERIFY_ALGOS],\n\n // https://datatracker.ietf.org/doc/html/rfc9396#section-14.4\n authorization_details_types_supported:\n customMetadata?.authorization_details_types_supported,\n\n // https://www.rfc-editor.org/rfc/rfc9728.html#section-4\n protected_resources: customMetadata?.protected_resources,\n\n // https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html\n client_id_metadata_document_supported: true,\n })\n}\n"]}
|
package/dist/oauth-hooks.d.ts
CHANGED
|
@@ -62,6 +62,16 @@ export type OAuthHooks = {
|
|
|
62
62
|
deviceId: DeviceId;
|
|
63
63
|
deviceMetadata: RequestMetadata;
|
|
64
64
|
}) => Awaitable<void>;
|
|
65
|
+
/**
|
|
66
|
+
* This hook is called when a user requests a password reset, before the
|
|
67
|
+
* reset password request is triggered on the account store.
|
|
68
|
+
*/
|
|
69
|
+
onResetPasswordRequested?: (data: {
|
|
70
|
+
input: ResetPasswordRequestInput;
|
|
71
|
+
deviceId: DeviceId;
|
|
72
|
+
deviceMetadata: RequestMetadata;
|
|
73
|
+
account: Account;
|
|
74
|
+
}) => Awaitable<void>;
|
|
65
75
|
/**
|
|
66
76
|
* This hook is called when a user confirms a password reset, before the
|
|
67
77
|
* password is actually reset on the account store.
|
|
@@ -71,6 +81,16 @@ export type OAuthHooks = {
|
|
|
71
81
|
deviceId: DeviceId;
|
|
72
82
|
deviceMetadata: RequestMetadata;
|
|
73
83
|
}) => Awaitable<void>;
|
|
84
|
+
/**
|
|
85
|
+
* This hook is called after a user confirms a password reset, and the
|
|
86
|
+
* password was successfully reset on the account store.
|
|
87
|
+
*/
|
|
88
|
+
onResetPasswordConfirmed?: (data: {
|
|
89
|
+
input: ResetPasswordConfirmInput;
|
|
90
|
+
deviceId: DeviceId;
|
|
91
|
+
deviceMetadata: RequestMetadata;
|
|
92
|
+
account: Account;
|
|
93
|
+
}) => Awaitable<void>;
|
|
74
94
|
/**
|
|
75
95
|
* This hook is called when a user successfully signs up.
|
|
76
96
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-hooks.d.ts","sourceRoot":"","sources":["../src/oauth-hooks.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-hooks.d.ts","sourceRoot":"","sources":["../src/oauth-hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth-hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-hooks.js","sourceRoot":"","sources":["../src/oauth-hooks.ts"],"names":[],"mappings":";;;AAoBA,kDAA2C;AAyBzC,uFAzBO,kBAAM,OAyBP;AAtBR,4EAAmE;AAiBjE,kGAjBO,0CAAiB,OAiBP;AAhBnB,4EAAoE;AAmBlE,mGAnBO,2CAAkB,OAmBP;AAlBpB,gFAAuE;AA6BrE,oGA7BO,8CAAmB,OA6BP;AA5BrB,4DAAoD;AAkClD,2FAlCO,2BAAU,OAkCP","sourcesContent":["import { Jwks } from '@atproto/jwk'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport {\n OAuthAccessToken,\n OAuthAuthorizationDetails,\n OAuthAuthorizationRequestParameters,\n OAuthClientMetadata,\n OAuthTokenResponse,\n OAuthTokenType,\n} from '@atproto/oauth-types'\nimport {\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n} from './account/account-store.js'\nimport { SignInData } from './account/sign-in-data.js'\nimport { SignUpInput } from './account/sign-up-input.js'\nimport { ClientAuth } from './client/client-auth.js'\nimport { ClientId } from './client/client-id.js'\nimport { ClientInfo } from './client/client-info.js'\nimport { Client } from './client/client.js'\nimport { DeviceId } from './device/device-id.js'\nimport { DpopProof } from './dpop/dpop-proof.js'\nimport { AccessDeniedError } from './errors/access-denied-error.js'\nimport { AuthorizationError } from './errors/authorization-error.js'\nimport { InvalidRequestError } from './errors/invalid-request-error.js'\nimport { OAuthError } from './errors/oauth-error.js'\nimport {\n HcaptchaClientTokens,\n HcaptchaConfig,\n HcaptchaVerifyResult,\n} from './lib/hcaptcha.js'\nimport { RequestMetadata } from './lib/http/request.js'\nimport { Awaitable, OmitKey } from './lib/util/type.js'\nimport { RequestId } from './request/request-id.js'\nimport { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { TokenClaims } from './token/token-claims.js'\n\n// Make sure all types needed to implement the OAuthHooks are exported\nexport {\n AccessDeniedError,\n type AccessTokenPayload,\n type Account,\n AuthorizationError,\n type Awaitable,\n Client,\n type ClientAuth,\n type ClientId,\n type ClientInfo,\n type DeviceId,\n type DpopProof,\n type HcaptchaClientTokens,\n type HcaptchaConfig,\n type HcaptchaVerifyResult,\n InvalidRequestError,\n type Jwks,\n type OAuthAccessToken,\n type OAuthAuthorizationDetails,\n type OAuthAuthorizationRequestParameters,\n type OAuthClientMetadata,\n OAuthError,\n type OAuthTokenResponse,\n type OAuthTokenType,\n type RequestMetadata,\n type ResetPasswordConfirmInput,\n type ResetPasswordRequestInput,\n type SignInData,\n type SignUpData,\n type SignUpInput,\n type TokenClaims,\n}\n\nexport type OAuthHooks = {\n /**\n * Use this to alter, override or validate the client metadata & jwks returned\n * by the client store.\n *\n * @throws {InvalidClientMetadataError} if the metadata is invalid\n * @see {@link InvalidClientMetadataError}\n */\n getClientInfo?: (\n clientId: ClientId,\n data: { metadata: OAuthClientMetadata; jwks?: Jwks },\n ) => Awaitable<undefined | Partial<ClientInfo>>\n\n /**\n * This hook is called when a user attempts to sign up, after every validation\n * has passed (including hcaptcha).\n */\n onSignUpAttempt?: (data: {\n input: SignUpInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user attempts to sign up, after the hcaptcha\n * `/siteverify` request has been made (and before the result is validated).\n */\n onHcaptchaResult?: (data: {\n input: SignUpInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n tokens: HcaptchaClientTokens\n result: HcaptchaVerifyResult\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user requests a password reset, before the\n * reset password request is triggered on the account store.\n */\n onResetPasswordRequest?: (data: {\n input: ResetPasswordRequestInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user confirms a password reset, before the\n * password is actually reset on the account store.\n */\n onResetPasswordConfirm?: (data: {\n input: ResetPasswordConfirmInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user successfully signs up.\n *\n * @throws {AccessDeniedError} to deny the sign-up\n */\n onSignedUp?: (data: {\n data: SignUpData\n account: Account\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n onSignInAttempt?: (data: {\n data: SignInData\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user successfully signs in.\n *\n * @throws {InvalidRequestError} when the sing-in should be denied\n */\n onSignedIn?: (data: {\n data: SignInData\n account: Account\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * Allows validating an authorization request (typically the requested scopes)\n * before it is created. Note that the validity against the client metadata is\n * already enforced by the OAuth provider.\n *\n * @throws {AuthorizationError}\n */\n onAuthorizationRequest?: (data: {\n client: Client\n clientAuth: null | ClientAuth\n parameters: Readonly<OAuthAuthorizationRequestParameters>\n }) => Awaitable<void>\n\n /**\n * This hook is called when a client is authorized.\n *\n * @throws {AuthorizationError} to deny the authorization request and redirect\n * the user to the client with an OAuth error (other errors will result in an\n * internal server error being displayed to the user)\n *\n * @note We use `deviceMetadata` instead of `clientMetadata` to make it clear\n * that this metadata is from the user device, which might be different from\n * the client metadata (because the OAuth client could live in a backend).\n */\n onAuthorized?: (data: {\n client: Client\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n requestId: RequestId\n }) => Awaitable<void>\n\n /**\n * This hook is called whenever a token is about to be created. You can use\n * it to modify the token claims or perform additional validation.\n *\n * This hook should never throw an error.\n */\n onCreateToken?: (data: {\n client: Client\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n claims: TokenClaims\n }) => Awaitable<void | OmitKey<AccessTokenPayload, 'iss'>>\n\n /**\n * This hook is called whenever a token was just decoded, and basic validation\n * was performed (signature, expiration, not-before).\n *\n * It can be used to modify the payload (e.g., to add custom claims), or to\n * perform additional validation.\n *\n * This hook is called when authenticating requests through the\n * `authenticateRequest()` method in `OAuthVerifier` and `OAuthProvider`.\n *\n * Any error thrown here will be propagated.\n */\n onDecodeToken?: (data: {\n tokenType: OAuthTokenType\n token: OAuthAccessToken\n payload: AccessTokenPayload\n dpopProof: null | DpopProof\n }) => Promise<AccessTokenPayload | void>\n\n /**\n * This hook is called when an authorized client exchanges an authorization\n * code for an access token.\n *\n * @throws {OAuthError} to cancel the token creation and revoke the session\n */\n onTokenCreated?: (data: {\n client: Client\n clientAuth: ClientAuth\n clientMetadata: RequestMetadata\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n }) => Awaitable<void>\n\n /**\n * This hook is called when an authorized client refreshes an access token.\n *\n * @throws {OAuthError} to cancel the token refresh and revoke the session\n */\n onTokenRefreshed?: (data: {\n client: Client\n clientAuth: ClientAuth\n clientMetadata: RequestMetadata\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n }) => Awaitable<void>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth-hooks.js","sourceRoot":"","sources":["../src/oauth-hooks.ts"],"names":[],"mappings":";;;AAoBA,kDAA2C;AAyBzC,uFAzBO,kBAAM,OAyBP;AAtBR,4EAAmE;AAiBjE,kGAjBO,0CAAiB,OAiBP;AAhBnB,4EAAoE;AAmBlE,mGAnBO,2CAAkB,OAmBP;AAlBpB,gFAAuE;AA6BrE,oGA7BO,8CAAmB,OA6BP;AA5BrB,4DAAoD;AAkClD,2FAlCO,2BAAU,OAkCP","sourcesContent":["import { Jwks } from '@atproto/jwk'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport {\n OAuthAccessToken,\n OAuthAuthorizationDetails,\n OAuthAuthorizationRequestParameters,\n OAuthClientMetadata,\n OAuthTokenResponse,\n OAuthTokenType,\n} from '@atproto/oauth-types'\nimport {\n ResetPasswordConfirmInput,\n ResetPasswordRequestInput,\n SignUpData,\n} from './account/account-store.js'\nimport { SignInData } from './account/sign-in-data.js'\nimport { SignUpInput } from './account/sign-up-input.js'\nimport { ClientAuth } from './client/client-auth.js'\nimport { ClientId } from './client/client-id.js'\nimport { ClientInfo } from './client/client-info.js'\nimport { Client } from './client/client.js'\nimport { DeviceId } from './device/device-id.js'\nimport { DpopProof } from './dpop/dpop-proof.js'\nimport { AccessDeniedError } from './errors/access-denied-error.js'\nimport { AuthorizationError } from './errors/authorization-error.js'\nimport { InvalidRequestError } from './errors/invalid-request-error.js'\nimport { OAuthError } from './errors/oauth-error.js'\nimport {\n HcaptchaClientTokens,\n HcaptchaConfig,\n HcaptchaVerifyResult,\n} from './lib/hcaptcha.js'\nimport { RequestMetadata } from './lib/http/request.js'\nimport { Awaitable, OmitKey } from './lib/util/type.js'\nimport { RequestId } from './request/request-id.js'\nimport { AccessTokenPayload } from './signer/access-token-payload.js'\nimport { TokenClaims } from './token/token-claims.js'\n\n// Make sure all types needed to implement the OAuthHooks are exported\nexport {\n AccessDeniedError,\n type AccessTokenPayload,\n type Account,\n AuthorizationError,\n type Awaitable,\n Client,\n type ClientAuth,\n type ClientId,\n type ClientInfo,\n type DeviceId,\n type DpopProof,\n type HcaptchaClientTokens,\n type HcaptchaConfig,\n type HcaptchaVerifyResult,\n InvalidRequestError,\n type Jwks,\n type OAuthAccessToken,\n type OAuthAuthorizationDetails,\n type OAuthAuthorizationRequestParameters,\n type OAuthClientMetadata,\n OAuthError,\n type OAuthTokenResponse,\n type OAuthTokenType,\n type RequestMetadata,\n type ResetPasswordConfirmInput,\n type ResetPasswordRequestInput,\n type SignInData,\n type SignUpData,\n type SignUpInput,\n type TokenClaims,\n}\n\nexport type OAuthHooks = {\n /**\n * Use this to alter, override or validate the client metadata & jwks returned\n * by the client store.\n *\n * @throws {InvalidClientMetadataError} if the metadata is invalid\n * @see {@link InvalidClientMetadataError}\n */\n getClientInfo?: (\n clientId: ClientId,\n data: { metadata: OAuthClientMetadata; jwks?: Jwks },\n ) => Awaitable<undefined | Partial<ClientInfo>>\n\n /**\n * This hook is called when a user attempts to sign up, after every validation\n * has passed (including hcaptcha).\n */\n onSignUpAttempt?: (data: {\n input: SignUpInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user attempts to sign up, after the hcaptcha\n * `/siteverify` request has been made (and before the result is validated).\n */\n onHcaptchaResult?: (data: {\n input: SignUpInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n tokens: HcaptchaClientTokens\n result: HcaptchaVerifyResult\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user requests a password reset, before the\n * reset password request is triggered on the account store.\n */\n onResetPasswordRequest?: (data: {\n input: ResetPasswordRequestInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user requests a password reset, before the\n * reset password request is triggered on the account store.\n */\n onResetPasswordRequested?: (data: {\n input: ResetPasswordRequestInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n account: Account\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user confirms a password reset, before the\n * password is actually reset on the account store.\n */\n onResetPasswordConfirm?: (data: {\n input: ResetPasswordConfirmInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called after a user confirms a password reset, and the\n * password was successfully reset on the account store.\n */\n onResetPasswordConfirmed?: (data: {\n input: ResetPasswordConfirmInput\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n account: Account\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user successfully signs up.\n *\n * @throws {AccessDeniedError} to deny the sign-up\n */\n onSignedUp?: (data: {\n data: SignUpData\n account: Account\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n onSignInAttempt?: (data: {\n data: SignInData\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * This hook is called when a user successfully signs in.\n *\n * @throws {InvalidRequestError} when the sing-in should be denied\n */\n onSignedIn?: (data: {\n data: SignInData\n account: Account\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n }) => Awaitable<void>\n\n /**\n * Allows validating an authorization request (typically the requested scopes)\n * before it is created. Note that the validity against the client metadata is\n * already enforced by the OAuth provider.\n *\n * @throws {AuthorizationError}\n */\n onAuthorizationRequest?: (data: {\n client: Client\n clientAuth: null | ClientAuth\n parameters: Readonly<OAuthAuthorizationRequestParameters>\n }) => Awaitable<void>\n\n /**\n * This hook is called when a client is authorized.\n *\n * @throws {AuthorizationError} to deny the authorization request and redirect\n * the user to the client with an OAuth error (other errors will result in an\n * internal server error being displayed to the user)\n *\n * @note We use `deviceMetadata` instead of `clientMetadata` to make it clear\n * that this metadata is from the user device, which might be different from\n * the client metadata (because the OAuth client could live in a backend).\n */\n onAuthorized?: (data: {\n client: Client\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n deviceId: DeviceId\n deviceMetadata: RequestMetadata\n requestId: RequestId\n }) => Awaitable<void>\n\n /**\n * This hook is called whenever a token is about to be created. You can use\n * it to modify the token claims or perform additional validation.\n *\n * This hook should never throw an error.\n */\n onCreateToken?: (data: {\n client: Client\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n claims: TokenClaims\n }) => Awaitable<void | OmitKey<AccessTokenPayload, 'iss'>>\n\n /**\n * This hook is called whenever a token was just decoded, and basic validation\n * was performed (signature, expiration, not-before).\n *\n * It can be used to modify the payload (e.g., to add custom claims), or to\n * perform additional validation.\n *\n * This hook is called when authenticating requests through the\n * `authenticateRequest()` method in `OAuthVerifier` and `OAuthProvider`.\n *\n * Any error thrown here will be propagated.\n */\n onDecodeToken?: (data: {\n tokenType: OAuthTokenType\n token: OAuthAccessToken\n payload: AccessTokenPayload\n dpopProof: null | DpopProof\n }) => Promise<AccessTokenPayload | void>\n\n /**\n * This hook is called when an authorized client exchanges an authorization\n * code for an access token.\n *\n * @throws {OAuthError} to cancel the token creation and revoke the session\n */\n onTokenCreated?: (data: {\n client: Client\n clientAuth: ClientAuth\n clientMetadata: RequestMetadata\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n }) => Awaitable<void>\n\n /**\n * This hook is called when an authorized client refreshes an access token.\n *\n * @throws {OAuthError} to cancel the token refresh and revoke the session\n */\n onTokenRefreshed?: (data: {\n client: Client\n clientAuth: ClientAuth\n clientMetadata: RequestMetadata\n account: Account\n parameters: OAuthAuthorizationRequestParameters\n }) => Awaitable<void>\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-authorization-page.d.ts","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AAMpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,qDAAqD,CAAA;AAItG,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,aAAa,IAgBjE,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,gCAAgC,KACrC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"send-authorization-page.d.ts","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAA;AAMpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,qDAAqD,CAAA;AAItG,wBAAgB,wBAAwB,CAAC,aAAa,EAAE,aAAa,IAgBjE,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,MAAM,gCAAgC,KACrC,OAAO,CAAC,IAAI,CAAC,CAiCjB"}
|
|
@@ -41,6 +41,9 @@ function sendAuthorizePageFactory(customization) {
|
|
|
41
41
|
return (0, send_web_page_js_1.sendWebPage)(res, {
|
|
42
42
|
meta: [{ name: 'robots', content: 'noindex' }],
|
|
43
43
|
body: (0, index_js_2.html) `<div id="root"></div>`,
|
|
44
|
+
bodyAttrs: {
|
|
45
|
+
class: 'bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100',
|
|
46
|
+
},
|
|
44
47
|
csp,
|
|
45
48
|
coep,
|
|
46
49
|
scripts: [script, ...scripts],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-authorization-page.js","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"send-authorization-page.js","sourceRoot":"","sources":["../../../src/router/assets/send-authorization-page.ts"],"names":[],"mappings":";;AAaA,4DAoDC;AAhED,+FAAsF;AACtF,iGAAwF;AAExF,qDAAiD;AACjD,wEAAuE;AACvE,sDAAuD;AACvD,4EAA8E;AAC9E,iEAAwD;AAExD,2CAA6E;AAC7E,uCAA0C;AAE1C,SAAgB,wBAAwB,CAAC,aAA4B;IACnE,wBAAwB;IACxB,MAAM,iBAAiB,GAAG,IAAA,oDAAsB,EAAC,aAAa,CAAC,CAAA;IAC/D,MAAM,gBAAgB,GAAG,IAAA,kBAAO,EAAC,IAAA,kDAAqB,EAAC,aAAa,CAAC,CAAC,CAAA;IACtE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAA,qBAAS,EAAC,oBAAoB,CAAC,CAAA;IAC3D,MAAM,GAAG,GAAG,IAAA,mBAAQ,EAClB,mBAAO,EACP,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,wBAAY,CAAC,CAAC,CAAC,SAAS,CACnD,CAAA;IACD,MAAM,IAAI,GAAG,aAAa,EAAE,QAAQ;QAClC,CAAC,CAAC,wDAAwD;YACxD,wEAAwE;YACxE,+CAAyB,CAAC,UAAU;QACtC,CAAC,CAAC,+CAAyB,CAAC,cAAc,CAAA;IAE5C,OAAO,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,GAAmB,EACnB,IAAsC;QAEtC,MAAM,IAAA,wBAAc,EAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAE9B,MAAM,MAAM,GAAG,IAAA,wCAAoB,EAAsC;YACvE,mBAAmB,EAAE,iBAAiB;YACtC,eAAe,EAAE;gBACf,UAAU,EAAE,IAAI,CAAC,UAAU;gBAE3B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;gBACxB,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;gBACpC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS;gBACzC,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY;gBAE/C,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;gBAC5B,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU;gBACrC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU;gBACrC,cAAc,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC;aACxD;YACD,UAAU,EAAE,IAAI,CAAC,QAAQ;SAC1B,CAAC,CAAA;QAEF,OAAO,IAAA,8BAAW,EAAC,GAAG,EAAE;YACtB,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;YAC9C,IAAI,EAAE,IAAA,eAAI,EAAA,uBAAuB;YACjC,SAAS,EAAE;gBACT,KAAK,EAAE,+DAA+D;aACvE;YACD,GAAG;YACH,IAAI;YACJ,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;YAC7B,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,gBAAgB,CAAC;SACtC,CAAC,CAAA;IACJ,CAAC,CAAA;AACH,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { buildCustomizationCss } from '../../customization/build-customization-css.js'\nimport { buildCustomizationData } from '../../customization/build-customization-data.js'\nimport { Customization } from '../../customization/customization.js'\nimport { mergeCsp } from '../../lib/csp/index.js'\nimport { declareHydrationData } from '../../lib/html/hydration-data.js'\nimport { cssCode, html } from '../../lib/html/index.js'\nimport { CrossOriginEmbedderPolicy } from '../../lib/http/security-headers.js'\nimport { sendWebPage } from '../../lib/send-web-page.js'\nimport { AuthorizationResultAuthorizePage } from '../../result/authorization-result-authorize-page.js'\nimport { HCAPTCHA_CSP, HydrationData, SPA_CSP, getAssets } from './assets.js'\nimport { setupCsrfToken } from './csrf.js'\n\nexport function sendAuthorizePageFactory(customization: Customization) {\n // Pre-computed options:\n const customizationData = buildCustomizationData(customization)\n const customizationCss = cssCode(buildCustomizationCss(customization))\n const { scripts, styles } = getAssets('authorization-page')\n const csp = mergeCsp(\n SPA_CSP,\n customization?.hcaptcha ? HCAPTCHA_CSP : undefined,\n )\n const coep = customization?.hcaptcha\n ? // https://github.com/hCaptcha/react-hcaptcha/issues/259\n // @TODO Remove the use of `unsafeNone` once the issue above is resolved\n CrossOriginEmbedderPolicy.unsafeNone\n : CrossOriginEmbedderPolicy.credentialless\n\n return async function sendAuthorizePage(\n req: IncomingMessage,\n res: ServerResponse,\n data: AuthorizationResultAuthorizePage,\n ): Promise<void> {\n await setupCsrfToken(req, res)\n\n const script = declareHydrationData<HydrationData['authorization-page']>({\n __customizationData: customizationData,\n __authorizeData: {\n requestUri: data.requestUri,\n\n clientId: data.client.id,\n clientMetadata: data.client.metadata,\n clientTrusted: data.client.info.isTrusted,\n clientFirstParty: data.client.info.isFirstParty,\n\n scope: data.parameters.scope,\n uiLocales: data.parameters.ui_locales,\n loginHint: data.parameters.login_hint,\n permissionSets: Object.fromEntries(data.permissionSets),\n },\n __sessions: data.sessions,\n })\n\n return sendWebPage(res, {\n meta: [{ name: 'robots', content: 'noindex' }],\n body: html`<div id=\"root\"></div>`,\n bodyAttrs: {\n class: 'bg-white text-slate-900 dark:bg-slate-900 dark:text-slate-100',\n },\n csp,\n coep,\n scripts: [script, ...scripts],\n styles: [...styles, customizationCss],\n })\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/oauth-provider",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.",
|
|
6
6
|
"keywords": [
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"jose": "^5.2.0",
|
|
44
44
|
"zod": "^3.23.8",
|
|
45
45
|
"@atproto-labs/fetch": "0.2.3",
|
|
46
|
-
"@atproto-labs/fetch-node": "0.
|
|
46
|
+
"@atproto-labs/fetch-node": "0.2.0",
|
|
47
47
|
"@atproto-labs/pipe": "0.1.1",
|
|
48
48
|
"@atproto-labs/simple-store": "0.3.0",
|
|
49
49
|
"@atproto-labs/simple-store-memory": "0.1.4",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"@atproto/jwk": "0.6.0",
|
|
53
53
|
"@atproto/jwk-jose": "0.1.11",
|
|
54
54
|
"@atproto/lexicon": "0.5.1",
|
|
55
|
-
"@atproto/lexicon-resolver": "0.2.
|
|
56
|
-
"@atproto/oauth-types": "0.
|
|
57
|
-
"@atproto/oauth-provider-api": "0.3.
|
|
58
|
-
"@atproto/oauth-provider-frontend": "0.2.
|
|
59
|
-
"@atproto/oauth-provider-ui": "0.3.
|
|
55
|
+
"@atproto/lexicon-resolver": "0.2.3",
|
|
56
|
+
"@atproto/oauth-types": "0.5.0",
|
|
57
|
+
"@atproto/oauth-provider-api": "0.3.2",
|
|
58
|
+
"@atproto/oauth-provider-frontend": "0.2.3",
|
|
59
|
+
"@atproto/oauth-provider-ui": "0.3.4",
|
|
60
60
|
"@atproto/oauth-scopes": "0.2.1",
|
|
61
61
|
"@atproto/syntax": "0.4.1"
|
|
62
62
|
},
|
|
@@ -258,7 +258,18 @@ export class AccountManager {
|
|
|
258
258
|
})
|
|
259
259
|
|
|
260
260
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
261
|
-
await this.store.resetPasswordRequest(input)
|
|
261
|
+
const account = await this.store.resetPasswordRequest(input)
|
|
262
|
+
|
|
263
|
+
if (!account) {
|
|
264
|
+
return // Silently ignore to prevent user enumeration
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await this.hooks.onResetPasswordRequested?.call(null, {
|
|
268
|
+
input,
|
|
269
|
+
deviceId,
|
|
270
|
+
deviceMetadata,
|
|
271
|
+
account,
|
|
272
|
+
})
|
|
262
273
|
})
|
|
263
274
|
}
|
|
264
275
|
|
|
@@ -274,7 +285,18 @@ export class AccountManager {
|
|
|
274
285
|
})
|
|
275
286
|
|
|
276
287
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
277
|
-
await this.store.resetPasswordConfirm(input)
|
|
288
|
+
const account = await this.store.resetPasswordConfirm(input)
|
|
289
|
+
|
|
290
|
+
if (!account) {
|
|
291
|
+
throw new InvalidRequestError('Invalid token')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
await this.hooks.onResetPasswordConfirmed?.call(null, {
|
|
295
|
+
input,
|
|
296
|
+
deviceId,
|
|
297
|
+
deviceMetadata,
|
|
298
|
+
account,
|
|
299
|
+
})
|
|
278
300
|
})
|
|
279
301
|
}
|
|
280
302
|
|
|
@@ -171,8 +171,13 @@ export interface AccountStore {
|
|
|
171
171
|
filter: { sub: Sub } | { deviceId: DeviceId },
|
|
172
172
|
): Awaitable<DeviceAccount[]>
|
|
173
173
|
|
|
174
|
-
resetPasswordRequest(
|
|
175
|
-
|
|
174
|
+
resetPasswordRequest(
|
|
175
|
+
data: ResetPasswordRequestInput,
|
|
176
|
+
): Awaitable<null | Account>
|
|
177
|
+
|
|
178
|
+
resetPasswordConfirm(
|
|
179
|
+
data: ResetPasswordConfirmInput,
|
|
180
|
+
): Awaitable<null | Account>
|
|
176
181
|
|
|
177
182
|
/**
|
|
178
183
|
* @throws {HandleUnavailableError} - To indicate that the handle is already taken
|