Skip to main content
Version: 8.2405.x.x RR

Configuration

This section describes the required nevisFIDO configuration files and options.

Application Configuration

The main nevisFIDO configuration is specified in a file in standard YAML format. You find the file in the instance directory: /var/opt/nevisfido/<instance>/conf/nevisfido.yml.

It is possible to replace the configuration by supplying a custom --config location in the RUN_ARGS environment variable in the env.conf file of the instance.

Some property values are expressions that will be replaced. The next list shows the available syntax:

  • ${exec:command}

    Executes the given command and uses its output as the value.

    Example: server.host: ${exec:hostname -f}

  • ${env:variablename}

    Uses the value of the specified environment variable.

    Example: server.host: ${env:HOSTNAME}

Server Configuration

The server configuration defines the configuration of the main web server.

  • server.port

    Web application port. If not specified, the default value is 8080.

  • server.host

    Network address to which the server must bind. By default, it binds to all available interfaces (that is, "0.0.0.0").

  • server.protocol

    Either http or https. It is advisable to always run nevisFIDO in https mode. Refer to the server.tls settings for configuring TLS if set to https.

  • sever.connection-timeout

    The time after which idle connections will be terminated. The default value is 30 seconds. If no time unit is provided, seconds will be used.

  • sever.tls.keystore

    Path to the keystore that holds the TLS certificate of nevisFIDO.

  • sever.tls.keystore-passphrase

    Password used to access the keystore and the key. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • sever.tls.keystore-type

    Defines the type of keystore. It is recommended using a "pkcs12" type of keystore. If not specified, the system will use the default keystore type of the Java Virtual Machine that runs nevisFIDO.

  • sever.tls.key-alias

    Alias that identifies the key in the keystore.

  • sever.tls.require-client-auth

    true if client authentication (2-way TLS) is required for the TLS connection, false if no client authentication is required.

  • sever.tls.truststore

    Path to the truststore that holds the TLS certificates (typically a PKCS12 file) that nevisFIDO trusts. These are the certificates presented by the client when doing client authentication.

  • sever.tls.truststore-passphrase

    Password used to access the truststore contents. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • sever.tls.truststore-type

    Defines the type of truststore. It is recommended using a "pkcs12" type of keystore. If not specified, the system will use the default keystore type of the Java Virtual Machine that runs nevisFIDO.

  • sever.tls.supported-protocols

    Provides a list of protocols that are accepted by the client when trying to initiate a connection with TLS. This attribute must be provided as an array. By default only TLSv1.2 is supported.

  • sever.tls.cipher-suites

    Provides a list of ciphers that are accepted by the client when trying to initiate a connection with TLS. This attribute must be provided as an array. The default cipher suites are:

    • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    • TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
    • TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Server configuration example
server:
port: 9443
host: localhost
protocol: https
connection-timeout: 30s
tls:
keystore: conf/nevisfido-server-keystore.p12
keystore-passphrase: password
keystore-type: pkcs12
key-alias: nevisfido
supported-protocols:
- TLSv1.2
cipher-suites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_DHE_RSA_WITH_AES_256_GCM_SHA384

FIDO UAF Configuration

All UAF related configuration is located in the fido-uaf configuration section. This includes the UAF specific configuration options and files.

  • fido-uaf

    The root node of the FIDO UAF application configuration. It defines the application ID information.

  • fido-uaf.enabled

    FIDO UAF can be enabled or disabled with this boolean property, without the need to remove or comment out it’s configuration. Note that at least one of FIDO UAF and FIDO2 must be enabled.

  • fido-uaf.app-id

    The application ID.

  • fido-uaf.facets

    The facets associated with the application ID. This is an array of strings. Note that changing the contents of the facets configuration in the nevisfido.yml file are automatically taken into account without requiring a server restart. Refer to the Access App Facet ID calulation chapter or the SDK Facet ID configuration chapter for more details.

Wildcard Facet IDs

The Nevis Access App as well as the Nevis Mobile Authentication SDK support wildcard facet entries such as android:apk-key-hash:* and ios:bundle-id:*. Wildcard facets are useful for development and demo purposes, for example using the mobile SDK example applications. They are not allowed in production environments, use specific facet ID entries instead.

  • fido-uaf.metadata

The configuration of the metadata that nevisFIDO uses to process the requests. The default metadata contains the definitions of the Nevis Mobile Authentication authenticators.

  • fido-uaf.metadata.path

