import { Client } from "@atcute/client"; import { Did } from "@atcute/lexicons"; import { isDid, isHandle } from "@atcute/lexicons/syntax"; import { configureOAuth, createAuthorizationUrl, defaultIdentityResolver, finalizeAuthorization, getSession, OAuthUserAgent, type Session, } from "@atcute/oauth-browser-client"; import { createSignal, Show } from "solid-js"; import { didDocumentResolver, handleResolver } from "../utils/api"; configureOAuth({ metadata: { client_id: import.meta.env.VITE_OAUTH_CLIENT_ID, redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URL, }, identityResolver: defaultIdentityResolver({ handleResolver: handleResolver, didDocumentResolver: didDocumentResolver, }), }); export const [agent, setAgent] = createSignal(); type Account = { signedIn: boolean; handle?: string; }; export type Sessions = Record; const Login = () => { const [notice, setNotice] = createSignal(""); const [loginInput, setLoginInput] = createSignal(""); const login = async (handle: string) => { try { setNotice(""); if (!handle) return; setNotice(`Contacting your data server...`); const authUrl = await createAuthorizationUrl({ scope: import.meta.env.VITE_OAUTH_SCOPE, target: isHandle(handle) || isDid(handle) ? { type: "account", identifier: handle } : { type: "pds", serviceUrl: handle }, }); setNotice(`Redirecting...`); await new Promise((resolve) => setTimeout(resolve, 250)); location.assign(authUrl); } catch (e) { console.error(e); setNotice(`${e}`); } }; return (
e.preventDefault()}>
setLoginInput(e.currentTarget.value)} />
{notice()}
); }; const retrieveSession = async () => { const init = async (): Promise => { const params = new URLSearchParams(location.hash.slice(1)); if (params.has("state") && (params.has("code") || params.has("error"))) { history.replaceState(null, "", location.pathname + location.search); const auth = await finalizeAuthorization(params); const did = auth.session.info.sub; localStorage.setItem("lastSignedIn", did); const sessions = localStorage.getItem("sessions"); const newSessions: Sessions = sessions ? JSON.parse(sessions) : { [did]: {} }; newSessions[did] = { signedIn: true }; localStorage.setItem("sessions", JSON.stringify(newSessions)); return auth.session; } else { const lastSignedIn = localStorage.getItem("lastSignedIn"); if (lastSignedIn) { const sessions = localStorage.getItem("sessions"); const newSessions: Sessions = sessions ? JSON.parse(sessions) : {}; try { const session = await getSession(lastSignedIn as Did); const rpc = new Client({ handler: new OAuthUserAgent(session) }); const res = await rpc.get("com.atproto.server.getSession"); newSessions[lastSignedIn].signedIn = true; localStorage.setItem("sessions", JSON.stringify(newSessions)); if (!res.ok) throw res.data.error; return session; } catch (err) { newSessions[lastSignedIn].signedIn = false; localStorage.setItem("sessions", JSON.stringify(newSessions)); throw err; } } } }; const session = await init(); if (session) setAgent(new OAuthUserAgent(session)); }; export { Login, retrieveSession };