fix(19): CR-01 align OIDC-link client contract with server (authorizationUrl)

This commit is contained in:
Lucas Berger
2026-06-17 20:15:23 -04:00
parent 4b635784e4
commit 1688f229e0
2 changed files with 17 additions and 7 deletions
+9 -5
View File
@@ -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).
*
* The server returns a redirect URL to begin the OIDC authorization-code flow with a
* state parameter encoding the linkUserId claim. The caller should follow the redirect
* via top-level navigation (window.location.href = result.redirectUrl).
* The server returns the OIDC authorization endpoint URL (with a signed `state` parameter
* encoding the linkUserId claim) to begin the authorization-code flow. The caller should
* 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', {
method: 'POST',
credentials: 'include',
@@ -234,7 +238,7 @@ export async function fetchLinkOidc(): Promise<{ redirectUrl: string }> {
if (!res.ok) {
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 ────────────────────────────────────────────────────────────────
+8 -2
View File
@@ -859,9 +859,15 @@ function LinkOidcSheet({ isOpen, onClose }: LinkOidcSheetProps) {
const linkMutation = useMutation({
mutationFn: fetchLinkOidc,
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();
window.location.href = data.redirectUrl;
window.location.href = data.authorizationUrl;
},
onError: () => {
setError('Something went wrong. Please try again.');