Scratch space for learning atproto app development
1import { JoseKey } from '@atproto/jwk-jose'
2import { NodeOAuthClient } from '@atproto/oauth-client-node'
3import type { Database } from '#/db'
4import { env } from '#/env'
5import { SessionStore, StateStore } from './storage'
6
7export const createClient = async (db: Database) => {
8 const url = env.PUBLIC_URL
9 const privateKeyPKCS8 = Buffer.from(env.PRIVATE_KEY_ES256_B64, 'base64').toString()
10 const privateKey = await JoseKey.fromImportable(privateKeyPKCS8, 'key1')
11 return new NodeOAuthClient({
12 // This object will be used to build the payload of the /client-metadata.json
13 // endpoint metadata, exposing the client metadata to the OAuth server.
14 clientMetadata: {
15 // Must be a URL that will be exposing this metadata
16 client_id: `${url}/client-metadata.json`,
17 client_uri: url,
18 client_name: 'ATProto Express App',
19 jwks_uri: `${url}/jwks.json`,
20 logo_uri: `${url}/logo.png`,
21 tos_uri: `${url}/tos`,
22 policy_uri: `${url}/policy`,
23 redirect_uris: [`${url}/oauth/callback`],
24 token_endpoint_auth_signing_alg: 'ES256',
25 scope: 'profile email offline_access',
26 grant_types: ['authorization_code', 'refresh_token'],
27 response_types: ['code'],
28 application_type: 'web',
29 token_endpoint_auth_method: 'private_key_jwt',
30 dpop_bound_access_tokens: true,
31 },
32
33 // Used to authenticate the client to the token endpoint. Will be used to
34 // build the jwks object to be exposed on the "jwks_uri" endpoint.
35 keyset: [privateKey],
36
37 // Interface to store authorization state data (during authorization flows)
38 stateStore: new StateStore(db),
39
40 // Interface to store authenticated session data
41 sessionStore: new SessionStore(db),
42 })
43}