forked from pdsls.dev/pdsls
this repo has no description
at main 3.1 kB view raw
1import { createSignal } from "solid-js"; 2import { 3 configureOAuth, 4 createAuthorizationUrl, 5 deleteStoredSession, 6 finalizeAuthorization, 7 getSession, 8 OAuthUserAgent, 9 resolveFromIdentity, 10 resolveFromService, 11 type Session, 12} from "@atcute/oauth-browser-client"; 13import { Did } from "@atcute/lexicons"; 14import { isHandle } from "@atcute/lexicons/syntax"; 15import { TextInput } from "./text-input"; 16 17configureOAuth({ 18 metadata: { 19 client_id: import.meta.env.VITE_OAUTH_CLIENT_ID, 20 redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URL, 21 }, 22}); 23 24export const [agent, setAgent] = createSignal<OAuthUserAgent | undefined>(); 25 26const Login = () => { 27 const [notice, setNotice] = createSignal(""); 28 const [loginInput, setLoginInput] = createSignal(""); 29 30 const login = async (handle: string) => { 31 try { 32 if (!handle) return; 33 let resolved; 34 if (!isHandle(handle)) { 35 setNotice(`Resolving your service...`); 36 resolved = await resolveFromService(handle); 37 } else { 38 setNotice(`Resolving your identity...`); 39 resolved = await resolveFromIdentity(handle); 40 } 41 42 setNotice(`Contacting your data server...`); 43 const authUrl = await createAuthorizationUrl({ 44 scope: import.meta.env.VITE_OAUTH_SCOPE, 45 ...resolved, 46 }); 47 48 setNotice(`Redirecting...`); 49 await new Promise((resolve) => setTimeout(resolve, 250)); 50 51 location.assign(authUrl); 52 } catch (e) { 53 console.error(e); 54 setNotice(`${e}`); 55 } 56 }; 57 58 return ( 59 <form class="flex flex-col gap-y-1" onsubmit={(e) => e.preventDefault()}> 60 <div class="flex items-center gap-2"> 61 <label for="handle"> 62 <div class="i-lucide-user-round-plus text-lg" /> 63 </label> 64 <TextInput 65 id="handle" 66 placeholder="user.bsky.social" 67 onInput={(e) => setLoginInput(e.currentTarget.value)} 68 class="grow" 69 /> 70 <button onclick={() => login(loginInput())}> 71 <div class="i-lucide-log-in text-lg" /> 72 </button> 73 </div> 74 <div>{notice()}</div> 75 </form> 76 ); 77}; 78 79const retrieveSession = async () => { 80 const init = async (): Promise<Session | undefined> => { 81 const params = new URLSearchParams(location.hash.slice(1)); 82 83 if (params.has("state") && (params.has("code") || params.has("error"))) { 84 history.replaceState(null, "", location.pathname + location.search); 85 86 const session = await finalizeAuthorization(params); 87 const did = session.info.sub; 88 89 localStorage.setItem("lastSignedIn", did); 90 return session; 91 } else { 92 const lastSignedIn = localStorage.getItem("lastSignedIn"); 93 94 if (lastSignedIn) { 95 try { 96 return await getSession(lastSignedIn as Did); 97 } catch (err) { 98 deleteStoredSession(lastSignedIn as Did); 99 localStorage.removeItem("lastSignedIn"); 100 throw err; 101 } 102 } 103 } 104 }; 105 106 const session = await init().catch(() => {}); 107 108 if (session) setAgent(new OAuthUserAgent(session)); 109}; 110 111export { Login, retrieveSession };