Authentication flow for "discoverable credential" is different from the general FIDO Authentication flow. The most important difference is that the "username" input parameter for the preauthenticate web service has been made optional
This means that the "username" input param can either be set to NULL or an Empty value or it can be completely removed from the input JSON. All of these three conditions will now trigger a discoverable flow where the challenge will include an empty "allowCredentials" array.
The payload may take the following forms:
"payload": {
"username": null,
"options": {}
}
or
"payload": {
"username": "",
"options": {}
}
or
"payload": {
"options": {}
}
Following is the detailed explanation on how the Authentication works for Discoverable:
The web application sends a preauthenticate request. The "username" input parameter is optional. The "username" input param can either be set to NULL or an empty value or it can be completely removed from the input JSON.
preauthenticate request with username set to empty:
{
"svcinfo": {
"did": 1,
"protocol": "FIDO2_0",
"authtype": "PASSWORD",
"svcusername": "svcfidouser",
"svcpassword": "Abcd1234!"
},
"payload": {
"username": "",
"options": {}
}
}
In response, SKFS returns an empty "allowCredentials" array. This happens because the SKFS does not know the username and therefore must allow for any credential ID to be used.
Usernameless preauthenticate response:
{
"Response": {
"challenge": "nd54MgbnS0RkFZhBgwQtGg",
"allowCredentials": [],
"rpId": "strongkey.com"
},
"responseCode": "FIDO-MSG-0006"
}
The web application will convert the preauthenticate response to a challenge buffer to be used by the browser in a window.navigator.credentials.get call. Once the authenticator has returned a response to the web application, the web application calls the authenticate webservice:
authenticate request:
{
"svcinfo": {
"did": 1,
"protocol": "FIDO2_0",
"authtype": "PASSWORD",
"svcusername": "svcfidouser",
"svcpassword": "Abcd1234!"
},
"payload": {
"publicKeyCredential": {
"id": "ICg6T0HYY9lJekClKWL7inmT5OrWrabxRjHhzOLcJ456cpzWaVgk_9D0GJZCOmyq",
"rawId": "ICg6T0HYY9lJekClKWL7inmT5OrWrabxRjHhzOLcJ456cpzWaVgk_9D0GJZCOmyq",
"response": {
"authenticatorData": "WnTBrV2dI2nYtpWAzOrzVHMkwfEC46dxHD4U1RP9KKMFAAAACw",
"signature": "MEUCIBHnIq3odQlNctwbk_XxLkxIclbUQlyBuHTmjL0E5ScLAiEAgizvFG55Nz-Yb47JkJXGuxOEqgRLKVDwxUhtrF1bJIY",
"userHandle": "Gz0xMbW7QnQuLsHM9T0InFprZNWViumado5tikOX94c",
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiJuZDU0TWdiblMwUmtGWmhCZ3dRdEdnIiwib3JpZ2luIjoiaHR0cHM6Ly9kZW1vLnN0cm9uZ2tleS5jb206ODE4MSIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ=="
},
"type": "public-key"
},
"strongkeyMetadata": {
"version": "1.0",
"last_used_location": "Sunnyvale,CA",
"username": "",
"origin": "https://demo.strongkey.com:8181"
}
}
}
Even though the preauthenticate flow begins with the null or an empty username, SKFS returns a username after a successful authentication. As a result, the web application learns the username who authenticated with FIDO.
{ "Response":"Successfully processed sign response", "responseCode": "FIDO-MSG-0008", "username": "testuser", "jwt":"" }
For more information, check out the SKFS API for the preauthenticate and authenticate web services: