Fido2AuthState
Introduction and overview
The Fido2AuthState
AuthState manages the FIDO2 authentication in a nevisFIDO server.
The section refers to protocol messages defined in the FIDO2: Conformance testing server API.
Input Activity
Depending on the received inputs, the Fido2AuthState
may behave differently, as also illustrated on the activity diagram below. The following list of configuration properties heavily influence these behaviors. In order of priority:
clientResult
: if this configuration property resolves into a non-empty value (and is also an allowed client result), everything else is ignored, and the AuthState sets the received client result.fido2SessionIdInHeader
: if the header referenced by this property is received (and noclientResult
is received),Fido2AuthState
will try to contact nevisFIDO to verify the success of an authentication ceremony. Only set this if the ceremony has succeeded at nevisFIDO.fido2Username
: if this configuration property resolves into a non-null value (and none of the above properties resolved), theFido2AuthState
will initiate the authentication ceremony at nevisFIDO.
A common pitfall to configure fido2Username
into a value that is resolved immediately, before a GUI would be rendered and the client-side Javascript could be loaded. For example, consider the following: fido2Username
is configured with the value ${notes:loginId}
and the AuthState that preceeds the Fido2AuthState
already sets loginId
into the notes
. This means, the moment Fido2AuthState
starts processing, instead of asking to render a GUI, it will initiate the authentication at nevisFIDO, which means the client-side Javascript is completely out of the loop, even if it loads at all - no authentication can happen in the browser. As such, it is recommended to keep fido2Username
at default value ${inargs:o.username.v}
, which means the AuthState will wait for the client to send the username in an HTTP POST request's body, keeping the client in the FIDO2 ceremony.
Authentication flow
The FIDO2 authentication process including nevisAuth and the Fido2AuthState
is as follows:
A GUI is rendered and client-side Javascript is loaded that is capable of handling the FIDO2 protocol in the browser.
The client-side Javascript sends an HTTP POST with a JSON payload containing user information. (Example:
{"username": "charlesdexterward"}
)The
Fido2AuthState
retreives the username with thefido2Username
configuration property from the incoming request and then sends aServerPublicKeyCredentialGetOptionsRequest
to the nevisFIDO server with it. The value of this attribute can be retrieved in various ways (theoretically, even without a GUI), but it is recommended that the HTTP client provides the FIDO2 username directly in the incoming request as JSON or FORM parameters. The username value can be a variable expression usinginargs
in this case, such as the default of this property, which is${inargs:o.username.v}
.The nevisFIDO server returns a
ServerPublicKeyCredentialGetOptionsResponse
to nevisAuth, which it forwards to the client. Thefido2SessionId
is in this request, which nevisAuth stores in the session for later.The client processes the
ServerPublicKeyCredentialGetOptionsResponse
and authenticates the user on the FIDO2 authenticator. As mentioned above, theServerPublicKeyCredentialGetOptionsResponse
contains a FIDO2 session ID, which the client must store. Example session ID in theServerPublicKeyCredentialGetOptionsResponse
:{
"fido2SessionId": "asdetwdIDsdfsewSAdsds09823423sdfsd9ds"
}The client sends a
ServerPublicKeyCredential
directly to the nevisFIDO server.The client queries nevisAuth. It depends on the configuration of the
fido2SessionIdInHeader
property in theFido2AuthState
what header the client is to provide the value in. By default, the client is required to send the property in an HTTP header like this:"nevis-fido2-session-id" : "asdetwdIDsdfsewSAdsds09823423sdfsd9ds"
The
Fido2AuthState
compares the receivedfido2SessionId
with the one stored in the session. On a match the AuthState will query the status service of nevisFIDO to verify whether the user is successfully authenticated. If so, theFido2AuthState
sets the result condition took
, which triggers a transition in the AuthStates to whatever follows theFido2AuthState
.
Description
The following table and chapters describe the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.auth.fido.fido2.authstate.Fido2AuthState |
Logging | Fido2 |
Auditing | none |
Marker | none |
Methods | process |
Properties
fido2Username
(string, optional)Username of the user in the nevisFIDO server.
Default value:
${inargs:o.username.v}
This means, it is expected that the client-side Javascript posts the username to nevisAuth with a JSON payload. Example:
{ "username" : "username_of_the_user" }
Once this configuration entry is resolved into a non-null value, the FIDO2 authentication ceremony is started at the FIDO2 server, nevisFIDO.
fido2UserVerification
(string, optional)Will be incorporated into the FIDO2 options that is delivered to the browser. This property signals whether the user is to be verified or not by the FIDO2 authenticator / browser. See also UserVerificationRequirement
Default value: ${inargs:o.userVerification.v} Allowed static values:
required
,preferred
,discouraged
.The default value means, it is expected that the client-side Javascript posts the
userVerification
to nevisAuth with a JSON payload. Example:{ "userVerification" : "required" }
It is recommended to specify a static value that represents the desired business. If a null or empty value is provided, the default
preferred
will take effect in nevisFIDO.fido2ServerUrl
(string, required)Base URL of the nevisFIDO server with the path prefix of the component. You cannot use variable expressions to specify this value.
Example:
https://siven.ch:8443/nevisfido
.With this configuration the FIDO2 AuthState will send the ServerPublicKeyCredentialGetOptionsRequest to
https://siven.ch:8443/nevisfido/fido2/attestation/options
.fido2SessionIdHeader
(string, optional)The name of the header the session ID is provided in by the client. The value is used to query the status service of nevisFIDO regarding ongoing authentication ceremonies. If header is provided, it is assumed the authentication ceremony has already been initiated.
Default value:
nevis-fido2-session-id
.With the default value, the client is expected to send an HTTP request with the header:
"nevis-fido2-session-id" : "the_session_ID"
userExtId
(string, optional)The nevisIDM
extId
of the user. If resolved to a non-empty value, theFido2AuthState
will verify that theextId
it received from nevisFIDO matches the resolved value. It is recommended to configure this property for stepup scenarios, where the user data is already loaded into the session. Usually the nevisIDM user is loaded into the session for these scenarios, which means this property will automatically take effect with its default value seen below.Default value:
${sess:ch.adnovum.nevisidm.user.extId}
.clientResult
(string, optional)The
Fido2AuthState
makes it possible for the client to influence the flow with results resolved in this property - if any valid result is resolved, it takes precedence over other actions of theFido2AuthState
, so only provide this in case it is certain the FIDO2 ceremony cannot continue.Default value:
${inargs:clientResult}
With the default value, the client is expected to send an HTTP form with the
clientResult
content set. Example:"clientResult"="cancelled"
Allowed results:
cancelled
: we recommend to send this in case the user cancels the ceremony explicitly.notSupported
: we recommend to send this in case the client-side detects the client's lack of support for FIDO2.
httpclient.*
(String)Configure the outgoing HTTP communication towards nevisFIDO. For a list of valid HTTP properties, see HTTP Client configuration.
Input
fido2SessionIdHeader
The
Fido2AuthState
queries the nevisFIDO server to check whether the session with the provided ID is authenticated. The FIDO2 session ID can be provided using a header in an HTTP request:"nevis-fido2-session-id" : "the_session_ID"
Transitions
error
If an error occurred in the communication with nevisFIDO.
failed
If nevisFIDO reports a failed authentication (in response to the client’s query for the authentication status).
cancelled
Only happens if signalled explicitly to theFido2AuthState
with theclientResult
property. It is recommended to use this for explicit cancellations requested by the user on the client-side.notSupported
Only happens if signalled explicitly to theFido2AuthState
with theclientResult
property. It is recommended to use this for the case when the client-side code detects that the client does not support FIDO2.ok
If nevisAuth detects a successfully authenticated user in nevisFIDO. In this case, nevisFIDO responses positively to the client’s query for the authentication status.
Output
ServerPublicKeyCredentialGetOptionsResponse
If the
Fido2AuthState
generates aServerPublicKeyCredentialGetOptionsRequest
, it will forward the response from the nevisFIDO server, aServerPublicKeyCredentialGetOptionsResponse
object, to the client. The client must process thisServerPublicKeyCredentialGetOptionsResponse
, authenticate the user and eventually send aServerPublicKeyCredential
directly to the nevisFIDO server.Payload with authentication status:
If the
Fido2AuthState
queried nevisFIDO regarding the authentication status of the session, it will return a JSON object describing the status. Example:{
"challenge": "6283u0svT-YIF3pSolzkQHStwkJCaLKx",
"timeout": 20000,
"rpId": "nevis.net",
"allowCredentials": [
{
"id": "m7xl_TkTcCe0WcXI2M-4ro9vJAuwcj4m",
"type": "public-key"
}
],
"userVerification": "required",
"fido2SessionId": "asdetwdIDsdfsewSAdsds09823423sdfsd9ds"
}
Errors
none
Notes
none
Example
The AuthState in the following example integrates FIDO2 authentication in nevisAuth using the nevisFIDO server located in siven.ch
with port 8443
. The FIDO2 username is retrieved from the incoming JSON {"username": "the_username"}
the client must send from the rendered GUI.
<AuthState name="Fido2Authentication" class="ch.nevis.auth.fido.fido2.authstate.Fido2AuthState" final="true" resumeState="true"
classPath="/opt/nevisfidocl/nevisauth/lib">
<ResultCond name="ok" next="AuthDone"/>
<ResultCond name="failed" next="AuthError"/>
<ResultCond name="error" next="AuthError"/>
<ResultCond name="cancelled" next="AuthError"/>
<ResultCond name="notSupported" next="AuthError"/>
<Response value="AUTH_CONTINUE">
<Gui name="fido2dialog" label="FIDO2 Dialog" target="">
<GuiElem name="lasterror" type="error" label="${notes:lasterrorinfo}" value="${notes:lasterror}"/>
<GuiElem name="username" optional="true" type="text" label="Username" />
<GuiElem name="displayName" optional="true" type="text" label="Display Name" />
<GuiElem name="btnFido2Authentication" type="button" label="Authentication" />
<GuiElem name="btnFido2Cancel" type="button" label="Cancel" />
</Gui>
</Response>
<property name="fido2SessionIdHeader" value="nevis-fido2-session-id"/>
<property name="fido2UserName" value="${inargs:o.username.v}"/>
<property name="fido2ServerUrl" value="https://siven.ch.8443/nevisfido"/>
<property name="httpclient.tls.trustStoreRef" value="TrustStoreForNevisFido"/>
<property name="httpclient.tls.keyObjectRef" value="DefaultSigner" />
</AuthState>
Request and Response Examples
Request Body Providing Username
It is assumed that the fido2Username
attribute value is ${inargs:o.username.v}
and the transactions
attribute is ${inargs:o.transaction.v}
.
{
"username": "charlesdexterward",
}
Response
HTTP/1.1 200 OK
Date: Mon, 25 Jul 2022 11:31:19 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Content-Length: 375
{
"status" : "ok",
"errorMessage" : "",
"fido2SessionId" : "673c1466-2fb8-43fe-8898-a94a06d1793c",
"challenge" : "bs1rWtPCQrmEDrBGAfjcKg",
"timeout" : 300000,
"rpId" : "siven.ch",
"allowCredentials" : [ {
"type" : "public-key",
"id" : "Y3JlZGVudGlhbElk",
"transports" : [ "usb", "internal", "ble", "nfc" ]
} ],
"userVerification" : "preferred"
}
Status Request Body
It is assumed that the fido2SessionIdHeader
attribute value is nevis-fido2-session-id
.
"fido2SessionIdHeader": "1c8a5b00-165c-4a63-ae13-2e03fb7f57ce"
Status Response
HTTP/1.1 200 OK
Date: Mon, 25 Jul 2022 11:31:19 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Content-Length: 187
{
"status" : "succeeded",
"fido2SessionId" : "7fea6065-17fd-47d4-a5b0-85f513687c8d",
"timestamp" : "2022-07-25T11:31:18.987Z",
"username" : "Jeff ",
"userId" : "[email protected]"
}