The path (file or directory) containing the metadata. If the path is a directory, nevisFIDO reads all the files in the directory and aggregates its content. This allows you to update the metadata by adding/removing/updating single files. nevisFIDO expects that each of the files contains one JSON object. The JSON object is either an object defining a single UAF Metadata Statement or a JSON array with several metadata statements.

  • fido-uaf.metadata.polling-period

    Determines how often nevisFIDO checks whether metadata content has changed. For example, if polling-period is set to "120s", then nevisFIDO checks the metadata content every two minutes for changes. The default value is 5 seconds. If no time unit is provided, seconds will be used.

  • fido-uaf.policy

    The configuration of the policy that nevisFIDO uses to process requests. nevisFIDO can support multiple policies. The default nevisFIDO policy accepts all the Nevis Mobile Authentication authenticators.

    • In case of a registration request from a user that already has registered other credentials, nevisFIDO adds one non-acceptable match criteria to each of the already registered credentials in the policy. This is to prevent the user from reregistering an already registered credential.
    • In case of a step-up authentication, nevisFIDO validates the user against the policy. If at least one credential is registered for the provided username, nevisFIDO returns a policy that only contains the user’s AAID and KeyIDs. If no valid credentials are found, the policy is sent as defined in the configuration files.
  • fido-uaf.policy.path

    The path to the file or directory containing the policies. See policy configuration for details.

  • fido-uaf.timeout

    The configuration of the client timeouts.

  • fido-uaf.timeout.registration

    Defines the maximum time duration between the generation of the RegistrationRequest by nevisFIDO and the RegistrationResponse by the FIDO UAF client. If the client has not sent the response after this time, a client timeout occurs. The default value is 5 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.authentication

    Defines the maximum time duration between the generation of the AuthenticationRequest by nevisFIDO and the AuthenticationResponse by the FIDO UAF client. If the client has not sent the response after this time, a client timeout occurs. The default value is 2 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.token-registration

    Defines the maximum time a client has to redeem a registration token after the generation of the token by nevisFIDO. Once the token is redeemed, the value of the registration timeout applies: from the moment of the redemption of the token the client has a maximum time (the registration timeout) to send a RegistrationResponse to nevisFIDO). The default value is 5 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.token-authentication

    Defines the maximum time a client has to redeem an authentication token after the generation of the token by nevisFIDO. Once the token is redeemed, the value of the authentication timeout applies: from the moment of the redemption of the token the client has a maximum time (the authentication timeout) to send an AuthenticationResponse to nevisFIDO). The default value is 2 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.token-deregistration

    Defines the maximum time a client has to redeem a deregistration token after the generation of the token by nevisFIDO. The default value is 2 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.token-deregistration

    Defines the maximum time a client has to redeem a deregistration token after the generation of the token by nevisFIDO. The default value is 2 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.timeout.device-request

    Defines the maximum time divergence that is accepted between the time specified in the creationTimeInEpochMillis attribute in the device service requests and the time the server processes the request. This value is close to the time divergence that is accepted between the mobile device clock and the server clock. If the clock divergence is bigger than this value, false positives will occur validating the device requests and the requests will be refused. The default value is 5 minutes. If no time unit is provided, seconds will be used.

  • fido-uaf.transaction-confirmation

    The configuration of the transaction confirmation.

  • fido-uaf.transaction-confirmation.max-text-length

    The maximum length of the transaction content when the content type of the transaction is text-plain. For example, if the transaction is of type text-plain, the value of max-text-length is 1000 and the content of the transaction in base64 URL encoded format has more than 1000 characters, the transaction will result in an error. The default value is 200 (as defined in the FIDO UAF specification) . The minimum value is 200, the maximum value is 2000. See Transaction Confirmation for more details.

  • fido-uaf.authorization

    Defines the authorization to be used when handling GetUAFRequest requests. See more in Authorization for FIDO UAF.

  • fido-uaf.dispatchers

    The list of dispatchers that can be used to dispatch tokens. See more in Dispatchers Configuration.

FIDO UAF configuration example
fido-uaf:
app-id: "https://www.siven.ch/appID"
facets:
- "https://register.siven.ch"
- "android:apk-key-hash:324234234"
metadata:
path: conf/metadata
policy:
path: conf/policy/policy.json
timeout:
registration: 30s
authentication: 30s
token-registration: 30s
token-authentication: 30s
token-deregistration: 30s

Authorization for FIDO UAF

nevisFIDO provides several authorization validation mechanisms for each operation, to meet the operations' different security requirements. For example, the deregistration operation usually requires authorization, to ensure that only known clients can deregister a FIDO UAF credential. To trigger authentication, however, authorization is typically not required.

info

The Modify Dispatch Target Service uses JWS to verify whether a request is sent by a trusted client. Therefore, the authorization validation configuration does not apply to this service.

Configuration Example
fido-uaf:
authorization:
# The username will be retrieved from the SecToken for the registration requests
registration:
type: sectoken
truststore: /var/opt/nevisfido/default/conf/truststore-with-nevisauth-signature-keys.p12
truststore-passphrase: password
truststore-type: pkcs12
username-attribute-names:
- userid

# The username will be retrieved from the Context for the authentication requests
authentication:
type: none

# The username will be retrieved from the SecToken for the deregistration requests
deregistration:
type: sectoken
truststore: /var/opt/nevisfido/default/conf/truststore-with-nevisauth-signature-keys.p12
truststore-passphrase: password
truststore-type: pkcs12
username-attribute-names:
- userid

Currently, you can configure two authorization validation modes: Authorization validation with SecToken, or no authorization validation.

SecToken Authorization

The SecToken authorization mode expects that the username is provided in the HTTP headers, as part of the SecToken. The SecToken is validated by nevisFIDO. For the authorization to be successful, the username in the SecToken must match the username in the request (which is provided, for example, in the context of the GetUAFRequest).

Assuming that the username is provided in the SecToken for registration operations, the process is as follows:

  1. The FIDO UAF client tries to register a credential.
  2. nevisProxy detects that the FIDO UAF client is not authenticated. It redirects the client to nevisAuth for authentication.
  3. nevisAuth generates a SecToken upon successful authentication of the client.
  4. The authenticated FIDO UAF client will now be able to access the registration endpoint of nevisFIDO. nevisProxy will include the SecToken generated in the previous step in the Basic authorization header.
  5. nevisFIDO validates the SecToken, by verifying that the token was signed by nevisAuth and is not expired.
  6. nevisFIDO also checks whether the SecToken contains the username provided in the request (for example, in the context of the GetUAFRequest or in the username attribute of the "Create dispatch target" request).

The Basic authorization header has the following value:

    Basic <base64Value>

where <base64Value> is a string encoded with base64 and with the following format:

    <username>:<sectoken>

Note that nevisFIDO does not take into account the first part of the base64 value (username), but retrieves the username from the SecToken. The reason for this is that the username used to log in may differ from the username required in nevisFIDO. The content of the SecToken is configurable, thus allowing for flexibility in scenarios where one user can have several user identifiers.

However, it is still recommended that you include a username in the Basic authorization header. This is because nevisProxy must provide two values to meet the definition of a correct Basic header.

See nevisProxy Configuration for configuration details.

info

The use of a SecToken implies a preceding validation of the user identity by nevisAuth. So for security reasons, we recommend the usage of this type of authorization for non-authentication operations (registration, deregistration, creation and deletion dispatch targets).

To enable a SecToken authorization for a specific operation, set the value of the type attribute to sectoken.

