fix(19): CR-01 align OIDC-link client contract with server (authorizationUrl)
This commit is contained in:
@@ -219,11 +219,15 @@ export async function fetchAdminResetPassword(
|
|||||||
/**
|
/**
|
||||||
* POST /api/me/link-oidc — initiate the OIDC-link flow for the current local user (Surface 13).
|
* POST /api/me/link-oidc — initiate the OIDC-link flow for the current local user (Surface 13).
|
||||||
*
|
*
|
||||||
* The server returns a redirect URL to begin the OIDC authorization-code flow with a
|
* The server returns the OIDC authorization endpoint URL (with a signed `state` parameter
|
||||||
* state parameter encoding the linkUserId claim. The caller should follow the redirect
|
* encoding the linkUserId claim) to begin the authorization-code flow. The caller should
|
||||||
* via top-level navigation (window.location.href = result.redirectUrl).
|
* follow it via top-level navigation (window.location.href = authorizationUrl) when present.
|
||||||
|
*
|
||||||
|
* authorizationUrl is null when OIDC is not configured in env (the server cannot build the
|
||||||
|
* URL); callers MUST handle that case and surface an error instead of navigating to null.
|
||||||
|
* The server contract is { signedState, authorizationUrl } (see apps/api/src/routes/me.ts).
|
||||||
*/
|
*/
|
||||||
export async function fetchLinkOidc(): Promise<{ redirectUrl: string }> {
|
export async function fetchLinkOidc(): Promise<{ authorizationUrl: string | null }> {
|
||||||
const res = await fetch('/api/me/link-oidc', {
|
const res = await fetch('/api/me/link-oidc', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@@ -234,7 +238,7 @@ export async function fetchLinkOidc(): Promise<{ redirectUrl: string }> {
|
|||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`fetchLinkOidc failed: ${res.status}`);
|
throw new Error(`fetchLinkOidc failed: ${res.status}`);
|
||||||
}
|
}
|
||||||
return res.json() as Promise<{ redirectUrl: string }>;
|
return res.json() as Promise<{ signedState: string; authorizationUrl: string | null }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── /api/me ────────────────────────────────────────────────────────────────
|
// ── /api/me ────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -859,9 +859,15 @@ function LinkOidcSheet({ isOpen, onClose }: LinkOidcSheetProps) {
|
|||||||
const linkMutation = useMutation({
|
const linkMutation = useMutation({
|
||||||
mutationFn: fetchLinkOidc,
|
mutationFn: fetchLinkOidc,
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
// Close the sheet and initiate OIDC link flow
|
// authorizationUrl is null when OIDC is not configured in env (server could not
|
||||||
|
// build the URL). Do NOT navigate to null — surface an error and keep the sheet open.
|
||||||
|
if (!data.authorizationUrl) {
|
||||||
|
setError('Something went wrong. Please try again.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Close the sheet and initiate the OIDC link flow via top-level navigation.
|
||||||
onClose();
|
onClose();
|
||||||
window.location.href = data.redirectUrl;
|
window.location.href = data.authorizationUrl;
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
setError('Something went wrong. Please try again.');
|
setError('Something went wrong. Please try again.');
|
||||||
|
|||||||
Reference in New Issue
Block a user