A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at fff48ea3213bb11efcfcb7db85be1dfcd2bebc5e 62 lines 2.1 kB view raw
1import { JoseKey } from "@atproto/jwk-jose"; 2import { NodeOAuthClient, type RuntimeLock } from "@atproto/oauth-client-node"; 3import Redis from "ioredis"; 4import Redlock from "redlock"; 5import type { Database } from "../db"; 6import { env } from "../lib/env"; 7import { SessionStore, StateStore } from "./storage"; 8 9export const createClient = async (db: Database) => { 10 const publicUrl = env.PUBLIC_URL; 11 const url = publicUrl.includes("localhost") 12 ? `http://127.0.0.1:${env.PORT}` 13 : publicUrl; 14 const enc = encodeURIComponent; 15 16 const redis = new Redis(env.REDIS_URL); 17 const redlock = new Redlock([redis]); 18 19 const requestLock: RuntimeLock = async (key, fn) => { 20 const lock = await redlock.acquire([key], 45e3); // 45 seconds 21 try { 22 return await fn(); 23 } finally { 24 await lock.release(); 25 } 26 }; 27 28 return new NodeOAuthClient({ 29 clientMetadata: { 30 client_name: "Rocksky", 31 client_id: !publicUrl.includes("localhost") 32 ? `${url}/oauth-client-metadata.json` 33 : `http://localhost?redirect_uri=${enc( 34 `${url}/oauth/callback`, 35 )}&scope=${enc("atproto transition:generic")}`, 36 client_uri: url, 37 redirect_uris: [`${url}/oauth/callback`], 38 scope: "atproto transition:generic", 39 grant_types: ["authorization_code", "refresh_token"], 40 response_types: ["code"], 41 application_type: "web", 42 token_endpoint_auth_method: url.startsWith("https") 43 ? "private_key_jwt" 44 : "none", 45 token_endpoint_auth_signing_alg: url.startsWith("https") 46 ? "ES256" 47 : undefined, 48 dpop_bound_access_tokens: true, 49 jwks_uri: url.startsWith("https") ? `${url}/jwks.json` : undefined, 50 }, 51 keyset: url.startsWith("https") 52 ? await Promise.all([ 53 JoseKey.fromImportable(env.PRIVATE_KEY_1), 54 JoseKey.fromImportable(env.PRIVATE_KEY_2), 55 JoseKey.fromImportable(env.PRIVATE_KEY_3), 56 ]) 57 : undefined, 58 stateStore: new StateStore(db), 59 sessionStore: new SessionStore(db), 60 requestLock, 61 }); 62};