Copyright © 2013-2018 FIDO Alliance All Rights Reserved.
Describes APIs and an interoperability profile for client applications to utilize FIDO UAF. This includes methods of communicating with a FIDO UAF Client for both Web platform and Android applications, transport requirements, and an HTTPS interoperability profile for sending FIDO UAF messages to a compatible server.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current FIDO Alliance publications and the latest revision of this technical report can be found in the FIDO Alliance specifications index at https://www.fidoalliance.org/specifications/.
This document was published by the FIDO Alliance as a Implementation Draft. This document is intended to become a FIDO Alliance Proposed Standard. If you wish to make comments regarding this document, please Contact Us. All comments are welcome.
This Implementation Draft Specification has been prapared by FIDO Alliance, Inc. Permission is hereby granted to use the Specification solely for the purpose of implementing the Specification. No rights are granted to prepare derivative works of this Specification. Entities seeking permission to reproduce portions of this Specification for other uses must contact the FIDO Alliance to determine whether an appropriate license for such use is available.
Implementation of certain elements of this Specification may require licenses under third party intellectual property rights, including without limitation, patent rights. The FIDO Alliance, Inc. and its Members and any other contributors to the Specification are not, and shall not be held, responsible in any manner for identifying or failing to identify any or all such third party intellectual property rights.
THIS FIDO ALLIANCE SPECIFICATION IS PROVIDED “AS IS” AND WITHOUT ANY WARRANTY OF ANY KIND, INCLUDING, WITHOUT LIMITATION, ANY EXPRESS OR IMPLIED WARRANTY OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Type names, attribute names and element names are written as code
.
String literals are enclosed in “”, e.g. “UAF-TLV”.
In formulas we use “|” to denote byte wise concatenation operations.
The notation base64url refers to "Base 64 Encoding with URL and Filename Safe Alphabet" [RFC4648] without padding.
DOM APIs are described using the ECMAScript [ECMA-262] bindings for WebIDL [WebIDL-ED].
Following [WebIDL-ED], dictionary members are optional unless they are explicitly
marked as required
.
WebIDL dictionary members MUST NOT have a value of null.
Unless otherwise specified, if a WebIDL dictionary member is DOMString, it MUST NOT be empty.
Unless otherwise specified, if a WebIDL dictionary member is a List, it MUST NOT be an empty list.
UAF specific terminology used in this document is defined in [FIDOGlossary].
All diagrams, examples, notes in this specification are non-normative.
Note: Certain dictionary members need to be present in order to
comply with FIDO requirements. Such members are marked in the
WebIDL definitions found in this document, as
required
. The keyword required
has been
introduced by [WebIDL-ED], which is a work-in-progress. If you
are using a WebIDL parser which implements [WebIDL], then you
may remove the keyword required
from your WebIDL and
use other means to ensure those fields are present.
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC2119].
This section is non-normative.
The FIDO UAF technology replaces traditional username and password-based authentication solutions for online services, with a stronger and simpler alternative. The core UAF protocol consists of four conceptual conversations between a FIDO UAF Client and FIDO Server: Registration, Authentication, Transaction Confirmation, and Deregistration. As specified in the core protocol, these messages do not have a defined network transport, or describe how application software that a user interfaces with can use UAF. This document describes the API surface that a client application can use to communicate with FIDO UAF Client software, and transport patterns and security requirements for delivering UAF Protocol messages to a remote server.
The reader should also be familiar with the FIDO Glossary of Terms [FIDOGlossary] and the UAF Protocol specification [UAFProtocol].
This document is of interest to client-side application authors that wish to utilize FIDO UAF, as well as implementers of web browsers, browser plugins and FIDO clients, in that it describes the API surface they need to expose to application authors.
This document describes:
The following are out of scope for this document:
The goal of describing standard APIs and an interoperability profile for the transport of FIDO UAF messages here is to provide an example of how to develop a FIDO-enabled application and to promote the ease of integrating interoperable layers from different vendors to build a complete FIDO UAF solution. For any given application instance, these particular patterns may not be ideal and are not mandatory. Applications may use alternate transports, bundle UAF Protocol messages with other network data, or discover and utilize alternative APIs as they see fit.
The overall architecture of the UAF protocol and its various operations is described in the FIDO UAF Protocol Specification [UAFProtocol]. The following simplified architecture diagram illustrates the interactions and actors this document is concerned with:
This document describes the shaded components in Fig 1.
The core UAF protocol consists of five conceptual phases:
Discovery does not involve a protocol exchange with the FIDO Server. However, the information available through the discovery APIs might be communicated back to the server in an application-specific manner, such as by obtaining a UAF protocol request message containing an authenticator policy tailored to the specific capabilities of the FIDO user device.
Although the UAF protocol abstractly defines the FIDO server as the initiator of requests, UAF client applications working as described in this document will always transport UAF protocol messages over a client-initiated request/response protocol such as HTTP.
The protocol flow from the point of view of the relying party client application for registration, authentication, and transaction confirmation is as follows:
Deregister does not involve a UAF protocol round-trip. If the relying party server instructs the client application to perform a deregistration, the client application simply delivers the UAF protocol Request message to the FIDO UAF Client using the appropriate API. The FIDO UAF Client does not return the results of a deregister operation to the relying party client application or FIDO Server.
UAF protocol Messages are JSON [ECMA-404] structures, but client applications are discouraged from modifying them. These messages may contain embedded cryptographic integrity protections and any modifications might invalidate the messages from the point of view of the FIDO UAF Client or Server.
This section is normative.
These elements are shared by several APIs and layers.
This table lists UAF protocol status codes.
Code | Meaning |
---|---|
1200 | OK. Operation completed |
1202 | Accepted. Message accepted, but not completed at this time. The RP may need time to process the attestation, run risk scoring, etc. The server SHOULD NOT send an authenticationToken with a 1202 response |
1400 | Bad Request. The server did not understand the message |
1401 | Unauthorized. The userid must be authenticated to perform this operation, or this KeyID is not associated with this UserID. |
1403 | Forbidden. The userid is not allowed to perform this operation. Client SHOULD NOT retry |
1404 | Not Found. |
1408 | Request Timeout. |
1480 | Unknown AAID. The server was unable to locate authoritative metadata for the AAID. |
1481 |
Unknown KeyID. The server was unable to locate a registration
for the given UserID and KeyID combination.
This error indicates that there is an invalid registration on the user's device. It is recommended that FIDO UAF Client deletes the key from local device when this error is received. |
1490 | Channel Binding Refused. The server refused to service the request due to a missing or mismatched channel binding(s). |
1491 | Request Invalid. The server refused to service the request because the request message nonce was unknown, expired or the server has previously serviced a message with the same nonce and user ID. |
1492 | Unacceptable Authenticator. The authenticator is not acceptable according to the server's policy, for example because the capability registry used by the server reported different capabilities than client-side discovery. |
1493 | Revoked Authenticator. The authenticator is considered revoked by the server. |
1494 | Unacceptable Key. The key used is unacceptable. Perhaps it is on a list of known weak keys or uses insecure parameter choices. |
1495 | Unacceptable Algorithm. The server believes the authenticator to be capable of using a stronger mutually-agreeable algorithm than was presented in the request. |
1496 | Unacceptable Attestation. The attestation(s) provided were not accepted by the server. |
1497 | Unacceptable Client Capabilities. The server was unable or unwilling to use required capabilities provided supplementally to the authenticator by the client software. |
1498 | Unacceptable Content. There was a problem with the contents of the message and the server was unwilling or unable to process it. |
1500 | Internal Server Error |
This section is normative.
This section describes the API details exposed by a web browser
or browser plugin to a client-side web application executing in
a Document
[DOM] context.
FIDO's UAF DOM APIs are rooted in a new fido
object, a property
of window.navigator
code; the existence and properties of which
MAY be used for feature detection.
<script> if(!!window.navigator.fido.uaf) { var useUAF = true; } </script>
The window.navigator.fido.uaf
interface is the primary means of
interacting with the FIDO UAF Client. All operations are asynchronous.
interface uaf {
void discover (DiscoveryCallback
completionCallback, ErrorCallback
errorCallback);
void checkPolicy (UAFMessage
message, ErrorCallback
cb);
void processUAFOperation (UAFMessage
message, UAFResponseCallback
completionCallback, ErrorCallback
errorCallback);
void notifyUAFResult (int responseCode, UAFMessage
uafResponse);
};
discover
Discover if the user's client software and devices support UAF and if authenticator capabilities are available that it may be willing to accept for authentication.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
completionCallback |
| ✘ | ✘ | The callback that receives DiscoveryData from
the FIDO UAF Client. |
errorCallback |
| ✘ | ✘ | A callback function to receive error and progress events. |
void
checkPolicy
Ask the browser or browser plugin if it would be able to process the supplied request message without prompting the user.
Unlike other operations using an ErrorCallback
,
this operation MUST always trigger the callback and
return NO_ERROR
if
it believes that the message can be processed and a
suitable authenticator matching the embedded policy is
available, or the appropriateErrorCode
value otherwise.
Because this call should not prompt the user, it should not incur a potentially disrupting context-switch even if the FIDO UAF Client is implemented out-of-process.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
message |
| ✘ | ✘ |
A UAFMessage containing the policy and operation to be
tested.
|
cb |
| ✘ | ✘ | The callback function which receives the status of the operation. |
void
processUAFOperation
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
message |
| ✘ | ✘ | The UAFMessage to be used by the FIDO client software. |
completionCallback |
| ✘ | ✘ | The callback that receives the client response UAFMessage from
the FIDO UAF Client, to be delivered to the relying party server. |
errorCallback |
| ✘ | ✘ | A callback function to receive error and progress events from the FIDO UAF Client. |
void
notifyUAFResult
Used to indicate the status code resulting from a FIDO UAF message delivered to the remote server. Applications MUST make this call when they receive a UAF status code from a server. This allows the FIDO UAF Client to perform housekeeping for a better user experience, for example not attempting to use keys that a server refused to register.
If, and how, a status code is delivered by the server, is application and transport specific. A non-normative example can be found below in the HTTPS Transport Interoperability Profile.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
responseCode | int | ✘ | ✘ | The uafResult field of a ServerResponse . |
uafResponse |
| ✘ | ✘ | The UAFMessage to which this responseCode applies. |
void
A UAFResponseCallback
is used upon successful completion of an
asynchronous operation by the FIDO UAF Client to return the
protocol response message to the client application for
transport to the server.
This callback is also called in the case of deregistration completion, even though the response object is empty then.
callback UAFResponseCallback = void (UAFMessage
uafResponse);
UAFResponseCallback
ParametersuafResponse
of type UAFMessage
A DiscoveryCallback
is used upon successful completion of an
asynchronous discover operation by the FIDO UAF Client to return the
DiscoveryData
to the client application.
callback DiscoveryCallback = void (DiscoveryData
data);
DiscoveryCallback
Parametersdata
of type DiscoveryData
An ErrorCallback is used to return progress and error codes from asynchronous operations performed by the FIDO UAF Client.
callback ErrorCallback = void (ErrorCode
code);
ErrorCallback
Parameterscode
of type ErrorCode
ErrorCode
interface indicating the
result of the operation.For certain operations, an ErrorCallback may be called multiple
times, for example with the WAIT_USER_ACTION
code.
This section is non-normative.
Differences in the FIDO capabilities on a user device may (among many other characteristics) allow a server to "fingerprint" a remote client and attempt to persistently identify it, even in the absence of any explicit session state maintenance mechanism. Although it may contribute some amount of signal to servers attempting to fingerprint clients, the attributes exposed by the Discovery API are designed to have a large anonymity set size and should present little or no qualitatively new privacy risk. Nonetheless, an unusual configuration of FIDO Authenticators may be sufficient to uniquely identify a user.
It is recommended that user agents expose the Discovery API to all applications without requiring explicit user consent by default, but user agents or FIDO Client implementers should provide users with the means to opt-out of discovery if they wish to do so for privacy reasons.
This section is non-normative.
When FIDO UAF APIs are called and operations are performed in a
Document
context in a web user agent, such a context MUST NOT
contain insecure mixed content. The exact definition insecure
mixed content is specific to each user agent, but generally
includes any script, plugins and other "active" content,
forming part of or with access to the DOM, that was not itself
loaded over HTTPS.
The UAF APIs must immediately trigger the ErrorCallback
with the
INSECURE_TRANSPORT
code and cease any further processing if any
APIs defined in this document are invoked by a Document context
that was not loaded over a secure transport and/or which
contains insecure mixed content.
When retrieving or transporting UAF protocol messages over HTTP, it is important to maintain consistency among the web origin of the document context and the origin embedded in the UAF protocol message. Mismatches may cause the protocol to fail or enable attacks against the protocol. Therefore:
FIDO UAF messages should not be transported using methods that
opt-out of the Same Origin Policy [SOP], for example, using
<script src=”url”>
to non-same-origin
URLs or by setting the Access-Control-Allow-Origin
header
at the server.
When transporting FIDO UAF messages using XMLHttpRequest [XHR] the client should not follow redirects that are to URLs with a different origin than the requesting document.
FIDO UAF messages should not be exposed in HTTP responses where the
entire response body parses as valid ECMAScript. Resources
exposed in this manner may be subject to unauthorized
interactions by hostile applications hosted at untrusted
origins through cross-origin embedding using <script
src=”url”>
.
Web applications should not share FIDO UAF messages
across origins through channels such as postMessage()
[webmessaging].
This section is non-normative.
Web applications utilizing UAF depend on services from the web browser as a trusted platform. The APIs for web applications do not provide a means to assert an origin as an application identity for the purposes of FIDO operations as this will be provided to the FIDO UAF Client by the browser based on its privileged understanding of the actual origin context.
The browser must enforce that the web origin communicated to the FIDO UAF Client as the application identity is accurate
The browser must also enforce that resource instances containing insecure mixed-content cannot utilize the UAF DOM APIs.
This section is normative.
This section describes how an Android [ANDROID] client application can locate and communicate with a conforming FIDO Client installation operating on the host device.
As with web applications, a variety of integration patterns are possible on the Android platform. The API described here allows an app to communicate with a shared FIDO UAF Client on the user device in a loosely-coupled fashion using Android Intents.
FIDO UAF Clients running on Android versions prior to Android 5 MUST declare
the org.fidoalliance.uaf.permissions.FIDO_CLIENT
permission and they also MUST declare the related "uses-permission".
See the below example of this permission expressed in an Android app manifest file
<permission/>
and <uses-permission/>
element [AndroidAppManifest].
FIDO UAF Clients running on Android version 5 or later MUST NOT declare this permission and they also MUST NOT declare the related "uses-permission".
<permission android:name="org.fidoalliance.uaf.permissions.FIDO_CLIENT" android:label="Act as a FIDO Client." android:description="This application acts as a FIDO Client. It may access authentication devices available on the system, create and delete FIDO registrations on behalf of other applications." android:protectionLevel="dangerous" /> <uses-permission android:name="org.fidoalliance.uaf.permissions.FIDO_CLIENT"/>
Android applications requesting services from the FIDO UAF Client can do so under their own identity, or they can act as the user's agent by explicitly declaring an RFC6454 [RFC6454] serialization of the remote server's origin when invoking the FIDO UAF Client.
An application that is operating on behalf of a single entity
MUST NOT set an explicit origin. Omitting an explicit origin
will cause the FIDO UAF Client to determine the caller's identity as
android:apk-key-hash:<hash-of-public-key>
. The FIDO UAF Client will
then compare this with the list of authorized application facets
for the target AppID and proceed if it is listed as trusted.
See the UAF Protocol Specification [UAFProtocol] for more information on application and facet identifiers.
If the application is explicitly intended to operate as the user's agent in the context of an arbitrary number of remote applications (as when implementing a full web browser) it may set its origin to the RFC6454 [RFC6454] Unicode serialization of the remote application's Origin. The application MUST satisfy the necessary conditions described in Transport Security Requirements for authenticating the remote server before setting the origin.
Use of the origin parameter requires the application to declare
the org.fidoalliance.uaf.permissions.ACT_AS_WEB_BROWSER
permission, and the FIDO UAF Client MUST verify that the calling
application has this permission before processing the
operation.
<permission android:name="org.fidoalliance.uaf.permissions.ACT_AS_WEB_BROWSER" android:label="Act as a browser for FIDO registrations." android:description="This application may act as a web browser, creating new and accessing existing FIDO registrations for any domain." android:protectionLevel="dangerous" />
This section is non-normative.
In the DOM API, the browser or browser plugin is responsible for supplying any available channel binding information to the FIDO Client, but an Android application, as the direct owner of the transport channel, must provide this information itself.
The channelBindings
data structure is:
Map<String,String>
with the keys as defined for the ChannelBinding
structure in the UAF
Protocol Specification. [UAFProtocol]
The use of channel bindings for TLS helps assure the server that the channel over which UAF protocol messages are transported is the same channel the legitimate client is using and that messages have not been forwarded through a malicious party.
UAF defines support for the tls-unique
and
tls-server-end-point
bindings from [RFC5929], as well as
server certificate and ChannelID [ChannelID] bindings. The
client should supply all channel binding information available
to it.
Missing or invalid channel binding information may cause a relying party server to reject a transaction.
This enumeration describes the type of operation for the intent implementing the Android API.
UAF uses only a single intent to simplify behavior in the situation even where multiple FIDO clients may be installed. In such a case, the user will be prompted which of the installed FIDO UAF clients should be used to handle an implicit intent.
If the user selected to make different FIDO UAF Clients the default for different intents representing different phases, it could produce inconsistent results or fail to function at all.
If the application workflow requires
multiple calls to the client (and it usually does)
the application should read the componentName
from the intent extras it receives
from startActivityForResult()
and pass it to setComponent()
for subsequent intents to be sure they are
explicitly resolved to the same FIDO UAF Client.
enum UAFIntentType {
"DISCOVER",
"DISCOVER_RESULT",
"CHECK_POLICY",
"CHECK_POLICY_RESULT",
"UAF_OPERATION",
"UAF_OPERATION_RESULT",
"UAF_OPERATION_COMPLETION_STATUS"
};
Enumeration description | |
---|---|
DISCOVER | Discovery |
DISCOVER_RESULT | Discovery results |
CHECK_POLICY | Perform a no-op check if a message could be processed. |
CHECK_POLICY_RESULT | Check Policy results. |
UAF_OPERATION | Process a Registration, Authentication, Transaction Confirmation or Deregistration message. |
UAF_OPERATION_RESULT | UAF Operation results. |
UAF_OPERATION_COMPLETION_STATUS | Inform the FIDO UAF Client of the completion status of a Registration, Authentication, Transaction Confirmation or Deregistration message. |
All interactions between a FIDO UAF Client and an application on Android takes place via a single Android intent:
org.fidoalliance.intent.FIDO_OPERATION
The specifics of the operation are carried by the MIME media type and various extra data included with the intent.
The operations described in this document are of MIME media type
application/fido.uaf_client+json
and this MUST be set as the type
attribute of any intent.
Client applications can discover if a FIDO UAF Client (or several) is available
on the system by using
PackageManager.queryIntentActivities(Intent intent, int flags)
with this intent to see if any activities are available.
Extra | Type | Description |
---|---|---|
UAFIntentType |
String | One of the UAFIntentType enumeration values describing the intent. |
discoveryData |
String | DiscoveryData JSON dictionary. |
componentName |
String | The component name of the responding FIDO UAF Client. It must be serialized using ComponentName.flattenString() |
errorCode |
short | ErrorCode value for operation |
message |
String | UAFMessage request to test or process,
depending on UAFIntentType . |
origin |
String | An RFC6454 Web Origin [RFC6454]
string for the request, if the caller has
the org.fidoalliance.permissions.ACT_AS_WEB_BROWSER permission. |
channelBindings |
String | The JSON dictionary of channel bindings for the operation. |
responseCode |
short | The uafResult field of a ServerResponse . |
The following table shows what intent extras are expected, depending on the value of
the UAFIntentType
extra:
UAFIntentType value | discoveryData | componentName | errorCode | message | origin | channelBindings | responseCode |
---|---|---|---|---|---|---|---|
"DISCOVER" | |||||||
"DISCOVER_RESULT" | OPTIONAL | REQUIRED | REQUIRED | ||||
"CHECK_POLICY" | REQUIRED | OPTIONAL | |||||
"CHECK_POLICY_RESULT" | REQUIRED | REQUIRED | |||||
"UAF_OPERATION" | REQUIRED | OPTIONAL | REQUIRED | ||||
"UAF_OPERATION_RESULT" | REQUIRED | REQUIRED | OPTIONAL | ||||
"UAF_OPERATION_COMPLETION_STATUS" | REQUIRED | REQUIRED |
This Android intent invokes the FIDO UAF Client to discover the available authenticators and capabilities. The FIDO UAF Client generally will not show a UI associated with the handling of this intent, but immediately return the JSON structure. The calling application cannot depend on this however, as the FIDO UAF Client MAY show a UI for privacy purposes, allowing the user to choose whether and which authenticators to disclose to the calling application.
This intent MUST be invoked with startActivityForResult()
.
An intent with this type is returned by the FIDO UAF Client as an argument to onActivityResult()
in response to receiving an intent of type DISCOVER
.
If the resultCode
passed to onActivityResult()
is RESULT_OK
,
and the intent extra errorCode
is NO_ERROR,
this intent has an extra, discoveryData
, containing a String
representation of a DiscoveryData
JSON dictionary with the
available authenticators and capabilities.
This intent invokes the FIDO UAF Client to discover if it would be able to process the supplied message without prompting the user. The action handling this intent SHOULD NOT show a UI to the user.
This intent requires the following extras:
message
, containing a String
representation
of a UAFMessage
representing the request message to test.origin
, an OPTIONAL extra that allows a caller with the
org.fidoalliance.uaf.permissions.ACT_AS_WEB_BROWSER
permission
to supply an RFC6454 Origin [RFC6454] string to be used instead of the application's
own identity.This intent MUST be invoked with startActivityForResult()
.
This Android intent is returned by the FIDO UAF Client as an argument to onActivityResult()
in response to receiving a CHECK_POLICY
intent.
In addition to the resultCode
passed to onActivityResult()
,
this intent has an extra, errorCode
, containing an ErrorCode
value
indicating the specific error condition or NO_ERROR if the FIDO UAF Client could
process the message.
This Android intent invokes the FIDO UAF Client to process the supplied request message and return a response message ready for delivery to the FIDO UAF Server.
The sender SHOULD assume that the FIDO UAF Client will display a user interface allowing the user to handle this intent, for example, prompting the user to complete their verification ceremony.
This intent requires the following extras:
message
, containing a String
representation
of a UAFMessage
representing the request message to process.channelBindings
, containing a String
representation
of a JSON dictionary as defined by the ChannelBinding
structure in the
FIDO UAF Protocol Specification [UAFProtocol].origin
, an OPTIONAL parameter that allows a caller with the
org.fidoalliance.uaf.permissions.ACT_AS_WEB_BROWSER
permission
to supply an RFC6454 Origin [RFC6454] string to be used instead of the application's
own identity.This intent MUST be invoked with startActivityForResult()
.
This intent is returned by the FIDO UAF Client as an argument to onActivityResult()
,
in response to receiving a UAF_OPERATION
intent.
If the resultCode
passed to onActivityResult()
is RESULT_CANCELLED
,
this intent will have an extra, errorCode
parameter, containing an ErrorCode
value
indicating the specific error condition.
If the resultCode
passed to onActivityResult()
is RESULT_OK
,
and the errorCode
is NO_ERROR,
this intent has a message
, containing a String
representation of a UAFMessage
, being the UAF protocol response message
to be delivered to the FIDO Server.
This intent MUST be delivered to the FIDO UAF Client to indicate the processing status of a FIDO UAF message delivered to the remote server. This is especially important as a new registration may be considered by the client to be in a pending state until it is communicated that the server accepted it.
The Android Intent API can also be implemented using Android AIDL services as an alternative transport mechanism to Android Intents. While Android Intents work at the UI layer, Android AIDL services are performed at a lower level. This can ease integration with relying party apps, since UAF requests can be fulfilled without interfering with existing relying party app UI and application lifecycle behavior.
The UAF Android AIDL service needs to be defined in the UAF client manifest. This is done
using the <service>
tag for an Android AIDL service instead of the <activity>
tag
in Android Intents. Just as with Android intents, the manifest definition for the AIDL
service uses an intent filter (note org.fidoalliance.aidl.FIDO_OPERATION
versus org.fidoalliance.intent.FIDO_OPERATION
) to identify itself as a
FIDO UAF client to the relying party app:
<service android:name="foo" > <intent-filter> <action android:name="org.fidoalliance.aidl.FIDO_OPERATION" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/fido.uaf_client+json" /> </intent-filter> </service>
Once the relying party app chooses a UAF client from the list discovered by
PackageManager.queryIntentServices()
, the relying party app and
the FIDO UAF client share the following AIDL interface to service UAF requests:
package org.fidoalliance.aidl oneway interface IUAFOperation { void process(in Intent uafRequest, in IUAFResponseListener uafResponseListener); }
Android AIDL services use Binder.getCallingUid()
instead of Activity.getCallingActivity()
with Android Intents to
identify the caller and obtain FacetID information.
For consistency, the Intents for the Android AIDL service are the same as
defined in the Android Intent specification in the UAF standard.
In process()
, the uafRequest
parameter is the
Intent that would be passed to startActivityForResult()
. The
uafResponseListener
parameter is a listener interface that
receives the result. The following AIDL defines this interface:
package org.fidoalliance.aidl interface IUAFResponseListener { void onResult(in Intent uafResponse); }
In the listener, the uafResponse
parameter is the Intent
that would be passed to onActivityResult
.
This section is non-normative.
Android applications may choose to implement the user-interactive portion of FIDO in at least two ways:
addJavaScriptInterface()
.
An application that chooses to inject the UAF interface into a WebView MUST follow all appropriate security considerations that apply to usage of the DOM APIs, and those that apply to user agent implementers.
In particular, the content of a WebView into which an API will be injected MUST be loaded only from trusted local content or over a secure channel as specified in Transport Security Requirements and must not contain insecure mixed-content.
Applications SHOULD NOT declare the ACT_AS_WEB_BROWSER
permission
unless they need to act as the user's agent for an un-predetermined
number of third party applications. Where an Android application
has an explicit relationship with a relying party application(s),
the preferred method of access control is for those applications
to list the Android application's identity as a trusted facet. See the UAF
Protocol Specification [UAFProtocol] for more information on application and facet identifiers.
To protect against a malicious application registering itself as a FIDO UAF Client, relying party applications can obtain the identity of the responding application, and utilize it in risk management decisions around the authentication or transaction events.
For example, a relying party might maintain a list of application identities known to belong to malware and refuse to accept operations completed with such clients, or a list of application identities of known-good clients that receive preferred risk-scoring.
Relying party applications running on Android versions prior to Android 5 MUST make
sure that a FIDO UAF Client has
the "uses-permission" for org.fidoalliance.uaf.permissions.FIDO_CLIENT
. Relying party
applications running on Android 5 SHOULD NOT implement this check.
Relying party applications SHOULD implement the check on Android prior to 5 by using the
package manager to verify that the FIDO Client indeed
declared the org.fidoalliance.uaf.permissions.FIDO_CLIENT
permission (see example below).
Relying party applications SHOULD NOT use a "uses-permission" for FIDO_CLIENT
.
boolean checkFIDOClientPermission(String packageName) throws NameNotFoundException { for (String requestedPermission : getPackageManager().getPackageInfo(packageName, PackageManager.GET_PERMISSIONS).requestedPermissions) { if (requestedPermission.matches( "org.fidoalliance.uaf.permissions.FIDO_CLIENT")) return true; } return false; }
Relying party applications which use the AIDL service implementation of the UAF Client Intent API
MUST use an explicit intent to bind to the AIDL service. Failing to do so may result in binding to an
unexpected and possibly malicious service, because intent filter resolution depends on application
installation order and intent filter priority. Android 5.0 and later will throw a
SecurityException
if an implicit intent is used, but earlier versions do not enforce
this behavior.
This section is normative.
This section describes how an iOS relying party application can locate and communicate with a conforming FIDO UAF Client installed on the host device.
Because of sandboxing and no true multitasking support, the iOS operating system offers very limited ways to do interprocess communication (IPC).
Any IPC solution for a FIDO UAF Client must be able to:
Currently the only IPC method on iOS that satisfies both of these requirements is custom URL handlers.
Custom URL handlers use the iOS operating system to handle URL requests from the sender, launch the receiving app, and then pass the request to the receiving app for processing. By enabling custom URL handlers for two different applications, it is possible to achieve bidirectional IPC between them--one custom URL handler to send data from app A to app B and another custom URL handler to send data from app B to app A.
Because iOS has no true multitasking, there must be an app transition to process each request and response. Too many app transitions can negatively affect the user experience, so relying party applications must carefully choose when it is necessary to query the FIDO UAF Client.
When the relying party application communicates with the FIDO UAF Client, it sends a URL with the
standard x-callback-url
format (see x-callback-url.com):
FidoUAFClient1://x-callback-url/[UAFxRequestType]
?x-success=[RelyingPartyURL]
://x-callback-url/[UAFxResponseType]
& key=[SecretKey]
& state=[STATE]
& json=[Base64URLEncodedJSON]
FidoUAFClient1
is the iOS custom URL scheme used by FIDO UAF Clients. As specified
in the x-callback-url
standard, version information for the transport layer is encoded in
the URL scheme itself (in this case, FidoUAFClient1
). This is so other applications can check
for support for the 1.0 version by using the canOpenURL
call.
[UAFxRequestType]
is the type that should be used for request operations,
which are described later in this document.
[RelyingPartyURL]
is the URL that the relying party app has registered in order
to receive the response. According to the x-callback-url
standard, this is defined using the x-success
parameter.
[UAFxResponseType]
is the type that should be used for response operations,
which are described later in this document.
[SecretKey]
is a base64url-encoded, without padding, random key generated for each request by the calling application.
The response from the FIDO UAF Client will be encrypted with this key in order to prevent rogue applications from obtaining information by spoofing the return URL.
[STATE]
is data that can be used to match the request with the response.
[Base64URLEncodedJSON]
contains the message to be sent to the FIDO UAF Client.
Items are stored in JSON format and then base64url-encoded without padding.
For FIDO UAF Clients, the custom URL scheme handler entrypoint is the openURL() function:
Objective-C
(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
SWIFT
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { ... }
Here, the URL above is received via the url
parameter. For security considerations,
the sourceApplication
parameter contains the iOS bundle ID of the relying party application.
This bundle ID MUST be used to verify the application FacetID
.
Conversely, when the FIDO UAF Client responds to the request, it sends the following URL back
in standard x-callback-url
format:
[RelyingPartyURL]
://x-callback-url/[UAFxResponseType]
? state=[STATE]
& json=[Base64URLEncodedJWE]
The parameters in the response are similar to those of the request, except that the
[Base64URLEncodedEncryptedJSON]
parameter is encrypted with the public key before
being base64url-encoded without padding. [STATE]
is the same STATE
as was sent in the request--it is echoed
back to the sender to verify the matched response.
In the relying party application's openURL()
handler, the url
parameter will be the URL
listed above and the sourceApplication
parameter
will be the iOS bundle ID for the FIDO client application.
A new secret encryption key MUST be generated by the calling application every time it sends a request to FIDO UAF Client. The FIDO UAF Client MUST then use this key to encrypt the response message before responding to the caller.
JSON Web Encryption (JWE), JSON Serialization (JWE Section 7.2) format MUST be used to represent the encrypted response message.
The encryption algorithm is that specified in
"A128CBC-HS256"
where the JWE "Key Management Mode" employed is "Direct Encryption" and the JWE "Content Encryption Key (CEK)" is the secret key generated by the calling application and passed to the FIDO UAF Client in the key
parameter of the request.
{ "unprotected": {"alg": "dir", "enc": "A128CBC-HS256"}, "iv": "...", "ciphertext": "...", "tag": "..." }
iOS applications requesting services from the FIDO Client can do so under their own identity, or they can act as the user's agent by explicitly declaring an RFC6454 [RFC6454] serialization of the remote server's origin when invoking the FIDO UAF Client.
An application that is operating on behalf of a single entity
MUST NOT set an explicit origin. Omitting an explicit origin
will cause the FIDO UAF Client to determine the caller's identity as
"ios:bundle-id"
. The FIDO UAF Client will
then compare this with the list of authorized application facets
for the target AppID and proceed if it is listed as trusted.
See the UAF Protocol Specification [UAFProtocol] for more information on application and facet identifiers.
If the application is explicitly intended to operate as the user's agent in the context of an arbitrary number of remote applications (as when implementing a full web browser) it may set origin to the RFC6454 [RFC6454] Unicode serialization of the remote application's Origin. The application MUST satisfy the necessary conditions described in Transport Security Requirements for authenticating the remote server before setting origin.
This section is non-normative.
In the DOM API, the browser or browser plugin is responsible for supplying any available channel binding information to the FIDO Client, but an iOS application, as the direct owner of the transport channel, must provide this information itself.
The channelBindings data structure is Map<String,String>
with
the keys as defined for the ChannelBinding
structure in the FIDO UAF
Protocol Specification. [UAFProtocol]
The use of channel bindings for TLS helps assure the server that
the channel over which UAF protocol messages are transported is
the same channel the legitimate client is using and that
messages have not been forwarded through a malicious party. UAF
defines support for the tls-unique
and tls-server-end-point
bindings from [RFC5929], as well as server certificate and
ChannelID
[ChannelID] bindings. The client should supply all
channel binding information available to it.
Missing or invalid channel binding information may cause a relying party server to reject a transaction.
This value describes the type of operation for the x-callback-url
operations implementing the iOS API.
enum UAFxType {
"DISCOVER",
"DISCOVER_RESULT",
"CHECK_POLICY",
"CHECK_POLICY_RESULT",
"UAF_OPERATION",
"UAF_OPERATION_RESULT",
"UAF_OPERATION_COMPLETION_STATUS"
};
Enumeration description | |
---|---|
DISCOVER | Discovery |
DISCOVER_RESULT | Discovery results |
CHECK_POLICY | Perform a no-op check if a message could be processed. |
CHECK_POLICY_RESULT | Check Policy results. |
UAF_OPERATION | The UAF message operation type (for example Registration ). |
UAF_OPERATION_RESULT | UAF Operation results. |
UAF_OPERATION_COMPLETION_STATUS | Inform the FIDO UAF Client of
the completion status of a UAF operation (such as Registration . |
The specifics of the UAFxType operation are carried by various JSON values
encoded in the json
x-callback-url
parameter.
JSON value | Type | Description |
---|---|---|
discoveryData |
String | DiscoveryData JSON dictionary. |
errorCode |
short | ErrorCode value for operation |
message |
String | UAFMessage request to test or process, depending on UAFxType . |
origin |
String | An RFC6454 Web Origin [RFC6454] string for the request. |
channelBindings |
String | The channel bindings JSON dictionary for the operation. |
responseCode |
short | The uafResult field of a ServerResponse . |
The following table shows what JSON values are expected, depending on the
value of the UAFxType
x-callback-url
operation:
UAFxType operation | discoveryData | errorCode | message | origin | channelBindings | responseCode |
---|---|---|---|---|---|---|
"DISCOVER" | ||||||
"DISCOVER_RESULT" | OPTIONAL | REQUIRED | ||||
"CHECK_POLICY" | REQUIRED | OPTIONAL | ||||
"CHECK_POLICY_RESULT" | REQUIRED | |||||
"UAF_OPERATION" | REQUIRED | OPTIONAL | REQUIRED | |||
"UAF_OPERATION_RESULT" | REQUIRED | OPTIONAL | ||||
"UAF_OPERATION_COMPLETION_STATUS" | REQUIRED | REQUIRED |
This operation invokes the FIDO UAF Client to discover the available authenticators and capabilities. The FIDO UAF Client generally will not show a user interface associated with the handling of this operation, but will simply return the resulting JSON structure.
The calling application cannot depend on this however, as the client MAY show a user interface for privacy purposes, allowing the user to choose whether and which authenticators to disclose to the calling application.
iOS custom URL scheme handlers always require an application switch for every request and response, even if no user interface is displayed.
An operation with this type is returned by the FIDO UAF Client
in response to receiving an x-callback-url
operation of type DISCOVER
.
If x-callback-url JSON value errorCode
is NO_ERROR,
this x-callback-url operation has a JSON value, discoveryData
, containing a String
representation of a DiscoveryData
JSON dictionary listing the
available authenticators and their capabilities.
This operation invokes the FIDO UAF Client to discover if the client would be able to process the supplied message, without prompting the user.
The related Action
handling this
operation SHOULD NOT show an interface to the user.
iOS custom URL scheme handlers always require an application switch for every request and response, even if no UI is displayed.
This x-callback-url operation requires the following JSON values:
message
, containing a String
representation
of a UAFMessage
representing the request message to test.origin
, an OPTIONAL JSON value that allows a caller to supply
an RFC6454 Origin [RFC6454] string to be used instead of the application's
own identity.This operation is returned by the FIDO UAF Client in response to
receiving a CHECK_POLICY
x-callback-url operation.
The x-callback-url JSON value errorCode
containing an ErrorCode
value
indicating the specific error condition or NO_ERROR if the FIDO Client could
process the message.
This operation invokes the FIDO UAF Client to process the supplied request message and return a result message ready for delivery to the FIDO UAF Server. The sender SHOULD assume that the FIDO UAF Client will display a UI to the user to handle this x-callback-url operation, e.g. prompting the user to complete their verification ceremony.
This x-callback-url operation requires the following JSON values:
message
, containing a String
representation
of a UAFMessage
representing the request message to process.channelBindings
, containing a String
representation
of a JSON dictionary as defined by the ChannelBinding
structure in the
UAF Protocol Specification [UAFProtocol].origin
, an OPTIONAL JSON value that allows a caller
to supply an RFC6454 Origin [RFC6454] string to be used instead of the application's
own identity.This x-callback-url operation is returned by the FIDO UAF Client in
response to receiving a UAF_OPERATION
x-callback-url operation.
The x-callback-url JSON value errorCode
containing an ErrorCode
value
indicating the specific error condition.
If x-callback-url JSON value errorCode
is NO_ERROR,
this x-callback-url operation has a JSON value, message
, containing a String
representation of a UAFMessage
, being the UAF protocol response message to be
delivered to the FIDO Server.
This x-callback-url operation MUST be delivered to the FIDO UAF Client to indicate the completion status of a FIDO UAF message delivered to the remote server. This is especially important as, e.g. a new registration may be considered in a pending status until it is known the server accepted it.
This section is non-normative.
A security concern with custom URLs under iOS is that any app can register any custom URL. If multiple applications register the same custom URL, the behavior for handling the URL call in iOS is undefined.
On the FIDO UAF Client side, this issue with custom URL scheme handlers is solved by using the
sourceApplication
parameter which provides the bundle ID of the URL originator.
This is effective as long as the device has not been jailbroken and as long as Apple has done due diligence
vetting submissions to the app store for malware with faked bundle IDs.
The sourceApplication
parameter can be matched with the FacetID list to ensure that
the calling app is approved to use the credentials for the relying party.
On the relying party app side, encryption is used to prevent a rogue app from spoofing the relying party app's response URL. The relying party app generates a random encryption key on every request and sends it to the FIDO client. The FIDO client then encrypts the response to this key. In this manner, only the relying party app can decrypt the response. Even in the event that malware is able to spoof the relying party app's URL and intercept the response, it would not be able to decode it.
To protect against potentially malicious applications registering themselves to handle the FIDO UAF Client custom URL scheme, relying party Applications can obtain the bundle-id of the responding app and utilize it in risk management decisions around the authentication or transaction events. For example, a relying party might maintain a list of bundle-ids known to belong to malware and refuse to accept operations completed with such clients, or a list of bundle-ids of known-good clients that receive preferred risk-scoring.
This section is normative.
This section describes general normative security requirements for how a client application transports FIDO UAF protocol messages, gives specific requirements for Transport Layer Security (TLS), and describes an interoperability profile for using HTTP over TLS [RFC2818] with the FIDO UAF protocol.
This section is non-normative.
The UAF protocol contains no inherent means of identifying a relying party server, or for end-to-end protection of UAF protocol messages. To perform a secure UAF protocol exchange, the following abstract requirements apply:
This section is non-normative.
If using HTTP over TLS ([RFC2246] [RFC4346], [RFC5246] or [TLS13draft02]) to transport an UAF protocol exchange, the following specific requirements apply:
ChannelID
[ChannelID] public key, the tls-unique
and
tls-server-end-point
bindings [RFC5929], and TLS server
certificate binding [UAFProtocol]. This information provides
protection against certain classes of network attackers and the
forwarding of protocol messages, and a server may reject a
message that lacks or has channel binding data that does not
verify correctly.This section is normative.
Conforming applications MAY support this profile.
Complex and highly-optimized applications utilizing UAF will often transport UAF protocol messages in-line with other application protocol messages. The profile defined here for transporting UAF protocol messages over HTTPS is intended to:
Certain FIDO UAF operations, in particular, transaction confirmation, will always require an application-specific implementation. This interoperability profile only provides a skeleton framework suitable for replacing username/password authentication.
A UAF-enabled web application might typically deliver request messages as part of a response body containing other application content, e.g. in a script block as such:
... <script type=”application/json”> { “initialRequest”: { // initial request message here }, “lifetimeMillis”: 60000; // hint: this initial request is valid for 60 seconds } </script> ...
However, request messages have a limited lifetime, and an installed application cannot be delivered with a request, so client applications generally need the ability to retrieve a fresh request.
When sending a request message over HTTPS with XMLHttpRequest [XHR] or another HTTP API:
“application/fido+uaf; charset=utf-8”.
[RFC7231]“application/fido+uaf”
as a media type
in the HTTP “Accept” header [RFC7231]. Conforming servers MUST accept
“application/fido+uaf”
as media type.GetUAFRequest
dictionary.“application/fido+uaf; charset=utf-8”
ReturnUAFRequest
interface.Describes the operation type of a FIDO UAF message or request for a message.
enum Operation {
"Reg",
"Auth",
"Dereg"
};
Enumeration description | |
---|---|
Reg | Registration |
Auth | Authentication or Transaction Confirmation |
Dereg | Deregistration |
dictionary GetUAFRequest {
Operation
op;
DOMString previousRequest;
DOMString context;
};
GetUAFRequest
Membersop
of type Operation
previousRequest
of type DOMStringcontext
of type DOMStringdictionary ReturnUAFRequest {
required unsigned long statusCode;
DOMString uafRequest;
Operation
op;
long lifetimeMillis;
};
ReturnUAFRequest
MembersstatusCode
of type required unsigned longuafRequest
of type DOMStringop
of type Operation
lifetimeMillis
of type longuafRequest
, this is an OPTIONAL hint
informing the client application of the lifetime of the message
in milliseconds.dictionary SendUAFResponse {
required DOMString uafResponse;
DOMString context;
};
SendUAFResponse
MembersuafResponse
of type required DOMStringUAFMessage.uafProtocolMessage
returned by FIDO UAF Client.context
of type DOMStringAlthough it is not the only pattern possible, an asynchronous HTTP request is a useful way of delivering a UAF Response to the remote server for either web applications or standalone applications.
When delivering a response message over HTTPS with XMLHttpRequest [XHR] or another API:
“application/fido+uaf; charset=utf-8”
. [RFC7231]“application/fido+uaf”
as a media type
in the HTTP “Accept” header. [RFC7231]SendUAFResponse
.“application/fido+uaf; charset=utf-8”
and the body of the
response MUST consist entirely of a JSON structure described by
the ServerResponse
interface.The ServerResponse
interface represents the completion status
and additional application-specific additional data that
results from successful processing of a Register, Authenticate,
or Transaction Confirmation operation. This message is not
formally part of the UAF protocol, but the statusCode
should be
posted to the FIDO UAF Client, for housekeeping, using the
notifyUAFResult()
operation.
interface ServerResponse {
readonly attribute int statusCode;
[Optional]
readonly attribute DOMString description;
[Optional]
readonly attribute Token
[] additionalTokens;
[Optional]
readonly attribute DOMString location;
[Optional]
readonly attribute DOMString postData;
[Optional]
readonly attribute DOMString newUAFRequest;
};
statusCode
of type int, readonly description
of type DOMString, readonly additionalTokens
of type array of Token
, readonly location
.location
of type DOMString, readonly postData
of type DOMString, readonly location
, indicates that the
client should POST the contents to the specified location after
processing any tokens.newUAFRequest
of type DOMString, readonly The UAF Server is not responsible for creating additional tokens returned as part of a UAF response. Such tokens exist to provide a means for the relying party application to update the authentication/authorization state of the client in response to a successful UAF operation. For example, these fields could be used to allow UAF to serve as the initial authentication leg of a federation protocol, but the scope and details of any such federation are outside of the scope of UAF.
interface Token {
readonly attribute TokenType
type;
readonly attribute DOMString value;
};
type
of type TokenType
, readonly value
of type DOMString, readonly enum TokenType {
"HTTP_COOKIE",
"OAUTH",
"OAUTH2",
"SAML1_1",
"SAML2",
"JWT",
"OPENID_CONNECT"
};
Enumeration description | |
---|---|
HTTP_COOKIE | If the user agent is a standard web browser or other HTTP native client with a cookie store, this TokenType SHOULD NOT be used. Cookies should be set directly with the Set-Cookie HTTP header for processing by the user agent. For non-HTTP or non-browser contexts this indicates a token intended to be set as an HTTP cookie. [RFC6265] For example, a native VPN client that authenticates with UAF might use this TokenType to automatically add a cookie to the browser cookie jar. |
OAUTH | Indicates that the token is of type OAUTH. [RFC5849]. |
OAUTH2 | Indicates that the token is of type OAUTH2. [RFC6749]. |
SAML1_1 | Indicates that the token is of type SAML 1.1. [SAML11]. |
SAML2 | Indicates that the token is of type SAML 2.0. [SAML2-CORE] |
JWT | Indicates that the token is of type JSON Web Token (JWT). [JWT] |
OPENID_CONNECT | Indicates that the token is an OpenID Connect “id_token”. [OpenIDConnect] |
This section is non-normative.
It is important that the client set, and the server require, the
method be POST and the “Content-Type” HTTP header be the correct
values. Because the response body is valid ECMAScript, to
protect against unauthorized cross-origin access, a server must not
respond to the type of request that can be generated by a
script tag, e.g. <script
src=”https://example.com/fido/uaf/getRequest”>
. The request a
user agent generates with this kind of embedding cannot set
custom headers.
Likewise, by requiring a custom “Content-Type” header, cross-origin requests cannot be made with an XMLHttpRequest [XHR] without triggering a CORS preflight access check. [CORS]
As FIDO UAF messages are only valid when used same-origin, servers should not supply an “Access-Control-Allow-Origin” [CORS] header with responses that would allow them to be read by non-same-origin content.
To protect from some classes of cross-origin, browser-based, distributed denial-of-service attacks, request endpoints should ignore, without performing additional processing, all requests with an “Access-Control-Request-Method” [CORS] HTTP header or an incorrect “Content-Type” HTTP header.
If a server chooses to respond to requests made with the GET
method and without the custom “Content-Type” header, it should
apply a prefix string such as “while(1);
” or
“&&&BEGIN_UAF_RESPONSE&&&
” to the body of all replies and so
prevent their being read through cross-origin <script> tag
embedding. Legitimate same-origin callers will need to (and
alone be able to) strip this prefix string before parsing the
JSON content.