FIDO registration - REST flow example

Requirements

Component

Requirement

Comments

Airlock IAM

  • Airlock IAM 7.3 or newer.
  • An Airlock 2FA subscription is required.
  • The IAM bundle Enhanced Authentication must be licensed.

For licensing:
Contact order@airlock.com.

Intended solution environment

The following example illustrates how a FIDO-related self-service is configured and used over the REST API.

It covers the following use-case:

  • A logged-in user may register a FIDO authenticator.

Goal

  • Understand how the FIDO self-service works in general.
  • Understand how the FIDO self-service is configured.
  • Learn how to use the Loginapp REST API with respect to the configured self-service.

All following procedures are exemplary and will vary according to your setup or needs.

Prerequisites

  • An end-user account exists in IAM and end-users can be authenticated (e.g. username, password, and a 2nd factor).
  • The end-user has a supported FIDO authenticator.
  • The FIDO authenticator complies with the settings in the FIDO configuration.
  • The end-users browser or mobile app supports FIDO.
  • The FIDO authenticator has not yet been registered with the end-users account.
  • The Loginapp REST API is configured and ready to use.
  • At least one Login REST authentication flow is configured.
  • The end-user has been authenticated using a REST authentication flow.
  • The end-user is authorized to register FIDO authenticators (i.e. the FIDO registration flow's configured authorization condition is fulfilled).
  • The FIDO Settings (basic settings) are configured. Especially, the configured relying party ID matches the browser domain when accessing the Loginapp.

Configuration

  1. Go to:
    Loginapp >> Protected Self-Services >> Protected Self-Service Flows.
  2. Add a flow plugin Self-Service Flow with flow ID fido-registration.
  3. Add the plugin FIDO Registration Step to the flow and in it connect the FIDO Settings.
  4. If required, set an appropriate Access Condition and an appropriate Authorization Condition.

Step 1: Select the FIDO registration flow

Before starting a flow, it's generally a good idea to end possibly ongoing other flows of the same type to avoid getting a UNEXPECTED_CALL response. To do so, we use the following request in our example:

DELETE /rest/protected/self-service/flow

To start the protected self-service flow with flow ID fido-registration, use:

POST /rest/protected/self-service/flows/fido-registration/select

The response tells the REST client, that a FIDO challenge must be retrieved:

HTTP/1.1 200 OK

{
   "meta":{
      "type":"jsonapi.metadata.document",
      "timestamp":"2021-02-16T11:46:07.806+01:00"
   },
   "data":{
      "type":"self-service.session",
      "id":"150932765365474699",
      "attributes":{
         "nextStep":"FIDO_REGISTRATION_CHALLENGE_RETRIEVAL_REQUIRED"
      }
   }
}

Step 2: Get FIDO challenge and set an authenticator display name

Getting the FIDO registration challenge also sets the display name for the FIDO authenticator. The display name later helps the end-user (or the helpdesk) to identify the authenticator. Identification is especially important if a user registers multiple authenticators:

POST /rest/protected/self-service/fido/registration/challenge/retrieve

{displayName: "my usb stick"}	
   

The response bears the FIDO challenge and information about the requirements imposed on the FIDO authenticator to be registered:

HTTP/1.1 200 OK

{
   "meta":{
      "type":"jsonapi.metadata.document",
      "timestamp":"2021-02-16T11:47:06.121+01:00"
   },
   "data":{
      "type":"self-service.fido.registration.challenge",
      "id":"2853364706",
      "attributes":{
         "publicKeyCredentialCreationOptions":{
            "rp":{
               "name":"localhost",
               "id":"localhost"
            },
            "user":{
               "name":"-",
               "id":"zBcyYsonWQgxZ9NbeZz9n_N0G6Pu5DaF_D3E",
               "displayName":"my usb stick"
            },
            "challenge":"XoL13o_ad3IZLQBm…oZg",
            "pubKeyCredParams":[
               {
                  "type":"public-key",
                  "alg":-7
               },
               {
                  "type":"public-key",
                  "alg":-8
               }
            ],
            "timeout":60000,
            "excludeCredentials":[
               {
                  "type":"public-key",
                  "id":"AbXIsHnKwe9RfhLY…54g"
               }
            ],
            "authenticatorSelection":{
               "requireResidentKey":false,
               "userVerification":"preferred"
            },
            "attestation":"direct"
         }
      }
   }
}

Step 4: Send response to FIDO challenge

The FIDO client (browser or mobile app) now interacts with the end-user and asks to provide and activate the FIDO authenticator (e.g. connect USB stick and touch it).

  • If multiple FIDO Authenticators are available, the end-user must select one.
  • The above example challenge contains an excludeCredentials statement: it lists FIDO Authenticators that must not be selected (because already registered for this user account).
  • The FIDO client rejects FIDO authenticators not meeting the requirements in the challenge.

Once the FIDO Authenticator is selected and the end-user has granted permission to the FIDO client to use it, the challenge is signed and the response send back:

POST /rest/protected/self-service/fido/registration/attestation-response/check


{
   "publicKeyCredential":{
      "id":"hP_z3dA-1HapqU38nS3Xt5y…XSA",
      "response":{
         "attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc…aOX",
         "clientDataJSON":"{\"type\":\"webauthn.create\",\"challenge\":\"6BpohYAw1jN_xidTwda79HlXnYzo6ez4CFCP_1_gpt4\",\"origin\":\"https://localhost:8443\",\"crossOrigin\":false}"
      },
      "type":"public-key"
   }
}   

The response is checked by Airlock IAM and information about the FIDO authenticator extracted from the attestation object. If the registration was successful, the usual success response is sent back and the registration has succeeded.

HTTP/1.1 200 OK

{
   "meta":{
      "type":"jsonapi.metadata.document",
      "timestamp":"2021-02-16T11:48:29.504+01:00"
   },
   "data":{
      "type":"self-service.session",
      "id":"150932765365474699",
      "attributes":{
         
      }
   }
}