The SecToken authorization has the following additional configuration attributes:

  • truststore

    Defines the path to the truststore with the public key that is used by nevisAuth to sign the SecToken.

  • truststore-passphrase

    The password needed to access the truststore. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • truststore-type

    The type of the truststore. The recommended type is "pkcs12". Using the legacy Java key-/truststore "jks" is also possible. If this attribute is not set, the system will use the default truststore type of the Java Virtual Machine running nevisFIDO.

  • username-attribute-names

    Defines the attributes that the server will use to retrieve the username. If any of the SecToken attributes listed in this property contains the expected username, then the request will be authorized. By default, the value is userId. Typically, the authorized user and the user associated with the nevisFIDO operation are the same. For example, the authorized user is also the user whose FIDO credentials must be deleted. The authorized user is normally the user defined by the userId attribute of the SecToken. But in some cases, the authenticated user must perform an operation on behalf of another user. For example, an administrator must delete the FIDO credentials of a given user whose user device was lost or stolen. In this case, the username associated with the operation is not the user defined in the SecToken (that is, the userId attribute of the SecToken does not contain the username of the FIDO credentials to be deleted). To be able to cover both use cases, the configuration attribute username-attribute-names can take several values.

info

There is no username provided in the delete dispatch target request, so the SecToken authorization works in a different way as for the other endpoints: the element that is used to validate that the request is authorized is the user identifier used by the repository (extId when the user is stored in nevisIDM) of the user owning the dispatch target to be deleted. This is why the value of the username-attribute-names attribute of the SecToken configuration should contain in most cases the value userId; with this configuration the userId in the SecToken is compared to the user identifier (as stored by the repository) of the owner of the dispatch target.

Configuration Example
fido-uaf:
authorization:
registration:
type: sectoken
truststore: /var/opt/nevisfido/default/conf/truststore-with-nevisauth-signature-keys.p12
truststore-passphrase: password
truststore-type: pkcs12
username-attribute-names:
- userid
No Authorization Validation

It is not recommended using the "no authorization" validation mode for non-authentication operations, such as registration, deregistration as well as creating and deleting dispatch targets. This is because the "no authorization"s ralidation mode is not secure. It allows everyone to perform an operation and thus makes impersonation possible. Fors rxample, the malicious client "Mallory" could send a registration request providing Alice’s name. This would generate credentials in Mallory’s FIDO device that would be associated with Alice, allowing Mallory to authenticate as Alice.

To not perform authorization validation for a specific operation, set the value of the type attribute to none.

Configuration Example
fido-uaf:
authorization:
authentication:
type: none

Dispatchers Configuration

nevisFIDO can generate and dispatch tokens through one of the configured dispatchers (see Dispatch Token Service). The HTTP client specifies the dispatcher to be used in the HTTP request to generate the token.

The dispatching mechanism is used in the out-of-band case. In this case, one device triggers the FIDO operation by asking to generate a token. Then the token is dispatched to another device through a dispatcher. This FIDO UAF enabled device redeems the token and proceeds with the FIDO UAF operation. Usually, the device that triggers the operation is a desktop computer whereas the device receiving the token is a mobile device with FIDO UAF capabilities.

A typical example of a dispatcher is the FCM Dispatcher, which allows to dispatch tokens to a mobile device. The FCM dispatcher is provided by nevisFIDO.

nevisFIDO allows to configure several dispatchers. The HTTP client specifies the dispatcher to be used by providing the value of the type attribute. Currently only one dispatcher for a given type can be configured (that is, you cannot configure two FCM dispatchers).

    dispatchers:
- type: logger

Expression resolution in dispatcher configuration has a limitation, which is only relevant for developers implementing custom dispatchers. Expressions resulting in integer or Boolean values require special escaping to result in strings. For example, assuming that the value of the environment variable BOOLEAN_VALUE is "true":

    dispatchers:
- type: logger
value: ${ENV:BOOLEAN_VALUE}

value is boolean "true".

    dispatchers:
- type: logger
value: "${ENV:BOOLEAN_VALUE}"

value is boolean "true".

    dispatchers:
- type: logger
value: '"${ENV:BOOLEAN_VALUE}"'

value is string "true".

Metadata Configuration

A minimal metadata configuration must include the following attributes:

  • aaid
  • description
  • authenticatorVersion
  • upv
  • assertionScheme
  • authenticationAlgorithm
  • publicKeyAlgAndEncoding
  • attestationTypes
  • userVerificationDetails
  • keyProtection
  • matcherProtection
  • attachmentHint
  • isSecondFactorOnly
  • tcDisplay
  • attestationRootCertificates
info

The possible configuration options are not explained in detail here. For more information, refer to the UAF Metadata Statement specification.

The default metadata statements shipped with nevisFIDO include all authenticators supported by the Access App and Mobile Authentication SDK.

Policy Configuration

The policy defines which are the authenticators that can be used in a registration or authentication operation.

nevisFIDO must be configured to have at least one policy, which will be referred to, as the default policy. The policy to be used is specified in the GetUafRequest context (registration, or authentication). If no policy is provided in the GetUafRequest, the default policy is used.

The policy is configured using fido-uaf.policy.path. The nevisFIDO path specified in fido-uaf.policy.path can be either a file or a directory:

  • If it is a file, only one policy will be supported (the default policy). The policy defined in the file will be used when there is no policy specified in the GetUafRequest context (registration, or authentication), or if the specified policy is default.

  • If it is directory, the directory contains the different policies to be supported. Each file with .json extension in the directory contains a policy, and the name of the policy is the name of the file without the JSON extension.

    The directory must contain a file named default.json with the default policy. The policy defined in default.json will be used when there is no policy specified in the GetUafRequest context, or if the specified policy is default.

    If the directory contains a file named my-policy.json, then it contains the policy that will be used when the policy in the GetUafRequest context is my-policy.

Each of the policy configuration files contains one JSON object, representing a Policy as defined in the FIDO UAF specification.

You can find a number of predefined policies under the conf/policy directory of the nevisFIDO installation:

  • all-authenticators.json allows to execute the registration or authentication with all Nevis authenticators.
  • only-pin-authenticators.json allows only the PIN authenticators.
  • only-biometric-authenticators.json allows only biometric authenticators.
  • only-password-authenticators.json allows only (alphanumeric) password authenticators.
info

