FidoUafAuthState
The new HTTP client shipped with nevisAuth 4.38.0.12 will likely require changes in this auth state configuration, specifically in the area of certificate configuration and handling.
Visit Appendix H for additional information.
Introduction and overview
The FidoUafAuthState
AuthState manages the UAF authentication in a nevisFIDO server.
The section refers to protocol messages defined in the FIDO UAF HTTP Transport Specification.
The UAF authentication process including nevisAuth and the FidoUafAuthState
is as follows:
- The
FidoUafAuthState
sends aGetUAFRequest
to the nevisFIDO server using thefidoUafUsername
attribute. The value of this attribute, that is, the username can be retrieved in different ways:
By authenticating the user through an AuthState configured before the
FidoUafAuthState
. The username value can be a variable expression usingnotes
.The HTTP client provides the FIDO UAF username directly in the incoming request as JSON or FORM parameters. The username value can be a variable expression using
inargs
.In the context of transaction confirmation, the
FidoUafAuthState
can be configured with a list of FIDO UAFtransactions
sent to the nevisFIDO server as part of theGetUAFRequest
. See the FIDO UAF Protocol Specification for more information.
The nevisFIDO server returns a
ReturnUafRequest
to nevisAuth, which forwards this response to the client. If theGetUAFRequest
includes transactions, theReturnUafRequest
also contains these transactions, see Authentication Request Service for more information.The client processes the
ReturnUafRequest
and authenticates the user on the FIDO authenticator. TheReturnUafRequest
contains anAuthenticationRequest
with anOperationHeader
including anExtension
. TheExtension
provides a FIDO UAF session ID, like the one in the following code snippet:{
"id" : "ch.nevis.auth.fido.uaf.sessionId",
"value" : "asdetwdIDsdfsewSAdsds09823423sdfsd9ds"
}The client sends a
SendUafResponse
directly to the nevisFIDO server.The client queries nevisAuth. It depends on the configuration of the
fidoUafSessionId
property in theFidoUafAuthState
whether the client is to provide the property. By default, the client is required to send the property in a POST with a payload like this:{ "fidoUafSessionId" : "asdetwdIDsdfsewSAdsds09823423sdfsd9ds" }
The
FidoUafAuthState
processes the authentication status query, by checking in the nevisFIDO server whether the user is authenticated. If so, theFidoUafAuthState
is set took
. nevisAuth sends a response to the client including a payload like this:{ "status" : "succeeded" }
The client has to send another request to nevisAuth to continue with the authentication process.
To allow chained UAF AuthStates, nevisAuth removes the stored FIDO UAF session ID every time an AuthState transition occurs in the FidoUafAuthState
. As a consequence, the HTTP client receives the authenticated
status only once for a given session ID. The next queries with the same session ID return an unknown
status.
This is to prevent the following undesired situation: suppose a given configuration consists of the two chained UAF AuthStates AuthState1
and AuthState2
. If the user authenticates in AuthState1
, the AuthEngine makes AuthState2the current AuthState. If the client sends an authentication status request with the session ID used in
AuthState1, and the session is not cleaned up, then the user is considered to be authenticated in
AuthState2`.
Restarting the FIDO UAF Authentication
To be able to retrieve the authentication status, nevisAuth requires the FIDO UAF session ID. If the fidoUafSessionId
property is not provided in the nevisAuth configuration, it must be provided as part of the request (using the fidoUafSessionId
JSON attribute).
In any case where a FIDO UAF session ID cannot be associated with the client, the client will initiate an authentication flow, even though an authentication was already triggered. If you configure fidoUafSessionId
in nevisAuth, the client may lose this ability to control redundant authentications.
The main reasons for requiring the session ID are:
Requiring the session ID adds a security layer to what already is provided by nevisAuth and nevisProxy. Stealing the cookie is not enough to hijack the authentication session. An attacker must also have access to the session ID returned in a previous request by nevisAuth. That is, by stealing the cookie, the attacker can prevent the user from being authenticated by restarting the FIDO UAF authentication (see the point below). However, without the session ID the attacker will not be able to authenticate.
Requiring the session ID allows a client application to restart the FIDO UAF authentication at any point in time. This can help to improve the user experience.
By default, sending a request without a FIDO UAF session ID is enough to restart the FIDO UAF authentication. This can be useful in different scenarios, for instance:
- The application requiring authentication is executed in the browser in a laptop whereas the FIDO UAF authentication is done in a mobile device (out-of-band scenario). Suppose the browser polls nevisAuth for the authentication status, but the authentication is still going on after a certain time. Then the application can ask the user to trigger a new FIDO UAF authentication by confirming a message. Note that the browser application could also decide to restart the whole authentication, by removing the nevisAuth cookie. However, this could be annoying for the end user.
- The FIDO UAF client is the one interacting with nevisAuth. The FIDO UAF client detects an error in the interaction with the user. Instead of restarting the entire authentication, the FIDO UAF client can decide to restart only the FIDO UAF authentication.
- An example using this behaviour is described in Authentication Retry / Fallback Example.
Description
The following table and chapters describe the characteristics of the AuthState.
Topic | Description |
---|---|
Class | ch.nevis.auth.fido.uaf.authstate.FidoUafAuthState |
Logging | FidoUaf |
Auditing | none |
Marker | none |
Methods | process |
Properties
fidoUafUsername
(string, optional)Username of the user in the nevisFIDO server.
Examples:
${inargs:username}
${inargs:o.username.v}
: Provides the username in the request parameter username. For instance if the client sends this payload in the HTTP request{ "username" : "jsmith" }
, the username that will be used isjsmith
.
fidoUafServerUrl
(string, required)Base URL of the nevisFIDO server. You cannot use variable expressions to specify this value.
Example:
https://siven.ch:8443/nevisfido
.With this configuration the FIDO UAF AuthState will send the GetUAFRequest to
https://siven.ch:8443/nevisfido/uaf/1.1/request/authentication
.fidoUafSessionId
(string, optional)The session ID required to query nevisFIDO about the status of an ongoing authentication.
Default value:
${inargs:o.fidoUafSessionId.v}
.With the default value, the client is expected to maintain and send the FIDO UAF session ID to nevisAuth using a POST with the following payload:
{ "fidoUafSessionId" : "the_session_ID" }
fidoUafTransactions
(string, optional)The transactions that can be provided to nevisFIDO in the GetUAFRequest. The string represents a JSON array with the transactions as defined in the {uaf-transaction-confirmation-dictionary-spec}.
Example:
{ "contentType": "text/plain", "content": "VGhlIHRyYW5zYWN0aW9uIGNvbmZpcm1hdGlvbiB0ZXh0" }
fidoUafPolicy
(string, optional)Name of the policy to be used for the authentication. If no value is specified the default policy will be used. See policy configuration for more information regarding configuring multiple policies.
This can be used to restrict the authenticators that can be used by the client to authenticate. For example, if the operation is sensible and biometric authentication is considered to be stronger than PIN, here you can specify a policy that only allows biometric authenticators.
httpclient.*
(string)
Configure the outgoing HTTP communication towards nevisFIDO. For a list of valid HTTP properties, see HTTP Client configuration.
Input
fidoUafSessionId
The FidoUafAuthState queries the nevisFIDO server to check whether the session with the provided ID is authenticated. The FIDO UAF session ID can be provided using a POST with the following payload:
{ "fidoUafSessionId" : "the_session_ID" }
infoThis is the equivalent of sending the session ID in the
o.fidoUafSessionId.v
attribute of the inargs.
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).
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
ReturnUafRequest
If the
FidoUafAuthState
generates aGetUAFRequest
, it will forward the response from the nevisFIDO server, aReturnUafRequest
object, to the client. The client must process thisReturnUafRequest
, authenticate the user and eventually send aSendUafResponse
with theAuthenticationResponse
to the nevisFIDO server.Payload with authentication status:
If the
FidoUafAuthState
queried nevisFIDO regarding the authentication status of the session, it will return a JSON object describing the status. Example:{
"status": "succeeded",
"timestamp": "2018-12-14T20:37:48.556Z",
"uafStatusCode": 1200,
"userId": "09890989009",
"authenticators": [
{
"aaid": "ABBA#0001"
}
]
}
Errors
none
Notes
none
Example
The AuthState in the following example integrates FIDO UAF authentication in nevisAuth using the nevisFIDO server located in siven.ch
with port 8443
. The FIDO UAF username is retrieved from the username
parameter of the notes
.
<AuthState name="FidoUafAuthState" class="ch.nevis.auth.fido.uaf.authstate.FidoUafAuthState" resumeState="false">
<ResultCond name="ok" next="AuthDone"/>
<ResultCond name="error" next="AuthError"/>
<ResultCond name="failed" next="AuthError"/>
<property name="fidoUafUsername" value="${sess:username}"/>
<property name="fidoUafServerUrl" value="https://siven.ch:8443/nevisfido"/>
<property name="httpclient.tls.truststoreRef" value="DefaultKeyStore"/>
</AuthState>
The FidoUafAuthState
does not display a GUI. This means that defining GUI elements or setting the property final
to "true" will have no effect.
Request and Response Examples
Request Body Providing Username
It is assumed that the fidoUafUsername
attribute value is ${inargs:o.username.v}
and the transactions
attribute is ${inargs:o.transaction.v}
.
The transactions must be provided as a stringified JSON array.
{
"username": "jeff",
"transaction": "[{\"contentType\":\"text/plain\",\"content\":\"Q29uZmlybSB5b3VyIHB1cmNoYXNlIGZvciBhIHZhbHVlIG9mIENIRjIwMC4\"}]"
}
Response Containing AuthRequest
HTTP/1.1 200 OK
Date: Mon, 25 Jul 2022 11:30:56 GMT
Content-Type: application/fido+uaf;charset=UTF-8
Transfer-Encoding: chunked
Content-Length: 813
{
"lifetimeMillis" : 120000,
"uafRequest" : "[{\"header\":{\"serverData\":\"ervVRaEsmebKoT53bZhWBsOOcq_HhYunZj-3mJExXVBwa1vNhJSvzaVQB7AxvFJk7YcoXw5l6t2Dr-kv7gpvug\",\"upv\":{\"major\":1,\"minor\":1},\"op\":\"Auth\",\"appID\":\"https://www.siven.ch/appID\",\"exts\":[{\"id\":\"ch.nevis.auth.fido.uaf.sessionid\",\"data\":\"0eb8b439-1092-428b-a595-21ea96fe30a0\",\"fail_if_unknown\":false}]},\"challenge\":\"2B7oYIQIh49QDR2P0WCBydh_l_bACgDvfU-jmnXdPn6mWIrseNJOTDEvfy5k5MtsrVu1hrX7o35Rt0y-TMHsWA\",\"policy\":{\"accepted\":[[{\"userVerification\":1023,\"authenticationAlgorithms\":[1,2,3,4,5,6,7,8,9],\"assertionSchemes\":[\"UAFV1TLV\"]}]]},\"transaction\":[{\"contentType\":\"text/plain\",\"content\":\"Q29uZmlybSB5b3VyIHB1cmNoYXNlIGZvciBhIHZhbHVlIG9mIENIRjIwMC4\"}]}]",
"statusCode" : 1200,
"op" : "Auth"
}
Status Request Body
It is assumed that the fidoUafSessionId
attribute value is ${inargs:o.fidoUafSessionId.v}
.
{
"fidoUafSessionId": "1c8a5b00-165c-4a63-ae13-2e03fb7f57ce"
}
Status Response
HTTP/1.1 200 OK
Date: Mon, 04 Feb 2019 12:42:29 GMT
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Content-Length: 415
{
"status" : "succeeded",
"timestamp" : "2019-02-04T12:44:34.980Z",
"uafStatusCode" : 1200,
"asmStatusCode" : 0,
"clientErrorCode" : 0,
"userId" : "123122233",
"authenticators" : [ {
"aaid" : "ABBA#0001"
} ]
}