Overview
Diagrams
<webauthn-spring-boot-starter>
supports multiple flows
-
Authentication
-
Registration of a new user
-
Registration of a new device
-
Account recovery
Resources
Register new user
Registration start
A POST
request is used to start the Add User ceremony
Request structure
POST /registration/start HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 72
Host: localhost:8080
{"username":"newjunit","registrationAddToken":null,"recoveryToken":null}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 648
{"status":"OK","registrationId":"Ey6LyiaXLwgM8wxeNIXnKQ==","publicKeyCredentialCreationOptions":{"rp":{"name":"localhost","id":"localhost","icon":{"empty":false,"present":true}},"user":{"name":"newjunit","displayName":"newjunit","id":"AAAAAAAAAAM","icon":{"empty":true,"present":false}},"challenge":"hZV-7roGRNnDzytShOxyDAvVTAHQTcVamfr2TYmDJZg","pubKeyCredParams":[{"alg":-7,"type":"public-key"},{"alg":-8,"type":"public-key"},{"alg":-257,"type":"public-key"}],"timeout":{"empty":true,"present":false},"excludeCredentials":{"empty":false,"present":true},"authenticatorSelection":{"empty":true,"present":false},"attestation":"none","extensions":{}}}
CURL request
$ curl 'http://localhost:8080/registration/start' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{"username":"newjunit","registrationAddToken":null,"recoveryToken":null}'
Register new user
Registration start
A POST
request is used to start the Add User ceremony
Request structure
POST /registration/start HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 72
Host: localhost:8080
{"username":"newjunit","registrationAddToken":null,"recoveryToken":null}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 648
{"status":"OK","registrationId":"Ey6LyiaXLwgM8wxeNIXnKQ==","publicKeyCredentialCreationOptions":{"rp":{"name":"localhost","id":"localhost","icon":{"empty":false,"present":true}},"user":{"name":"newjunit","displayName":"newjunit","id":"AAAAAAAAAAM","icon":{"empty":true,"present":false}},"challenge":"hZV-7roGRNnDzytShOxyDAvVTAHQTcVamfr2TYmDJZg","pubKeyCredParams":[{"alg":-7,"type":"public-key"},{"alg":-8,"type":"public-key"},{"alg":-257,"type":"public-key"}],"timeout":{"empty":true,"present":false},"excludeCredentials":{"empty":false,"present":true},"authenticatorSelection":{"empty":true,"present":false},"attestation":"none","extensions":{}}}
CURL request
$ curl 'http://localhost:8080/registration/start' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{"username":"newjunit","registrationAddToken":null,"recoveryToken":null}'
Registration finish
A POST
request is used to fnish the Add User ceremony
Request structure
POST /registration/finish HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 855
Host: localhost:8080
{
"registrationId": "KukKik86leDlveDwJvGZVA==",
"credential": {
"type": "public-key",
"id": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"rawId": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoidTZvVFJqSDlpdk5HVnRORGRKZ2VTYWItWHNibEt6TGw1VHRKaTJaUmpCOCIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVi4SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFYQFsmK3OAAI1vMYKZIsLJfHwVQMANAEYMch38OTfN4ETJdjO7x4apEJrR8AyfEAnIjOLlpchor6U39NG_EyL8ugRKQQGVQgPSeelAQIDJiABIVggRrK9x1qVGusI8SJ2mhhtl0eY2wN4jJgGhUnoefCZSrgiWCBXhX1M2HIdIZDENOvj5NRZY_rR51ylCXJuvA6UivFpxQ"
},
"clientExtensionResults": {}
}
}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 44
{"recoveryToken":"l7NBeKAM1R4MwGlTIpA+Lg=="}
CURL request
$ curl 'http://localhost:8080/registration/finish' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{
"registrationId": "KukKik86leDlveDwJvGZVA==",
"credential": {
"type": "public-key",
"id": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"rawId": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoidTZvVFJqSDlpdk5HVnRORGRKZ2VTYWItWHNibEt6TGw1VHRKaTJaUmpCOCIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVi4SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NFYQFsmK3OAAI1vMYKZIsLJfHwVQMANAEYMch38OTfN4ETJdjO7x4apEJrR8AyfEAnIjOLlpchor6U39NG_EyL8ugRKQQGVQgPSeelAQIDJiABIVggRrK9x1qVGusI8SJ2mhhtl0eY2wN4jJgGhUnoefCZSrgiWCBXhX1M2HIdIZDENOvj5NRZY_rR51ylCXJuvA6UivFpxQ"
},
"clientExtensionResults": {}
}
}'
Authentication
Authentication start
A POST
request is used to start the authentication ceremony
Request structure
POST /assertion/start HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 22
Host: localhost:8080
{ "username": "junit"}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 333
{"assertionId":"FTE9ue5Wvl+IcN2eON+i5A==","publicKeyCredentialRequestOptions":{"challenge":"TBYbGa9fGTv03Ad29-T8ETEfnKRmNeSFcq1hz1qYRyU","timeout":{"empty":true,"present":false},"rpId":"localhost","allowCredentials":{"empty":false,"present":true},"userVerification":"preferred","extensions":{"appid":{"empty":true,"present":false}}}}
CURL request
$ curl 'http://localhost:8080/assertion/start' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{ "username": "junit"}'
Authentication finish
A POST
request is used to finish the authentication ceremony
Request structure
POST /assertion/finish HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 766
Host: localhost:8080
{
"assertionId": "bWnC7+6A/fUcwjl048iPOQ==",
"credential": {
"type": "public-key",
"id": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"rawId": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVWVCWWtKdTRjdk5xeDZGRmk0cVNJTDhLSURveDBwcXlNUzlXNmJBYlRIOCIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFYQFsow",
"signature": "MEUCIFnff70nAto5eJTwyVHYgoi_E3013MOnbUVHJWIfaWbWAiEA9tw1WfZjTl1LOx3JF4-HQVPDhvVNVpRMXmtR2BN3m9I",
"userHandle": "AAAAAAAAAAE"
},
"clientExtensionResults": {}
}
}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 20
{"username":"junit"}
CURL request
$ curl 'http://localhost:8080/assertion/finish' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{
"assertionId": "bWnC7+6A/fUcwjl048iPOQ==",
"credential": {
"type": "public-key",
"id": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"rawId": "ARgxyHfw5N83gRMl2M7vHhqkQmtHwDJ8QCciM4uWlyGivpTf00b8TIvy6BEpBAZVCA9J5w",
"response": {
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVWVCWWtKdTRjdk5xeDZGRmk0cVNJTDhLSURveDBwcXlNUzlXNmJBYlRIOCIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MCIsImNyb3NzT3JpZ2luIjpmYWxzZX0",
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFYQFsow",
"signature": "MEUCIFnff70nAto5eJTwyVHYgoi_E3013MOnbUVHJWIfaWbWAiEA9tw1WfZjTl1LOx3JF4-HQVPDhvVNVpRMXmtR2BN3m9I",
"userHandle": "AAAAAAAAAAE"
},
"clientExtensionResults": {}
}
}
'
Recovery
Recovery start
A POST
request is used to start the recovery ceremony
Request structure
POST /registration/start HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 76
Host: localhost:8080
{"username":null,"registrationAddToken":null,"recoveryToken":"dG9rZW4tMTIz"}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 642
{"status":"OK","registrationId":"W08vAOAX8iaiL4SLGN7RYg==","publicKeyCredentialCreationOptions":{"rp":{"name":"localhost","id":"localhost","icon":{"empty":false,"present":true}},"user":{"name":"junit","displayName":"junit","id":"AAAAAAAAAAE","icon":{"empty":true,"present":false}},"challenge":"mHGwnrzee8oNypfwV-EYqQ-UWkYrAes4W3RdH2bFjsQ","pubKeyCredParams":[{"alg":-7,"type":"public-key"},{"alg":-8,"type":"public-key"},{"alg":-257,"type":"public-key"}],"timeout":{"empty":true,"present":false},"excludeCredentials":{"empty":false,"present":true},"authenticatorSelection":{"empty":true,"present":false},"attestation":"none","extensions":{}}}
CURL request
$ curl 'http://localhost:8080/registration/start' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{"username":null,"registrationAddToken":null,"recoveryToken":"dG9rZW4tMTIz"}'
Add device
Generate registrationAddToken
A POST
request is used to start the add device ceremony. For a given authenticated user,
a new registration add token is created and valid for 10 minutes
Request structure
GET /registration/add HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Host: localhost:8080
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 51
{"registrationAddToken":"N/1N94jlP6KuIyTFAkdN8Q=="}
CURL request
$ curl 'http://localhost:8080/registration/add' -i -X GET \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json'
Add device
On another device, a POST
request is used to finish the add device ceremony.
Given the registrationAddToken
is valid, the new credentials are linked to the existing user.
Request structure
POST /registration/start HTTP/1.1
Content-Type: application/json;charset=UTF-8
Accept: application/json
Content-Length: 76
Host: localhost:8080
{"username":null,"registrationAddToken":"dG9rZW4tMTIz","recoveryToken":null}
Example response
HTTP/1.1 200 OK
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 642
{"status":"OK","registrationId":"t07B2lBX1voht8Gc9BdrBw==","publicKeyCredentialCreationOptions":{"rp":{"name":"localhost","id":"localhost","icon":{"empty":false,"present":true}},"user":{"name":"junit","displayName":"junit","id":"AAAAAAAAAAI","icon":{"empty":true,"present":false}},"challenge":"KY8E1H8YZfb954upHyD1uYB__S9xCj8N6HF0IGI9mBM","pubKeyCredParams":[{"alg":-7,"type":"public-key"},{"alg":-8,"type":"public-key"},{"alg":-257,"type":"public-key"}],"timeout":{"empty":true,"present":false},"excludeCredentials":{"empty":false,"present":true},"authenticatorSelection":{"empty":true,"present":false},"attestation":"none","extensions":{}}}
CURL request
$ curl 'http://localhost:8080/registration/start' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Accept: application/json' \
-d '{"username":null,"registrationAddToken":"dG9rZW4tMTIz","recoveryToken":null}'