The possible configuration options are not explained in detail here. For more information, refer to the UAF Policy and UAF Match Criteria specifications.

The following sample code shows a policy that accepts all authenticators from the vendor with ID "1234":

Policy configuration example for authenticators from vendor 1234
{
"accepted":
[
[{ "vendorID": ["1234"], "authenticationAlgorithms": [1, 2, 5, 6], "assertionSchemes": ["UAFV1TLV"]}]
]
}

FIDO2 Configuration

  • fido2

    The root node of the FIDO2 application configuration.

  • fido2.enabled

    FIDO2 can be enabled or disabled with this boolean property, without the need to remove or comment out it’s configuration. Note that at least one of FIDO UAF and FIDO2 must be enabled.

  • fido2.rp-name

    Name of the relying party. This value allows spaces to be used and is intended to be human readable. An example would be Siven Inc..

  • fido2.rp-id

    The ID of the relying party, where the public key credentials will be scoped to, see rpId in the specification. It is based on the host’s domain name and it restricts the set of origins that will be supported by the server. When evaluating a credential in context of a FIDO2 operation, the rpId must be equal to the origin’s effective domain, or a registrable domain suffix of the origin’s effective domain.

  • fido2.origins

    List of origins that will be associated with this server, restricted by the server’s configured rp-id. When evaluating a credential in context of a FIDO2 operation, the rpId must be equal to the origin’s effective domain, or a registrable domain suffix of the origin’s effective domain.

  • fido2.signature-algorithms

    The list of algorithms will be offered during registration for the client authenticator to generate the key material with. Supported values are ES256, ES384, ES512, RS256, RS384, RS512 and RS1. The default value is ES256.

  • fido2.timeout

    Timeouts for FIDO2 are not related to different ceremonies (i.e. registration & authentication), but rather for whether user verification is required in a ceremony or not.

  • fido2.timeout.user-verification

    Maximum time that a FIDO2 client has to send response in a ceremony where user-verification is required. Default value is 300s.

  • fido2.timeout.no-user-verification

    Maximum time that a FIDO2 client has to send response in a ceremony where user-verification is not required. Default value is 120s.

  • fido2.display-name-source

    Defines the attribute of the user that will be populated into the user.name property in the PublicKeyCredentialCreationOptions object that nevisFIDO sends to the FIDO2 client during the Registration ceremony. Some browsers choose this user.name property to display to the user when they prompt for user interaction (as opposed to user.displayName). Supported values are loginId, displayName, email and username - this latter does not correspond strictly to a nevisIDM user property, but instead is the same username what nevisFIDO received in the ServerPublicKeyCredentialCreationOptionsRequest object.

    For a nevisIDM credential repository, the default is loginId, for an in-memory credential repository, the default is username.

  • fido2.authorization

    Defines the authorization to be used when handling Options requests. See more in Authorization for FIDO2.

Authorization for FIDO2

nevisFIDO provides authorization validation mechanisms for each ceremony, to meet the ceremonies' different security requirements. For example, the registration ceremony usually requires authorization to ensure that only known clients can register a FIDO2 credential. To trigger the authentication ceremony however, authorization is typically not required.

FIDO2 Configuration Example
fido2:
authorization:
# The username will be retrieved from the SecToken for the creation options requests and validated against the incoming one
registration:
type: sectoken
truststore: /var/opt/nevisfido/default/conf/truststore-with-nevisauth-signature-keys.p12
truststore-passphrase: password
truststore-type: pkcs12
username-attribute-names:
- loginid
# The username will be retrieved from the get options requests
authentication:
type: none

FIDO2 Authorization supports validation with SecToken, or no authorization validation.

SecToken Authorization

The SecToken authorization mode expects the username to be provided in the HTTP headers as part of the SecToken. The SecToken is validated by nevisFIDO. For the authorization to be successful, the username in the SecToken must match the username in the request (that is for example provided in the options sent to trigger the registration ceremony).

Assuming that the username is provided in the SecToken for registration operations, the process is as follows:

  1. The FIDO2 client tries to register a credential.
  2. nevisProxy detects that the FIDO2 client is not authenticated. It redirects the client to nevisAuth for authentication.
  3. nevisAuth generates a SecToken upon successful authentication of the client.
  4. The authenticated FIDO2 client will now be able to access the creation options endpoint of nevisFIDO (which is accessed in the registration ceremony). nevisProxy will include the SecToken generated in the previous step in the Basic authorization header.
  5. nevisFIDO validates the SecToken, by verifying that the token was signed by nevisAuth and is not expired.
  6. nevisFIDO also checks whether the SecToken contains the username provided in the request.

The Basic authorization header has the following value:

    Basic <base64Value>

where <base64Value> is a string encoded with base64 and with the following format:

    <username>:<sectoken>
info

Note that nevisFIDO does not take into account the first part of the base64 value (username), but retrieves the username from the SecToken. The reason for this is that the username used to log in may differ from the username required in nevisFIDO. The content of the SecToken is configurable, thus allowing for flexibility in scenarios where one user can have several user identifiers.

However, it is still recommended that you include a username in the Basic authorization header. This is because nevisProxy must provide two values to meet the definition of a correct Basic header.

See nevisProxy Configuration for configuration details.

info

The use of a SecToken implies a preceding validation of the user identity by nevisAuth. So for security reasons, we recommend the usage of this type of authorization for the registration ceremony.

To enable a SecToken authorization for a specific ceremony, set the value of the type attribute to sectoken.

The SecToken authorization has the following additional configuration attributes:

  • truststore

    Defines the path to the truststore with the public key that is used by nevisAuth to sign the SecToken.

  • truststore-passphrase

    The password needed to access the truststore. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • truststore-type

