FCM (Firebase Cloud Messaging) Dispatcher
The FCM (Firebase Cloud Messaging) dispatcher supports out-of-band scenarios. Besides the Out-of-Band Services it relies on Google’s Firebase Cloud Messaging service. Thus, the FCM dispatcher is able to dispatch tokens and additional dispatch information to mobile devices using push messages.
As a prerequisite a Firebase project has to be created using a Google account.
The FCM Dispatcher plug-in needs the service account file of your Firebase project to cooperate with Cloud services. Carefully read the related documentation on how to generate and download the service account JSON file.
The service account JSON file contains sensitive information, including your service account’s private encryption key. Keep it confidential and never store it in a public repository.
The FCM dispatcher uses requires outbound access to several Google API services, specifically:
https://oauth2.googleapis.com
https://fcm.googleapis.com
https://accounts.google.com
https://www.googleapis.com
The FQDNs are also contained in the service account JSON file and are documented in the Google OpenID configuration metadata file.
In case proxies or company firewalls are in place, the connectivity to these Google services is to be ensured.
Configuration
Use the firebase-cloud-messaging dispatcher type in the Dispatchers Configuration to enable FCM dispatching.
The table below describes the possible configuration options.
Configuration Key | Mandatory | Type | Default value | Description |
---|---|---|---|---|
service-account-json | yes | String | - | Path to the valid FCM service account file to be used. |
dry-run | no | Boolean | false | Flag for testing the dispatch functionality without actually delivering the message to the target device. |
endpoint-base-url | no | String | fcm.googleapis.com | The base URL of the FCM Service endpoint. This URL could be used to configure a mock service for testing. |
proxy-url | no | String | - | The URL of the HTTP proxy required to access the FCM service. This URL is required if the FCM service is only accessible through a proxy. Example: https://proxy.siven.ch:3128 . |
registration-redeem-url | no | String | [nevisFIDO hostname]/nevisfido/token/redeem/registration | The URL that must be used to redeem the registration tokens. |
authentication-redeem-url | no | String | [nevisFIDO hostname]/nevisfido/token/redeem/authentication | The URL that must be used to redeem the authentication tokens. |
deregistration-redeem-url | no | String | [nevisFIDO hostname]/nevisfido/token/redeem/deregistration | The URL that must be used to redeem the deregistration tokens. |
FCM Dispatcher Configuration Options
Configuration Examples
The next example shows a typical production environment setup. Such a setup usually only contains the mandatory service-account-json configuration option:
dispatchers:
- type: firebase-cloud-messaging
service-account-json: /var/opt/nevisfido/default/conf/service-account.json
registration-redeem-url: https://siven.ch/nevisfido/token/redeem/registration
authentication-redeem-url: https://siven.ch/nevisfido/token/redeem/authentication
deregistration-redeem-url: https://siven.ch/nevisfido/token/redeem/deregistration
The next example shows a typical integration environment setup. In such a setup, the dry-run flag may be enabled to call Google’s FCM service, for example to test the connection. However, there are no push messages sent out to the target devices.
dispatchers:
- type: firebase-cloud-messaging
service-account-json: /var/opt/nevisfido/default/conf/service-account.json
dry-run: true
registration-redeem-url: https://integration.siven.ch/nevisfido/token/redeem/registration
authentication-redeem-url: https://integration.siven.ch/nevisfido/token/redeem/authentication
deregistration-redeem-url: https://integration.siven.ch/nevisfido/token/redeem/deregistration
The next example shows a typical developer environment setup. Such a setup may use an FCM mockup service instead of the real service, and overriding the default endpoint-base-url configuration value:
dispatchers:
- type: firebase-cloud-messaging
service-account-json: /var/opt/nevisfido/default/conf/service-account.json
endpoint-base-url: http://localhost:8080/mockfcm
registration-redeem-url: http://localhost:9080/nevisfido/token/redeem/registration
authentication-redeem-url: http://localhost:9080/nevisfido/token/redeem/authentication
deregistration-redeem-url: http://localhost:9080/nevisfido/token/redeem/deregistration
An FCM mock implementation is not provided by the nevisFIDO component.
Encryption
For encryption of tokens sent through the Firebase Cloud Messaging push service, the encryption algorithms used are currently fixed and cannot be configured. Note that the encryption keys can be administered using the Dispatch Target Service.
For encryption, both RSA and Elliptic Curve (EC) keys are supported. For each of those, the encryption algorithm used is the following:
- RSA: RSA-OAEP-256 algorithm (
RSAES using Optimal Asymmetric Encryption Padding with SHA-256 hash function
) with encryption method A256CBC_HS512 (AES_256_CBC_HMAC_SHA_512 authenticated encryption using a 512 bit
). - EC: ECDH-ES+A256KW
algorithm (
Elliptic Curve Diffie-Hellman Ephemeral Static key agreement, where the agreed-upon key is used to wrap the Content Encryption Key (CEK) with the A256KW function
) with encryption method A256CBC_HS512 (AES_256_CBC_HMAC_SHA_512 authenticated encryption using a 512 bit
).
Dispatch Target Format
In addition to configuring the FCM Dispatcher plug-in clients, register the dispatch targets with the HTTP API of the Dispatch Target Service. Configure the dispatch targets as follows:
- The registered dispatch targets must contain an
encryptionKey
. - Set the
target
attribute of the dispatch target to the firebase registration token of the client to which you want to dispatch the token. See the Message API of the Firebase HTTP API for details.
Dispatch Target Example
{
"name" : "My Mobile Phone",
"target" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P198aDPO",
"signatureKey" : {
"kty" : "RSA",
"x5t#S256" : "VdrYb5nzoOepus5UsKRwWPZyfUybt2ytv6lQq6e_Tyo",
"e" : "AQAB",
"use" : "sig",
"kid" : "10536191660674560031",
"x5c" : [ "MIICuzCCAaOgAwIBAgIJAJI4En4D8LAfMA0GCSqGSIb3DQEBCwUAMB0xCzAJBgNVBAYTAmNoMQ4wDAYDVQQDEwVzaXZlbjAeFw0yMjA3MjQxMzMwMzRaFw0yNDA3MjUxMzMwMzRaMB0xCzAJBgNVBAYTAmNoMQ4wDAYDVQQDEwVzaXZlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGRopz8pFVpFDDtOCUILU7tMC9DepNNk4p7YBpEBQ6FNPAq9sf1uz2Q5dRtn3jGJBLNx2d82QH/c+zxw2UHYVS/UKaYHB6VBCropoklG0U7vLqhPCM+FWFmjmu+kCt0S74iucSV34ddmMwyrEEM55hX9UgUNtWqcjReLHArcYBX2WmXLC2H6EIKdOQWsGC7dt3BZPwoygzaPOjeEw7INVZ4Ymym9qXcmWqUUPgmBf/9eWIc43EIyq90HCWEhxwz5ZnmLm7uKPnfbu9OhfdnakTfhRRK7vO27pQ4JKYok4IgvoFKm3N/y/wFHFPdBYmreZ1M8UdJA5AHy2Sig+CTV3sCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFzqFYxf2Wj4Nu1PrQ7etP9388IBZkJwYUxwpWg4Idv6+dLuheWd2aBQUzQYobkQ0fGSJo28WlAJ2drNfC+zI1/K1n8mcKGnjFDDOHay26X3EOOAFFsBm+dVDWzg/qfYgU2PM9L9dC/90FlD2ZriBF/ZF7wqz1IqOrSpgZhGIbLyDR5vOPxRdiWQDaDTY4lvhCa6bvliFJtiLkPIRonI4VOEiMmHIa59fZB9Xvx2+RmbCmGQAW+v+rZs4700AxYhPRu+wUK2BtFiFo/23vOYLaU9yk4XEXd3qya8CiP2C3e4rSu0MTr0RxWamI5f447BUQAbpgjgN5TOdD2Pu7iZ5Sg==" ],
"n" : "sZGinPykVWkUMO04JQgtTu0wL0N6k02TintgGkQFDoU08Cr2x_W7PZDl1G2feMYkEs3HZ3zZAf9z7PHDZQdhVL9QppgcHpUEKuimiSUbRTu8uqE8Iz4VYWaOa76QK3RLviK5xJXfh12YzDKsQQznmFf1SBQ21apyNF4scCtxgFfZaZcsLYfoQgp05BawYLt23cFk_CjKDNo86N4TDsg1VnhibKb2pdyZapRQ-CYF__15YhzjcQjKr3QcJYSHHDPlmeYubu4o-d9u706F92dqRN-FFEru87bulDgkpiiTgiC-gUqbc3_L_AUcU90Fiat5nUzxR0kDkAfLZKKD4JNXew"
},
"encryptionKey" : {
"kty" : "RSA",
"x5t#S256" : "URGQh2sd9ypwb2AZSNTFf711rRSDiuTnHw_HhSDB11A",
"e" : "AQAB",
"use" : "enc",
"kid" : "6997314261983703139",
"x5c" : [ "MIICujCCAaKgAwIBAgIIYRt0P3dQMGMwDQYJKoZIhvcNAQELBQAwHTELMAkGA1UEBhMCY2gxDjAMBgNVBAMTBXNpdmVuMB4XDTIyMDcyNDEzMzAzNFoXDTI0MDcyNTEzMzAzNFowHTELMAkGA1UEBhMCY2gxDjAMBgNVBAMTBXNpdmVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkzjtMhTSMY58vIZNocx53gGF3v9RQ3MYIa1kzqKSZPpzK8KwkHbo9yb6Wx5i0994G4HCSM9Ea6N4PKiwifRKfy4Ufznb7u/4e03w9QezQVUa6duXhjkwW5trJytoHp5F2Sc95hDTaPfPVlVC5DchjIL+p5Ay1K3lIe+RVPoVYN6CtsLTXJBAhBjtwKQHiKOq3UUbZLzOqMsrCcHXtw6gQHciWua8q4VloKO3sW4LHbeJD4cWy8IKwErtF8ShXo2vSRgeebivRXbA7OTAPEns6E0SoaMLeGdQ83dSHMQKIjY9teHua47Z9ovy5OZ1dXlDBmpKgO9FDiDK76lPYxvc5wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQA7d7tRXcRme1IoXSfIU0Co36NI4MjB5S37eFNj0ija85nzOrD7PkbaEjTv4pu1R1T2dES/qEXP5CEqarotx625/8sYddy8YRG7emKY47P7wzNJOAOOeAzPw/PR2tYDwdg3QKzG+id8IHeSYTNwMgEpcBM7GIBEwDG9YHRGkCqY46wBJ8H9uFvNGkdzI/VTLoZP4flCf992ImP6ZCUex6MciLwJ9Lq8L7f4wbfvlcy0KhFlAbLztrjstc9g+4e6FyR49ac9STpT/qyYIuyydaGOo01mf66Mncl33emjFLh32qELryOAzVqXiXgBuNSKGO0rFGUAMplnXewG/jP2YEy/" ],
"n" : "kzjtMhTSMY58vIZNocx53gGF3v9RQ3MYIa1kzqKSZPpzK8KwkHbo9yb6Wx5i0994G4HCSM9Ea6N4PKiwifRKfy4Ufznb7u_4e03w9QezQVUa6duXhjkwW5trJytoHp5F2Sc95hDTaPfPVlVC5DchjIL-p5Ay1K3lIe-RVPoVYN6CtsLTXJBAhBjtwKQHiKOq3UUbZLzOqMsrCcHXtw6gQHciWua8q4VloKO3sW4LHbeJD4cWy8IKwErtF8ShXo2vSRgeebivRXbA7OTAPEns6E0SoaMLeGdQ83dSHMQKIjY9teHua47Z9ovy5OZ1dXlDBmpKgO9FDiDK76lPYxvc5w"
},
"username" : "username",
"deviceId" : "Acme Inc Phone. Serial Number Hash: e14c2cec1f8c448a47874b5e164df11727a9e0ad"
}
Dispatch Token Request Format
Use the dispatchInformation
attribute of the Dispatch Token Service to specify information for the dispatcher. In case of the FCM Dispatcher, the client can provide the content of the notification
attribute that will be sent in the Message to the FCM infrastructure.
The client can also provide additional data in JSON format that will be encrypted and included in the push message. This is used for example to implement the Channel Linking.
Attribute | Type | Description | Optional |
---|---|---|---|
notification | Object | The contents of the notification that will be included in the notification attribute of the push message. If neither the title nor the body property is defined inside notification , or the dispatchInformation is not defined or it does not contain a notification attribute, then a Data Message will be sent out via FCM instead of a Notification Message. This might affect the behavior of the mobile client. For further details regarding the different message types, see the documentation About FCM messages. It is recommended that you always specify at least the notification title as an information for the end user. | true (but it is recommended to include it) |
data | Object | The additional data that will be encrypted into the nma_data attribute of the push message. This information will be sent inside the push message, so its size limitations apply here. | true |
Dispatch Token Request Example
{
"dispatchTargetId" : "0ea3abe9-c26c-4401-b5d5-2c1f4a4fd2eb",
"dispatcher" : "firebase-cloud-messaging",
"dispatchInformation" : {
"notification" : {
"title" : "Dirk Gently Bank - Confirm the payment"
},
"data" : {
"channelLinking" : {
"mode" : "visualString",
"content" : "AB"
}
}
},
"getUafRequest" : {
"context" : "{\"username\":\"jeff\"}",
"op" : "Auth"
}
}
The above example of a dispatch token request will generate a push message including a notification with the title "Dirk Gently Bank - Confirm the payment".
In addition to that, the specified information in the data
attribute (i.e the channelLinking
object) will be encrypted and sent with the token and the redeem URL in the nma_data
attribute of the push message. The data in the example corresponds to what is used in the context of Channel Linking.
Push Message Dispatching
When a dispatch token request arrives on the Dispatch Token Service interface, the FCM Dispatcher will compose and send a push message via the HTTP v1 API of FCM. For example the FCM Dispatcher will send the following message:
{
"validate_only" : false,
"message" : {
"token" : "98248c42-c9d5-4332-9b28-c3dc497df311",
"data" : {
"nma_data_version" : "1",
"nma_data_content_type" : "application/jose",
"nma_data" : "<the encrypted data>"
},
"notification" : {
"title" : "Dirk Gently Bank - Confirm the payment"
},
"android" : {
"priority" : "high"
},
"apns" : {
"headers" : {
"apns-priority" : "10"
},
"payload" : {
"aps" : {
"sound" : "default"
}
}
}
}
}
Push messages are always delivered with the highest priority to the devices. To achieve this the priority
is set to high
in the Android specific section of the message while for iOS devices the apns-priority
header is set to 10
for the same purpose. For further details check the related chapter
of the FCM documentation where additional platform specific documentations are also linked.
Currently the value at key nma_data_version
is always set to "1"
, and the value at key nma_data_content_type
is always set to "application/jose"
.
The data at key nma_data
contains a standard JWE using compact serialization with the following structure:
Attribute | Type | Description | Optional |
---|---|---|---|
token | String | The Nevis Mobile Authentication token. | false |
redeem_url | String | Nevis Mobile Authentication token redemption URL. | false |
In addition to the always present attributes above, the payload can contain optional JSON provided in the dispatch information of the request (see Dispatch Token Request Format).
The encrypted data payload in the example above is the following one:
{
"token" : "98248c42-c9d5-4332-9b28-c3dc497df311",
"redeem_url" : "https://fido.siven.ch/nevisfido/token/redeem/authentication",
"channelLinking" : {
"mode" : "visualString",
"content" : "AB"
}
}
For more information about how to receive and process incoming push messages on different target device platforms, refer to the Cloud Messaging documentation of FCM.
Push opt-out for users
The Nevis Access App allows end users to opt-out of receiving push messages. If a user decided to opt-out of receiving push messages, the fidouaf_target
attribute in the generic dispatch target credential in nevisIDM will contain the value user_disabled
.