authServerFor
uses tcmts.atproto.localNetwork, which uses process
The authorization server a PDS signs in with, and its metadata.
import { getJson, localNetwork } from "#codebase/tcmts/atproto"; import type { AuthServer } from "#codebase/tcmts/atproto"; export async function authServerFor(pds: string): Promise<AuthServer> { const resource = await getJson<{ authorization_servers?: string[] }>( `${pds}/.well-known/oauth-protected-resource`, ); const issuer = resource.authorization_servers?.[0]?.replace(/\/+$/, ""); if (!issuer) throw new Error(`${pds} names no authorization server`); const meta = await getJson<AuthServer>(`${issuer}/.well-known/oauth-authorization-server`); if (meta.issuer.replace(/\/+$/, "") !== issuer) throw new Error(`${issuer}'s metadata is for ${meta.issuer}`); // (where tokens and the browser go: https, as a PDS is, but on a local network) const https = (u: string | undefined) => typeof u === "string" && (u.startsWith("https://") || (localNetwork() && u.startsWith("http://"))); for (const k of [ "issuer", "authorization_endpoint", "token_endpoint", "pushed_authorization_request_endpoint", ] as const) if (!https(meta[k])) throw new Error(`${issuer}'s ${k} must be https: ${String(meta[k])}`); return meta; }