an attempt to make a lightweight, easily self-hostable, scoped bluesky appview
at main 82 lines 2.7 kB view raw
1// kindly borrowed from https://github.com/usounds/Skyblur/blob/303793148a6373b313d3354a453876cad864eae2/backend/src/logic/JWTTokenHandler.ts#L2 2// MIT License 3import * as didJWT from "npm:did-jwt" 4import { DIDDocument, DIDResolutionOptions, ParsedDID, Resolver, } from 'npm:did-resolver'; 5import { DIDResolver, ResolverRegistry } from 'npm:did-resolver'; 6import { getResolver as getWebResolver } from 'npm:web-did-resolver'; 7 8export function getResolver() { 9 async function resolve( 10 did: string, 11 parsed: ParsedDID, 12 didResolver: Resolver, 13 options: DIDResolutionOptions 14 ): Promise<DIDDocument> { 15 const encodedDid = encodeURIComponent(did); 16 const didUrl = `https://plc.directory/${encodedDid}`; 17 const response = await fetch(didUrl); 18 const didDoc = await response.json() as DIDDocument 19 return didDoc 20 } 21 22 return { DidPlcResolver: resolve } 23} 24const myResolver = getResolver() 25const webResolver = getWebResolver() 26const resolver: ResolverRegistry = { 27 'plc': myResolver.DidPlcResolver as unknown as DIDResolver, 28 ...webResolver 29} 30export const resolverInstance = new Resolver(resolver) 31export type Service = { 32 id: string; 33 type: string; 34 serviceEndpoint: string | Record<string, any> | Array<Record<string, any>>; 35} 36 37export const verifyJWT = async (auth: string, audience:string) => { 38 const authorization = auth.replace('Bearer ', '').trim() 39 const decodedJWT = authorization.replace('Bearer ', '').trim() 40 41 console.log("audience is: ", audience) 42 43 const result = await didJWT.verifyJWT(decodedJWT, { 44 resolver: resolverInstance, 45 audience: audience 46 }) 47 48 return result 49 50} 51export const fetchDiDDocument = async (did: string) => { 52 try { 53 const didDocument = await resolverInstance.resolve(did) 54 return didDocument 55 } catch (error) { 56 console.error('Error fetching service endpoint:', error); 57 } 58 59 60}; 61 62export const fetchServiceEndpoint = async (did: string) => { 63 try { 64 const response = await fetchDiDDocument(did); 65 if (!response) { 66 throw new Error('Invalid DID document response'); 67 } 68 69 const didDocument = response as unknown as DIDDocument; 70 71 // didDocument.serviceが存在するかチェック 72 const service = didDocument.service?.find((s: Service) => s.id === '#atproto_pds'); 73 74 if (service && service.serviceEndpoint) { 75 return service.serviceEndpoint; 76 } else { 77 throw new Error('Service with id #atproto_pds not found or no service endpoint available'); 78 } 79 } catch (error) { 80 console.error('Error fetching service endpoint:', error); 81 } 82};