Show redirect screen after OAuth2 consent submit

After allow or deny succeeds, replace the consent form with a full-page
redirect message naming the application and a spinner while the browser
navigates to the OAuth callback URL.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
This commit is contained in:
Cursor Agent
2026-07-02 16:35:00 +00:00
parent 41d8f945c0
commit fa455c315a

View File

@@ -24,9 +24,10 @@ import {
IconLockOpen,
IconUser,
IconUserCircle,
Spinner,
useToast,
} from "@probo/ui";
import { useCallback, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { type PreloadedQuery, useMutation, usePreloadedQuery } from "react-relay";
import { graphql } from "relay-runtime";
@@ -160,6 +161,10 @@ export default function ConsentPage(props: {
const { toast } = useToast();
const [deviceResult, setDeviceResult] = useState<"authorized" | "denied" | null>(null);
const [pendingAction, setPendingAction] = useState<"allow" | "deny" | null>(null);
const [redirectState, setRedirectState] = useState<{
url: string;
approved: boolean;
} | null>(null);
const data = usePreloadedQuery<ConsentPageQuery>(consentPageQuery, props.queryRef);
usePageTitle(__("Authorize Application"));
@@ -178,6 +183,12 @@ export default function ConsentPage(props: {
[__, apiScopes.length],
);
useEffect(() => {
if (!redirectState) return;
window.location.href = redirectState.url;
}, [redirectState]);
const handleAction = useCallback(
(approved: boolean) => {
if (!consent.id || pendingAction !== null) return;
@@ -221,7 +232,10 @@ export default function ConsentPage(props: {
}
if (response.approveConsent.redirectURL) {
window.location.href = response.approveConsent.redirectURL;
setRedirectState({
url: response.approveConsent.redirectURL,
approved,
});
}
},
onError: (err) => {
@@ -271,6 +285,27 @@ export default function ConsentPage(props: {
);
}
if (redirectState) {
return (
<div className="w-full max-w-md mx-auto pt-8 space-y-6 text-center">
<Spinner size={24} centered className="text-txt-tertiary" />
<div className="space-y-2">
<h1 className="text-2xl font-bold">
{redirectState.approved ? __("Authorization Complete") : __("Access Denied")}
</h1>
<p className="text-txt-tertiary">
{__("You will be redirected to")}
{" "}
<span className="font-medium text-txt-secondary">
{consent.application.name}
</span>
…
</p>
</div>
</div>
);
}
return (
<div className="w-full max-w-md mx-auto pt-8 space-y-6">
<div className="space-y-2 text-center">