Finish sign-in with a passkey
curl --request POST \
--url https://my.server.express/api/v1/auth/2fa/verify \
--header 'Content-Type: application/json' \
--data '
{
"preAuthToken": "<string>",
"response": {
"id": "<string>",
"rawId": "<string>",
"type": "public-key",
"response": {
"clientDataJSON": "<string>",
"authenticatorData": "<string>",
"signature": "<string>",
"userHandle": "<string>"
},
"clientExtensionResults": {}
}
}
'const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
preAuthToken: '<string>',
response: {
id: '<string>',
rawId: '<string>',
type: 'public-key',
response: {
clientDataJSON: '<string>',
authenticatorData: '<string>',
signature: '<string>',
userHandle: '<string>'
},
clientExtensionResults: {}
}
})
};
fetch('https://my.server.express/api/v1/auth/2fa/verify', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://my.server.express/api/v1/auth/2fa/verify"
payload = {
"preAuthToken": "<string>",
"response": {
"id": "<string>",
"rawId": "<string>",
"type": "public-key",
"response": {
"clientDataJSON": "<string>",
"authenticatorData": "<string>",
"signature": "<string>",
"userHandle": "<string>"
},
"clientExtensionResults": {}
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"accessToken": "<string>",
"refreshToken": "<string>",
"user": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "[email protected]",
"firstName": "<string>",
"lastName": "<string>",
"role": "CLIENT"
}
}
}{
"success": false,
"error": "<string>"
}{
"success": false,
"error": "<string>"
}{
"success": false,
"error": "<string>"
}Auth
Finish sign-in with a passkey
Second half of the passkey second factor. Verifies the WebAuthn assertion against the challenge from /v1/auth/2fa/options (single use), bumps the passkey’s counter and issues the session. A failed ceremony is 403, not 401. An expired pre-auth token, a missing challenge or a passkey that isn’t on this account is 400. Not rate-limited. Writes a LOGIN_2FA audit entry.
POST
/
v1
/
auth
/
2fa
/
verify
Finish sign-in with a passkey
curl --request POST \
--url https://my.server.express/api/v1/auth/2fa/verify \
--header 'Content-Type: application/json' \
--data '
{
"preAuthToken": "<string>",
"response": {
"id": "<string>",
"rawId": "<string>",
"type": "public-key",
"response": {
"clientDataJSON": "<string>",
"authenticatorData": "<string>",
"signature": "<string>",
"userHandle": "<string>"
},
"clientExtensionResults": {}
}
}
'const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
preAuthToken: '<string>',
response: {
id: '<string>',
rawId: '<string>',
type: 'public-key',
response: {
clientDataJSON: '<string>',
authenticatorData: '<string>',
signature: '<string>',
userHandle: '<string>'
},
clientExtensionResults: {}
}
})
};
fetch('https://my.server.express/api/v1/auth/2fa/verify', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://my.server.express/api/v1/auth/2fa/verify"
payload = {
"preAuthToken": "<string>",
"response": {
"id": "<string>",
"rawId": "<string>",
"type": "public-key",
"response": {
"clientDataJSON": "<string>",
"authenticatorData": "<string>",
"signature": "<string>",
"userHandle": "<string>"
},
"clientExtensionResults": {}
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"accessToken": "<string>",
"refreshToken": "<string>",
"user": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"email": "[email protected]",
"firstName": "<string>",
"lastName": "<string>",
"role": "CLIENT"
}
}
}{
"success": false,
"error": "<string>"
}{
"success": false,
"error": "<string>"
}{
"success": false,
"error": "<string>"
}