The type of the truststore. The recommended type is "pkcs12". Using the legacy Java key-/truststore "jks" is also possible. If this attribute is not set, the system will use the default truststore type of the Java Virtual Machine running nevisFIDO.

  • username-attribute-names

    Defines the attributes that the server will use to retrieve the username. If any of the SecToken attributes listed in this property contains the expected username, then the request will be authorized. By default, the value is userId. Typically, the authorized user and the user associated with the nevisFIDO operation are the same. For example, the authorized user is also the user whose FIDO credentials must be created. The authorized user is normally the user defined by the userId attribute of the SecToken. But in some cases, the authenticated user must perform an operation on behalf of another user. For example, an administrator might create the FIDO credentials on behalf of another user. In this case, the username associated with the ceremony is not the user defined in the SecToken (that is, the userId attribute of the SecToken does not contain the username of the FIDO credentials to be created) To be able to cover both use cases, the configuration attribute username-attribute-names can take several values.

FIDO2 Authorization Example
fido2:
authorization:
# The username will be retrieved from the SecToken for the creation options requests and validated against the incoming one
registration:
type: sectoken
truststore: /var/opt/nevisfido/default/conf/truststore-with-nevisauth-signature-keys.p12
truststore-passphrase: password
truststore-type: pkcs12
username-attribute-names:
- userid
# The username will be retrieved from the get options requests
authentication:
type: none

FIDO2 Authorization supports validation with SecToken, or no authorization validation.

Management Configuration

Configuration of liveness and readiness probes.

The configuration described in this section are experimental and can change in future releases.

  • management.server

    Main node of the management server configuration properties.

  • management.server.port

    Port where the management server listens. Currently this includes the readiness probe.

  • management.healthchecks

    Main node for health probe configurations.

  • management.healthchecks.enabled

    Enables liveness and readiness probes.

Management configuration example
management:
server:
port: 9452
healthchecks:
enabled: false

Credential Repository Configuration

The credential repository holds the registered credentials. nevisFIDO needs access to this repository to be able to perform the following actions:

  • Adding credentials.
  • Reading credentials.
  • Removing credentials.

You specify the configuration of the credential repository with the credential-repository attribute:

  • credential-repository

    The root node of the credential repository configuration.

  • credential-repository.type

    Defines the type of the credential repository. Currently, you can configure two types of credential repositories, the in-memory and the nevisIDM types of credential repository.

In-Memory Credential Repository

In case of an in-memory type of credential repository, the registered credentials are stored in the memory. The registered credentials will be lost when you stop nevisFIDO. This type of credential repository is therefore mainly used for testing purposes.

To define an in-memory type of credential repository, set the value of the type attribute to "in-memory". The in-memory repository does not have additional configuration options.

In-memory credential repository configuration example
credential-repository:
type: in-memory
caution

Do not use actively in production setups.

nevisIDM Credential Repository

In case of a nevisIDM type of credential repository, the FIDO UAF credentials are stored in nevisIDM.

If you select this type of repository, nevisFIDO needs key material to connect to nevisIDM. The connection is based on TLS Client Authentication. This means that both parties require a correctly set up private key and public certificate to be able to trust each other. The public certificate of nevisIDM has to be imported into nevisFIDO’s truststore and vice versa.

tip

nevisFIDO has 60 seconds to establish connections to and execute requests with nevisIDM before a timeout will occur.

To define a nevisIDM type of credential repository, set the value of the type attribute to "nevisidm".

The nevisIDM credential repository has the following additional configuration attributes:

  • administration-url

    Defines the URL pointing to the nevisIDM AdminService. For example: https://nevisidm.siven.ch:8443/nevisidmcc/services/v1/AdminService. Configuring the administration URL is required for supporting UAF at the server.

  • rest-url

    Defines the URL pointing to the root endpoint of the nevisIDM REST API. For example: https://nevisidm.siven.ch:8443/nevisidm. Configuring the REST URL is required.

  • keystore

    Defines the path to the keystore holding the nevisFIDO client certificate. nevisIDM must have a technical user whose certificate credential contains the public key of this nevisFIDO client certificate.

  • keystore-passphrase

    Sets the password of the keystore. It is assumed that this keystore password can be used to access the key. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • keystore-type

    Defines the type of keystore. A "pkcs12" type of keystore is recommended. Using the legacy Java key-/truststore "jks" is also possible. If you do not specify this attribute, the system will use the default keystore type of the Java Virtual Machine that runs nevisFIDO.

  • truststore

    Path to the truststore containing the nevisIDM public key.

  • truststore-passphrase

    Defines the password used to access the truststore. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • truststore-type

    Defines the type of truststore. A "pkcs12" truststore type is recommended. Using the legacy Java key-/truststore "jks" is also possible. If you do not specify this attribute, the system will use the default truststore type of the Java Virtual Machine that runs nevisFIDO.

  • admin-service-version

    Defines the version of the Admin Service SOAP interface to be used to communicate with nevisIDM. The default value is v1_46.

  • client-id

    Specifies the ID of the nevisIDM client that contains the relevant data. Configuring the client ID is required.

  • user-attribute

    Specifies how the username provided by the client applications is mapped to a user in nevisIDM. The user will be looked up in nevisIDM based on the provided information, if not found the operation will be aborted immediately. The allowed values are extId, and loginId. If not defined, the extId attribute is used as value of the attribute.

    For UAF the username is provided in the context of the GetUAFRequest ( for registration , authentication and deregistration). For FIDO2, the username is provided in the OptionsRequest for registration and authentication.

info

The username mapper is experimental and there are no guarantees that it will be kept in the future.

nevisIDM credential repository configuration example
credential-repository:
type: nevisidm
administration-url: https://nevisauth-fido-test1.zh.nevis-security.com:8443/nevisidmcc/services/v1/AdminService
keystore: /var/opt/nevisfido/default/conf/keystore.p12
keystore-passphrase: password
keystore-type: pkcs12
truststore: /var/opt/nevisfido/default/conf/truststore.p12
truststore-passphrase: password
truststore-type: pkcs12
admin-service-version: v1_46
client-id: 100
client-name: nevis
user-attribute: loginId
Be careful with the administration-url and rest-url attributes!
  • Use administration-url when you’re running a FIDO UAF instance
  • Use rest-url if you’re running a FIDO2 instance

In case you are running an instance supporting both FIDO UAF and FIDO2, configure both attributes.

Session Repository Configuration

Sessions managed by nevisFIDO are stored either in the memory or in a (MariaDB) SQL database.

