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
orhttps
. It is advisable to always run nevisFIDO inhttps
mode. Refer to theserver.tls
settings for configuring TLS if set tohttps
.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:
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. The default metadata contains the definitions of the Nevis Mobile Authentication authenticators.fido-uaf.metadata
The configuration of the metadata that nevisFIDO uses to process the requests.
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 theRegistrationResponse
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 theAuthenticationResponse
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 (theregistration
timeout) to send aRegistrationResponse
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 (theauthentication
timeout) to send anAuthenticationResponse
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 ofmax-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:
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.
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.
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:
- The FIDO UAF client tries to register a credential.
- nevisProxy detects that the FIDO UAF client is not authenticated. It redirects the client to nevisAuth for authentication.
- nevisAuth generates a
SecToken
upon successful authentication of the client. - 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 theBasic
authorization header. - nevisFIDO validates the
SecToken
, by verifying that the token was signed by nevisAuth and is not expired. - nevisFIDO also checks whether the
SecToken
contains the username provided in the request (for example, in the context of theGetUAFRequest
or in theusername
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.
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 isuserId
. 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 theuserId
attribute of theSecToken
. 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 theSecToken
(that is, theuserId
attribute of theSecToken
does not contain the username of the FIDO credentials to be deleted). To be able to cover both use cases, the configuration attributeusername-attribute-names
can take several values.
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.
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
.
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
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 isdefault
.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 indefault.json
will be used when there is no policy specified in theGetUafRequest
context, or if the specified policy isdefault
.If the directory contains a file named
my-policy.json
, then it contains the policy that will be used when the policy in theGetUafRequest
context ismy-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.
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":
{
"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
andRS1
. The default value isES256
.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 thisuser.name
property to display to the user when they prompt for user interaction (as opposed touser.displayName
). Supported values areloginId
,displayName
,email
andusername
- this latter does not correspond strictly to a nevisIDM user property, but instead is the sameusername
what nevisFIDO received in theServerPublicKeyCredentialCreationOptionsRequest
object.For a nevisIDM credential repository, the default is
loginId
, for an in-memory credential repository, the default isusername
.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:
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:
- The FIDO2 client tries to register a credential.
- nevisProxy detects that the FIDO2 client is not authenticated. It redirects the client to nevisAuth for authentication.
- nevisAuth generates a
SecToken
upon successful authentication of the client. - 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 theBasic
authorization header. - nevisFIDO validates the
SecToken
, by verifying that the token was signed by nevisAuth and is not expired. - 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>
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.
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 isuserId
. 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 theuserId
attribute of theSecToken
. 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 theSecToken
(that is, theuserId
attribute of theSecToken
does not contain the username of the FIDO credentials to be created) To be able to cover both use cases, the configuration attributeusername-attribute-names
can take several values.
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:
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.
credential-repository:
type: in-memory
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.
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 areextId
, andloginId
. If not defined, theextId
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 theOptionsRequest
for registration and authentication.
The username mapper is experimental and there are no guarantees that it will be kept in the future.
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
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.
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.
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.
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 attributepassword
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 tofalse
if the database must be not be set-up automatically. If not specified, the default value istrue
.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.
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;
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;
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
Semi-synchronous replication By default, MariaDB uses asynchronous replication. To reach more consistency, it is recommended using semi-synchronous replication
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
- the master DB node starts,
- the logs are flushed (nevisFIDO does not use this feature),
- 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,
- 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
<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.
<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"
}
]