forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
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};