You specify the configuration of the session storage with the session-repository attribute:

  • session-repository

    The root node of the session repository configuration.

  • session-repository.type

    The type of the session repository. The default value is "in-memory".

In-Memory Session Repository

The in-memory session repository is selected by setting "in-memory" as the repository type. This type of session repository has no other configuration options.

In-memory session repository configuration example
session-repository:
type: in-memory

The in-memory session repository is the default. It will also be selected if the above configuration is omitted.

We recommend only using in-memory for development and testing purposes. Use the SQL session repository for production setups.

SQL Session Repository

The SQL session repository is selected by configuring "sql" as the repository type. nevisFIDO comes bundled with MariaDB and PostgreSQL client capability. MariaDB and PostgreSQL are the officially supported SQL storage backend.

The SQL session repository needs a JDBC URL for locating the database, and a user and password for authentication. nevisFIDO will automatically initially generate the required tables in the specified database (no patches are applied later). It is recommended to create a dedicated MariaDB database to store the nevisFIDO session information. The required attributes are:

  • jdbc-url

    The JDBC URL to the database.

info

Examples:

  • jdbc:mariadb://localhost:3306/db?autocommit=true
  • jdbc:postgresql://localhost:5432/db

For more information visit the official connection parameter documentation for MariaDB and PostgreSQL

  • user

    The user name needed to access the database.

  • password

    The password needed to access the database. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • schema-user

    The user name of the user who creates the schema and the tables in the database. If you do not provide a schema user here, the system will use the user specified in the attribute user to create the schema. However, it is recommended having different users for creating the schema and for accessing the data.

info

If you do not set the schema-user attribute, do not set the schema-user-password attribute either. Otherwise the system will throw an error. This is because the system takes the user as fallback if no schema-user is provided. If in this case both the password attributes schema-user-password and password are set, there are two passwords available for the user attribute, which is ambiguous.

  • schema-user-password

    The password of the schema-user, that is, the user who creates the schema and the tables in the database. If you do not provide the schema user password, the system takes the password specified in the attribute password as fallback. Use the mechanisms described in Application Configuration to avoid providing a plaintext password.

  • automatic-db-schema-setup

    If set to true, the tables used to store the session data will be created automatically by nevisFIDO when they are missing. Note that it will not apply patches on existing tables. For non-docker-based setups, those patches has to be manually applied based on the release notes. Set this property to false if the database must be not be set-up automatically. If not specified, the default value is true.

  • max-connection-lifetime

    Defines the maximum time that a database connection remains in the connection pool. Although having a high value improves the performance, it should be lower than the connection idle timeout of the database (parameter wait_timeout in MariaDB). If not specified, the default value is 30 minutes. If no time unit is provided, seconds will be used.

SQL session repository configuration example
session-repository:
type: sql
jdbc-url: 'jdbc:mariadb://localhost:3306/db'
user: data-user
password: secret
schema-user: schema-user
schema-user-password: schema-secret
automatic-db-schema-setup: true
session-lifetime: 25m
Typical use cases for database setup
Kubernetes environment

Configure the nevisFIDO Instance pattern with the Managed nevisFIDO Database.

Non-Kubernetes environment
  • Create the database object and the users in the database server manually, using the following SQL scripts

  • nevisFIDO by default is configured to use automatic-db-schema-setup

  • nevisFIDO on startup creates the database tables in the previously manually created database

Manual steps for the database setup

To be able to create the tables and define the schema, the schema user must have CREATE privileges in the database. To be able to read, update and remove the session information, the user must have SELECT, INSERT, UPDATE and DELETE privileges in the database.

The following sample configuration uses SQL commands to create a database and two separate users and grant them the required privileges. In the sample, the database where you store the session information is called nevisfido. The database server and nevisFIDO are located on the same machine. The created users match the users from the previous sample configuration (SQL session repository).

These scripts are not necessary with nevisAdmin4 and Kubernetes deployment there the DB schema is set up automatically.

MariaDB
CREATE DATABASE IF NOT EXISTS nevisfido;
CREATE USER 'data-user'@'localhost' IDENTIFIED BY 'secret';
CREATE USER 'schema-user'@'localhost' IDENTIFIED BY 'schema-secret';
GRANT SELECT, INSERT, UPDATE, DELETE ON nevisfido.* TO 'data-user'@'localhost';
GRANT CREATE, ALTER ON nevisfido.* TO 'schema-user'@'localhost';
FLUSH PRIVILEGES;
The statements grant access from localhost only.

For test setups, you might connect remotely. In that case, you can use % instead of localhost to enable connection from anywhere. Do not use the approach in a production environment, it is not secure.

CREATE DATABASE IF NOT EXISTS nevisfido;
CREATE USER 'data-user'@'%' IDENTIFIED BY 'secret';
CREATE USER 'schema-user'@'%' IDENTIFIED BY 'schema-secret';
GRANT SELECT, INSERT, UPDATE, DELETE ON nevisfido.* TO 'data-user'@'%';
GRANT CREATE, ALTER ON nevisfido.* TO 'schema-user'@'%';
FLUSH PRIVILEGES;
Timezone setup

Timezone database should be initialized, in case the SELECT * FROM mysql.time_zone_name; returns nothing than this means the timezone database was not yet initialized. To fix that you have to run mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p.

PostgreSQL
CREATE USER "schema-user" WITH encrypted password 'password';
CREATE USER "data-user" WITH encrypted password 'password';

CREATE DATABASE nevisfido
WITH
OWNER = "schema-user";

ALTER ROLE "schema-user" IN DATABASE nevisfido SET search_path TO "schema-user";
ALTER ROLE "data-user" IN DATABASE nevisfido SET search_path TO "schema-user";

\connect nevisfido "schema-user";
CREATE SCHEMA "schema-user" AUTHORIZATION "schema-user";

GRANT USAGE ON SCHEMA "schema-user" to "data-user";
GRANT CONNECT ON DATABASE nevisfido TO "data-user";

