import { useMutation, useQuery } from "@tanstack/react-query" import { createFileRoute, redirect } from "@tanstack/react-router" import { AlertTriangle } from "lucide-react" import { OauthService } from "@/client" import { AuthLayout } from "@/components/Common/AuthLayout" import { Alert, AlertDescription } from "@/components/ui/alert" import { Button } from "@/components/ui/button" import { LoadingButton } from "@/components/ui/loading-button" import { Skeleton } from "@/components/ui/skeleton" import { isLoggedIn } from "@/hooks/useAuth" /** * Where an agent sends someone to be let in. * * Everything shown here is checked by the server first, and the URL the browser * is finally sent to is the one the server hands back — never the one in the * address bar — so a doctored link cannot redirect an approval somewhere else. */ export const Route = createFileRoute("/oauth/authorize")({ component: Authorize, validateSearch: (search: Record) => ({ client_id: String(search.client_id ?? ""), redirect_uri: String(search.redirect_uri ?? ""), code_challenge: String(search.code_challenge ?? ""), code_challenge_method: String(search.code_challenge_method ?? "S256"), state: search.state ? String(search.state) : undefined, resource: search.resource ? String(search.resource) : undefined, }), beforeLoad: ({ location }) => { if (!isLoggedIn()) { throw redirect({ to: "/login", search: { redirect: location.href }, }) } }, head: () => ({ meta: [{ title: "Authorize - Fluksio" }], }), }) function Authorize() { const search = Route.useSearch() const { data: info, isPending, error, } = useQuery({ queryKey: ["oauth", "authorize", search.client_id, search.redirect_uri], queryFn: () => OauthService.authorizeValidate({ clientId: search.client_id, redirectUri: search.redirect_uri, }), retry: false, }) const approve = useMutation({ mutationFn: () => OauthService.authorize({ requestBody: { client_id: search.client_id, redirect_uri: search.redirect_uri, code_challenge: search.code_challenge, code_challenge_method: search.code_challenge_method, state: search.state, resource: search.resource, }, }), onSuccess: (response) => { // The server's URL, built from the registered redirect. window.location.assign(response.redirect_url) }, }) const deny = () => { if (!info) return const url = new URL(info.redirect_uri) url.searchParams.set("error", "access_denied") if (search.state) url.searchParams.set("state", search.state) window.location.assign(url.toString()) } return (

Authorize access

{isPending ? (
) : error || !info ? ( This authorization request is not valid. Start it again from the application that sent you here. ) : ( <>

{info.client_name} {" "} wants to read and change your flows, and to run them. It will act as you. Only allow this if you started it.

approve.mutate()} data-testid="approve-client" > Allow
{approve.isError ? ( That did not work. Start again from the application. ) : null} )}
) }