{
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"maxLength": 254
},
"challenge": {
"type": "string",
"enum": [
"NEW_PASSWORD_REQUIRED",
"MFA_SETUP",
"SOFTWARE_TOKEN_MFA"
]
},
"session": {
"type": "string",
"minLength": 20,
"maxLength": 4096
},
"username": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"answers": {
"type": "object",
"properties": {
"newPassword": {
"type": "string",
"minLength": 12,
"maxLength": 256
},
"code": {
"type": "string",
"pattern": "^\\d{6}$"
}
},
"required": []
}
},
"required": [
"email",
"challenge",
"session",
"username",
"answers"
]
}{error:{code,message}} for CloudError failures, attaches Request-Id, and disables caching. Handle 401 by signing in; show role refusal for 403 forbidden, reauthenticate only for step_up_required, and collect a reason for 400 reason_required. A CSRF failure needs a current page/session token, not blind retries. Operation-specific 404/409/413/422/502/503 errors retain their status. Honor Retry-After on 429./**
* POST /api/admin/auth/challenge {email, challenge, session, username, answers}: answers NEW_PASSWORD_REQUIRED
* ({newPassword}), MFA_SETUP ({code} from the newly enrolled authenticator) or SOFTWARE_TOKEN_MFA ({code}).
*/
export const POST = authRoute(async (request, { requestId }) => {
if (!staffConfigured()) throw new CloudError(503, "not_configured", "Staff sign-in isn't configured yet (ADMIN_USER_POOL_ID).");
const input = await readBody(request, challengeSchema);
await limitLogin(request, input.email);
const step = await respond({ challenge: input.challenge, session: input.session, username: input.username, email: input.email, ...input.answers }).catch((error) => {
throw staffAuthFailure(error, "challenge");
});
return stepResponse(step, request, requestId, input.challenge);
});