authorize.tsx (2716B)
1 import { Link } from "#http/form.ts"; 2 import { AppState } from "#http/routes/_middleware.ts"; 3 import { Handlers, PageProps } from "$fresh/src/server/types.ts"; 4 import { ExceedingLimit } from "#core/domain/limiter.ts"; 5 6 type Props = { 7 scope: string[]; 8 description: string|null; 9 }; 10 11 export const handler: Handlers<Props, AppState<"/connect">> = { 12 async GET(req, ctx) { 13 const { oauth2Validate } = ctx.state.app; 14 const url = new URL(req.url); 15 16 const result = await oauth2Validate.execute({ 17 clientId: String(url.searchParams.get("client_id")), 18 scope: url.searchParams.has("scope") 19 ? String(url.searchParams.get("scope")) 20 : null, 21 }); 22 23 if (!result.valid) { 24 return ctx.renderNotFound(); 25 } 26 27 return ctx.render({ 28 scope: result.scope, 29 description: result.description, 30 }); 31 }, 32 33 async POST(req, ctx) { 34 const { forms, app } = ctx.state; 35 const { oauth2Initiate } = app; 36 try { 37 const url = new URL(req.url); 38 const clientId = `${url.searchParams.get("client_id")}`; 39 const result = await oauth2Initiate.execute({ 40 ip: ctx.remoteAddr.hostname, 41 clientId, 42 scope: url.searchParams.has("scope") 43 ? String(url.searchParams.get("scope")) 44 : null, 45 state: url.searchParams.has("state") 46 ? String(url.searchParams.get("state")) 47 : null, 48 }); 49 50 if (!result.initiated) { 51 return ctx.renderNotFound(); 52 } 53 54 const scope = result.scope; 55 let back = { 56 form: "/oauth2/callback", 57 context: { flowId: result.uuid, clientId }, 58 } as Link; 59 60 if (scope.includes("phone-number")) { 61 back = { form: "/register/phone", context: { back } }; 62 } 63 64 if (scope.includes("id-document")) { 65 back = { 66 form: "/register/id-document", 67 context: { side: "doc-front", back }, 68 }; 69 } 70 71 return forms.redirect({ form: "/connect", context: { back } }); 72 } catch (error) { 73 if (error instanceof ExceedingLimit) { 74 throw error; 75 } 76 return ctx.renderNotFound(); 77 } 78 }, 79 }; 80 81 const LABELS = { 82 "phone-number": "Phone number", 83 "id-document": "ID Document", 84 } as Record<string, string>; 85 86 export default function AuthorizePage({ data }: PageProps<Props>) { 87 return ( 88 <article> 89 <header style="text-align: center;"> 90 <b>Authorize</b> 91 </header> 92 <form method="POST"> 93 <p>{data.description}</p> 94 <ul> 95 {data.scope.map((scope) => <li>{LABELS[scope] ?? scope}</li>)} 96 </ul> 97 <div role="group"> 98 <button type="submit">Consent</button> 99 </div> 100 </form> 101 </article> 102 ); 103 }