ALTER DEFAULT PRIVILEGES FOR USER "schema-user" IN SCHEMA "schema-user" GRANT SELECT, INSERT, UPDATE, DELETE, TRIGGER ON TABLES TO "data-user";
ALTER DEFAULT PRIVILEGES FOR USER "schema-user" IN SCHEMA "schema-user" GRANT USAGE, SELECT ON SEQUENCES TO "data-user";
ALTER DEFAULT PRIVILEGES FOR USER "schema-user" IN SCHEMA "schema-user" GRANT EXECUTE ON FUNCTIONS TO "data-user";
Session Reaping

When the SQL backend session repository is in use, a session reaping mechanism cleans up old sessions in the database to prevent the table from growing unlimitedly in size.

Sessions are reaped after three times the timeout of the client session. For example, if the default client timeout for a registration operation is 30 seconds, the registration session will be reaped after 90 seconds.

For client session timeout values, refer to FIDO UAF Configuration.

Resilient SQL Session Repository using MariaDB

This chapter describes how to create a fault-tolerant setup for database- or network outages between nevisFIDO and MariaDB. (At least one database node must be available to prevent application failure.)

Use cases

On the primary DB node, failure connections will move to the secondary DB node when a 30 second timeout expires or immediately in case of an incoming request to the DB. You may experience increased response time for the duration of the switch.

Recovery connections will move back to the primary DB node once the connection maximum lifetime expires. The connection maximum lifetime is 30 minutes.

Implementation overview

Regular clustering solutions provide all fault tolerant features themselves. The connecting application is not aware of the resilient setup.

The suggested solution takes a different approach. In this setup, the connecting application becomes part of the resilient setup in terms of configuration.

There are two key features to achieve resilience:

1.) Connectivity (MariaDB JDBC driver) Configure a JDBC url where you define the DB nodes in priority order: jdbc:mariadb:sequential://host-db1:3306,host-db2:3306/nevisfido

2.) Data consistency (MariaDB replication) Configure Master-to-Master replication.

Replication is done by the database, the application and the JDBC driver are not aware of it.

Overview of database users

The replicated session store is managed by several database users to separate concerns. The creation of the users is explained below.

Step-by-step setup of the replicated session store

This chapters assumes that the Session Repository Configuration is completed and the tables used by nevisFIDO are created.

1.) Creation of the replication user:

    CREATE USER IF NOT EXISTS replication_user IDENTIFIED BY 'replicationpassword';
GRANT REPLICATION SLAVE ON *.* TO replication_user;

2.) Creation of the binary logs user:

    CREATE USER IF NOT EXISTS binarylog_user IDENTIFIED BY 'binarylogspassword';
GRANT SUPER ON *.* TO binarylog_user;

3.) Configuration of MariaDB service. To configure the MariaDB service, add the following entries to the file /etc/my.cnf as super user. The two configuration files (host-db1 and host-db2) differ at some points. The different lines are marked with (*).

3.1) Configure the MariaDB service on host-db1:

    [mariadb]
# Enabling binary log
log-bin
# The ID of this master (*)
server_id=1
# The ID of the replication stream created by this master (*)
gtid-domain-id=1
# The basename and format of the binary log
log-basename=mariadbmaster
binlog-format=MIXED
# Setting which tables are replicated
replicate_wild_do_table="nevisfido.%"
# Avoiding collisions of primary IDs for tables where the primary ID is auto-incremented
# Auto-increment value
auto_increment_increment=2
# Auto-increment offset (*)
auto_increment_offset=1
# Suppressing duplicated keys errors for multi-master setup
slave_exec_mode=IDEMPOTENT
# Ignoring some data definition language errors
slave-skip-errors=1452, 1062
# Suppressing binary logs after a delay regardless of the replication status
expire_logs_days=1
# Maximum number of connections
max_connections=1000
# Size of each of the binary log files (default: 1GB)
max_binlog_size=500M
# Enabling writing to the DB in parallel threads for the replication
slave-parallel-threads=10
# enabling semi-synchronous replication
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_slave_enabled=ON
# change to READ COMMITTED
transaction-isolation=READ-COMMITTED

3.2) Configure the MariaDB service on host-db2:

    [mariadb]
# Enabling binary log
log-bin
# The ID of this master (*)
server_id=2
# The ID of the replication stream created by this master (*)
gtid-domain-id=2
# The basename and format of the binary log
log-basename=mariadbmaster
binlog-format=MIXED
# Setting which tables are replicated
replicate_wild_do_table="nevisfido.%"
# Avoiding collisions of primary IDs for tables where the primary ID is auto-incremented
# Auto-increment value
auto_increment_increment=2
# Auto-increment offset (*)
auto_increment_offset=2
# Suppressing duplicated keys errors for multi-master setup
slave_exec_mode=IDEMPOTENT
# Ignoring some data definition language errors
slave-skip-errors=1452, 1062
# Suppressing binary logs after a delay regardless of the replication status
expire_logs_days=1
# Maximum number of connections
max_connections=1000
# Size of each of the binary log files (default: 1GB)
max_binlog_size=500M
# Enabling writing to the DB in parallel threads for the replication
slave-parallel-threads=10
# enabling semi-synchronous replication
rpl_semi_sync_master_enabled=ON
rpl_semi_sync_slave_enabled=ON
# change to READ COMMITTED
transaction-isolation=READ-COMMITTED

3.3) Restart the MariaDB servers on both hosts:

    sudo service mariadb restart

The database configurations previously shown enable semi-synchronous replication with the following lines:

    rpl_semi_sync_master_enabled=ON
rpl_semi_sync_slave_enabled=ON

MariaDB versions before 10.3.3 require the installation of plug-ins for semi-synchronous replication and are not supported.

Replication start To start the replication, log in as root into your MariaDB client and run the following commands

1.) On host-db1 (master is host-db2):

  CHANGE MASTER TO
MASTER_HOST='host-db2',
MASTER_USER='replication_user',
MASTER_PASSWORD='replicationpassword',
MASTER_PORT=3306,
MASTER_USE_GTID=current_pos,
MASTER_CONNECT_RETRY=10;

2.) On host-db2 (master is host-db1):

  CHANGE MASTER TO
