import {useMutation} from '@tanstack/react-query' import {useEffect, useState} from 'react' import {testUserPoolSignIn} from '@/api/cloudProxyClient' type Props = { poolId: string appClients: Array<{clientId: string; clientName: string}> loginLabel: string runtimeReachable: boolean } const KEY_CLAIMS = ['sub', 'email', 'cognito:username', 'cognito:groups', 'client_id', 'aud', 'token_use', 'exp'] export function CognitoSignInTest({poolId, appClients, loginLabel, runtimeReachable}: Props) { const [clientId, setClientId] = useState(appClients[0]?.clientId ?? '') const [username, setUsername] = useState('') const [password, setPassword] = useState('') useEffect(() => { if (!appClients.some((client) => client.clientId === clientId)) setClientId(appClients[0]?.clientId ?? '') }, [appClients, clientId]) const signIn = useMutation({ mutationFn: () => testUserPoolSignIn('aws', poolId, {clientId, username: username.trim(), password}), }) const result = signIn.data if (appClients.length === 0) return null return <>

Test sign-in

Signs in the way an app does and shows what is inside the tokens
{ event.preventDefault(); if (clientId && username.trim() && password) signIn.mutate() }}>
{signIn.error instanceof Error &&

{signIn.error.message}

} {result?.outcome === 'rejected' &&

Refused {result.code} {result.message}

} {result?.outcome === 'challenge' &&

Cognito wants another step {result.challengeName} {challengeHint(result.challengeName)}

} {result?.outcome === 'signed-in' &&

Signed in. {result.expiresIn ? `The ID and access tokens are valid for ${Math.round(result.expiresIn / 60)} minutes.` : ''}

} } function ClaimsTable({title, claims}: {title: string; claims: Record}) { const keys = [...KEY_CLAIMS.filter((key) => key in claims), ...Object.keys(claims).filter((key) => !KEY_CLAIMS.includes(key)).sort()] return

{title}

{keys.map((key) => ( ))}
{key}{formatClaim(key, claims[key])}
} function formatClaim(key: string, value: unknown): string { if ((key === 'exp' || key === 'iat' || key === 'auth_time') && typeof value === 'number') return `${value} (${new Date(value * 1000).toLocaleString()})` if (Array.isArray(value)) return value.join(', ') return typeof value === 'string' ? value : JSON.stringify(value) } function challengeHint(challenge: string): string { if (challenge === 'NEW_PASSWORD_REQUIRED') return 'The password is temporary: the user must choose a new one before getting tokens.' if (challenge.includes('MFA') || challenge === 'SOFTWARE_TOKEN_MFA') return 'The user must enter a second-factor code.' return 'The app has to answer this challenge before Cognito issues tokens.' }