Scratch space for learning atproto app development
at main 2.3 kB view raw
1import { 2 Keyset, 3 JoseKey, 4 atprotoLoopbackClientMetadata, 5 NodeOAuthClient, 6 OAuthClientMetadataInput, 7} from '@atproto/oauth-client-node' 8import assert from 'node:assert' 9 10import type { Database } from '#/db' 11import { env } from '#/env' 12import { SessionStore, StateStore } from './storage' 13 14export async function createOAuthClient(db: Database) { 15 // Confidential client require a keyset accessible on the internet. Non 16 // internet clients (e.g. development) cannot expose a keyset on the internet 17 // so they can't be private.. 18 const keyset = 19 env.PUBLIC_URL && env.PRIVATE_KEYS 20 ? new Keyset( 21 await Promise.all( 22 env.PRIVATE_KEYS.map((jwk) => JoseKey.fromJWK(jwk)), 23 ), 24 ) 25 : undefined 26 27 assert( 28 !env.PUBLIC_URL || keyset?.size, 29 'ATProto requires backend clients to be confidential. Make sure to set the PRIVATE_KEYS environment variable.', 30 ) 31 32 // If a keyset is defined (meaning the client is confidential). Let's make 33 // sure it has a private key for signing. Note: findPrivateKey will throw if 34 // the keyset does not contain a suitable private key. 35 const pk = keyset?.findPrivateKey({ use: 'sig' }) 36 37 const clientMetadata: OAuthClientMetadataInput = env.PUBLIC_URL 38 ? { 39 client_name: 'Statusphere Example App', 40 client_id: `${env.PUBLIC_URL}/oauth-client-metadata.json`, 41 jwks_uri: `${env.PUBLIC_URL}/.well-known/jwks.json`, 42 redirect_uris: [`${env.PUBLIC_URL}/oauth/callback`], 43 scope: 'atproto transition:generic', 44 grant_types: ['authorization_code', 'refresh_token'], 45 response_types: ['code'], 46 application_type: 'web', 47 token_endpoint_auth_method: pk ? 'private_key_jwt' : 'none', 48 token_endpoint_auth_signing_alg: pk ? pk.alg : undefined, 49 dpop_bound_access_tokens: true, 50 } 51 : atprotoLoopbackClientMetadata( 52 `http://localhost?${new URLSearchParams([ 53 ['redirect_uri', `http://127.0.0.1:${env.PORT}/oauth/callback`], 54 ['scope', `atproto transition:generic`], 55 ])}`, 56 ) 57 58 return new NodeOAuthClient({ 59 keyset, 60 clientMetadata, 61 stateStore: new StateStore(db), 62 sessionStore: new SessionStore(db), 63 plcDirectoryUrl: env.PLC_URL, 64 handleResolver: env.PDS_URL, 65 }) 66}