MASTER_HOST='host-db1',
MASTER_USER='replication_user',
MASTER_PASSWORD='replicationpassword',
MASTER_PORT=3306,
MASTER_USE_GTID=current_pos,
MASTER_CONNECT_RETRY=10;

3.) On host-db1:


sql START SLAVE;

4.) On host-db2:

START SLAVE;
Additional setup

With the provided configuration (expire_logs_days=1 in the MariaDB settings), the system will automatically remove binary logs that are older than one day, even if the logs were not copied by the slave. This prevents the disk of the master node from being filled up in case the slave is down for a long time.

The automatic binary log removal takes place when

  1. the master DB node starts,
  2. the logs are flushed (nevisFIDO does not use this feature),
  3. the binary log rotates, or 4. the binary logs are purged manually (see below).

This means that binary logs older than one day can exist, if none of the listed actions occurred recently.

Complementary to this expiration feature, MariaDB provides the possibility to manually purge the binary logs. The purge action removes all binary logs that were already copied by the slave. This allows a safe removal of the binary logs on a regular basis.

The nevisProxy package is delivered with an adaptable purging script, which is located at: /opt/nevisproxy/sql/mariadb/purgebinarylogs.sh

To use this script,

  1. copy the script to a location of your choice, and 2. adapt it to your configuration.

The script takes care of both DB nodes, so that it only needs to be configured once.

If you use different database server nodes for nevisProxy and nevisAuth, you have to set them up separately.

You can schedule the script to run for example once per hour, with a cron job:

 0 * * * * /var/opt/nevisproxy/instance/conf/purgebinarylogs.sh # Absolute path of your adapted script

The provided configuration (max_binlog_size=500M in the MariaDB settings) allows you to configure the maximal size of the binary log files before rotating. The smaller the size, the more often rotations occur, which will slow down replication. The advantage is a more efficient purge process. The bigger the size, the less often rotations occur, but the disk may be filled with old logs.

According to our experiences, a size less than 8K does stop replication completely under heavy load, because the slave keeps rotating the logs.

Usually the slave stops replication if an error occurs. You can check the state of the slave with the following SQL command:

    show slave status\G

Showing the slave status requires the REPLICATION CLIENT grant.

If replication has stopped, usually the error that caused it will be displayed. First you should try to fix the error. If this is not possible, you can do a "forced" restart of the slave like this:

  • On the master call (to display the current state of the master):
MariaDB [replicated_session_store]> show master status\G
*************************** 1. row ***************************
File: mariadbmaster-bin.000131
Position: 194630804
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
  • On the slave (using the values returned by the call show master status\G on the master):
STOP SLAVE;
CHANGE MASTER TO
MASTER_LOG_FILE='mariadbmaster-bin.000131',
MASTER_LOG_POS=194630804;
START SLAVE;

In this way, the system will restart the slave, without replicating to the slave all sessions that occurred from the moment the replication has stopped until now.

Resilient SQL Session Repository using PostgreSQL

Not supported during the experimental phase.

Logging Configuration

The default logging configuration is located at /var/opt/nevisfido/<instance>/conf/logging.yml. nevisFIDO will not start if the log4j2 configuration file does not exist or cannot be read.

You can replace the log4j2 configuration by specifying a custom --log-config location in the RUN_ARGS environment variable in the instance’s env.conf file.

Protocols

You can debug either FIDO UAF or FIDO2 related business logic by configuring ch.nevis.auth.fido at DEBUG level.

  • The FIDO UAF API is in the package scope ch.nevis.auth.fido.api.uaf
  • The FIDO2 / WebAuthn API is in the package scope ch.nevis.auth.fido.api.webauthn
"Example:
<logger name="ch.nevis.auth.fido.api.webauthn" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>

Requests

You can debug HTTP requests by configuring org.springframework.web.filter.CommonsRequestLoggingFilter at DEBUG level.

Example: Debugging HTTP requests
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
</logger>

Default Nevis Authenticator Metadata

The FIDO UAF metadata file contains a list of all supported authenticators and their corresponding Metadata.

The nevisFIDO server ignores any authenticators and halts all operations in relation to them, which do not have metadata data entries accessible for the server.

The following default metadata file is shipped with the nevisFIDO component as well as the nevisAdmin4 nevisFIDO UAF Instance pattern, the default value of this field represents the metadata required for nevisFIDO to be able to work with the Nevis Access App.

[
{
"aaid" : "F1D0#0001",
"description" : "Android NEVIS Mobile Authentication PIN Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 4
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 9,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 1,
"matcherProtection" : 1,
"publicKeyAlgAndEncoding" : 256,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#0002",
"description" : "Android NEVIS Mobile Authentication Fingerprint Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 2
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 9,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 4,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 256,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#0003",
"description" : "Android NEVIS Mobile Authentication Biometric Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 346
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 9,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 4,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 256,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#0004",
"description" : "Android NEVIS Mobile Authentication Device Passcode Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 132
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 9,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 4,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 259,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#1001",
"description" : "iOS NEVIS Mobile Authentication PIN Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 4
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 2,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 1,
"matcherProtection" : 1,
"publicKeyAlgAndEncoding" : 257,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#1002",
"description" : "iOS NEVIS Mobile Authentication Fingerprint Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 2
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 2,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 6,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 257,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#1003",
"description" : "iOS NEVIS Mobile Authentication Face Recognition Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 16
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 2,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 6,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 257,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
},
{
"aaid" : "F1D0#1004",
"description" : "iOS NEVIS Mobile Authentication Device Passcode Authenticator",
"assertionScheme" : "UAFV1TLV",
"attestationRootCertificates" : [],
"attestationTypes" : [ 15880 ],
"upv" : [ {
"major" : 1,
"minor" : 1
} ],
"userVerificationDetails" : [ [ {
"userVerification" : 4
} ] ],
"attachmentHint" : 1,
"authenticationAlgorithm" : 2,
"authenticatorVersion" : 1,
"isSecondFactorOnly" : false,
"keyProtection" : 6,
"matcherProtection" : 2,
"publicKeyAlgAndEncoding" : 257,
"tcDisplay" : 1,
"tcDisplayContentType" : "text/plain"
}
]