Skip to main content
Version: 2.4.x.x Java 8 ELS

Fido2AuthState

Introduction and overview

The Fido2AuthState AuthState manages the FIDO2 authentication in a nevisFIDO server.

info

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:

  1. 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.
  2. fido2SessionIdInHeader: if the header referenced by this property is received (and no clientResult 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.
  3. fido2Username: if this configuration property resolves into a non-null value (and none of the above properties resolved), the Fido2AuthState will initiate the authentication ceremony at nevisFIDO.
danger

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.

title="Input activity of Fido2AuthState"

Authentication flow

The FIDO2 authentication process including nevisAuth and the Fido2AuthState is as follows:

  1. A GUI is rendered and client-side Javascript is loaded that is capable of handling the FIDO2 protocol in the browser.

  2. The client-side Javascript sends an HTTP POST with a JSON payload containing user information. (Example: {"username": "charlesdexterward"})

  3. The Fido2AuthState retreives the username with the fido2Username configuration property from the incoming request and then sends a ServerPublicKeyCredentialGetOptionsRequest 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 using inargs in this case, such as the default of this property, which is ${inargs:o.username.v}.

  4. The nevisFIDO server returns a ServerPublicKeyCredentialGetOptionsResponse to nevisAuth, which it forwards to the client. The fido2SessionId is in this request, which nevisAuth stores in the session for later.

  5. The client processes the ServerPublicKeyCredentialGetOptionsResponse and authenticates the user on the FIDO2 authenticator. As mentioned above, the ServerPublicKeyCredentialGetOptionsResponse contains a FIDO2 session ID, which the client must store. Example session ID in the ServerPublicKeyCredentialGetOptionsResponse:

     {
    "fido2SessionId": "asdetwdIDsdfsewSAdsds09823423sdfsd9ds"
    }
  6. The client sends a ServerPublicKeyCredential directly to the nevisFIDO server.

  7. The client queries nevisAuth. It depends on the configuration of the fido2SessionIdInHeader property in the Fido2AuthState 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"
  8. The Fido2AuthState compares the received fido2SessionId 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, the Fido2AuthState sets the result condition to ok, which triggers a transition in the AuthStates to whatever follows the Fido2AuthState.

title="Fido2AuthState example flow"

Description

The following table and chapters describe the characteristics of the AuthState.

TopicDescription
Classch.nevis.auth.fido.fido2.authstate.Fido2AuthState
LoggingFido2
Auditingnone
Markernone
Methodsprocess

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, the Fido2AuthState will verify that the extId 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 the Fido2AuthState, 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 the Fido2AuthState with the clientResult 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 the Fido2AuthState with the clientResult 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 a ServerPublicKeyCredentialGetOptionsRequest, it will forward the response from the nevisFIDO server, a ServerPublicKeyCredentialGetOptionsResponse object, to the client. The client must process this ServerPublicKeyCredentialGetOptionsResponse, authenticate the user and eventually send a ServerPublicKeyCredential 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]"
}