Phase 19: Local Auth (No-OIDC Mode) #23
@@ -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 ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -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.');
|
||||
|
||||
Reference in New Issue
Block a user