Authentication Message - ** DEPRECATED **

Note

A new, upgraded Authentication message type is now available in iOS 16 and macOS 13. Be sure to review it in New Authentication Message Specification. All MSPs are required to support this new type beginning Fall 2022.

Pass a customer's authentication data to a business by using the OAuth protocol. Messages for Business allows authentication data to pass between customers and businesses on the Messaging Service Provider (MSP) using the authenticate endpoint as described in Sending an Authentication Message.

After the user is authorized, the system sends an OAuth response and the user’s device receives a login form. The user enters their username and password in the login form to continue the authorization process.

A screenshot of a login form, as displayed on iPhone.
A login form

Sending an Authentication Message

Pass authentication data between the business or Customer Service Platform and the customer's device using OAuth.

URL

POST https://mspgw.push.apple.com/v1/authenticate

HTTP Headers

For more information, see the HTTP Headers in Common Specifications.

HTTP Body

In iOS 15, Apple enhanced the authentication method built into Messages for Business. Prior to iOS 15, the authorization code and parameters appeared in the URI request.

Pre-iOS 15 example: server.example.com/?grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

Starting in iOS 15, the authorization code and parameters appear in the HTTP entity-body according to the standard for OAuth 2.0.

Name Description
AuthenticateRequestBody Content-Type: application/json

Response Codes

You can find the list of Response Codes in Common Specifications.

Businesses must supply authentication details about the OAuth provider, including authentication endpoint URLs, client identifier, and business information verified by Apple Business Register. Changing any of these authentication parameters requires additional verification and approval from multiple customers that own or administer the business.

Pass Authenticate Data

Passing authenticate data requires sending a POST request to the /v1/authenticateendpoint hosted by Messages for Business with the authenticate message in the request body. You must secure the authenticate endpoint before sending a request from a business to the customer. When the OAuth request is sent to the provider, the endpoints must present a valid Extended Validation (EV) certificate for a successful authorization.

You use the AuthenticateRequestBody.Authenticate dictionary key and the responseEncryptionKey to authenticate with the OAuth provider endpoints. This workflow enables the OAuth provider to audit the public key used to encrypt the authentication token. Use the requestIdentifier in the data dictionary to identify the authentication request and map the OAuth token in the response to the request originator. Either the business or the MSP generates the requestIdentifier and responseEncryptionKey.

Messages for Business returns a JSON dictionary containing the encrypted token field. The business or CSP can decrypt the access token and verify the user's access. If the business is responsible for decrypting the access token, the business and MSP must implement the delegation of key generation and token verification. The tall, rectangular boxes on the vertical lines in the figure below denotes key generation and access token verification.

A diagram showing the authentication flow and data as it is passed between a business/MSP and a user's device.
Authentication flow between a MSP and a user's device

Validate the Public Key

Messages for Business authentication uses OAuth to provide a way for the authentication provider and the business to audit the public key sent in a user's authentication request. The audit detects when a public key has been tampered with or replaced, which could result in the customer's authentication token leaking to an unintended party.

When a user's device makes the HTTPS call to the authorization endpoint, it includes two additional request parameters in addition to the standard authentication request: responseEncryptionKey and userHandle. The authentication provider can make an API call to the business with the responseEncryptionKey and the user's opaque ID.

If the business is acting as its own authentication provider, it checks these values against its internal database. If the business made a request with that customer's key, the authentication provider proceeds by sending back the code or access token. If the customer's key does not match the parameter values in its pending requests, the customer's key may have been tampered with and the authentication provider must immediately fail the request from the device.

Note

You can also work with your authentication provider on proper validation of the public key.

Compose an Authentication Request

The authenticate request is an interactive message. When composing an authenticate request, include the AuthenticateRequestBody.Authenticate dictionary key in the BaseInteractiveMessage dictionary to describe the behavior and content of the authentication request.

You can send authentication data to a customer’s device with the auth capability announced, which is included in the capability-list header of the message request. Devices that support authenticate messages have iOS 12 or later and macOS 10.14.0 or later. For more information about the Authorization header field, see Authorizing Messages.

Successful Authentication

Example of an authentication request. Note that the clientSecret key is forwarded to the authentication provider as client_secret.

Request
{
    "type": "interactive",
    "interactiveData": {
        "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
        "data": {
            "version": "1.0",
            "requestIdentifier": "3EF748B5-<truncated>",
            "authenticate": {
                "oauth2": {
                    "responseType": "code",
                    "scope": ["email", "profile"],
                    "state": "security_token",
                    "responseEncryptionKey": "BFz948MTG3OQ0Q69 <truncated>",
                    "clientSecret": "client_secret"
                }
            },
            "images": [{
                "data": "iVBORw0KGgoAAAANSUhEUgAA <truncated>",
                "identifier": "1"
            }]
        },
        "receivedMessage": {
            "title": "Sign In",
            "imageIdentifier": "1"
        },
        "replyMessage": {
            "title": "You Signed In",
            "imageIdentifier": "1"
        }
    }
}
Response
{
    "data": {
        "version": "1.0",
        "requestIdentifier": "8EF748B5-<truncated>",
        "authenticate": {
            "status":"authenticated",
            "token": "<An encrypted Base64-encoded token.>"
        },
        "images": [{
                   "data": "iVBORw0KGgoAAAANSUhEUgAAADIA <truncated>",
                   "identifier": "1"
                   }]
    },
    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
    "receivedMessage": {
        "title": "Sign In",
        "subtitle": "Authentication required to access your customer data",
        "style": "icon",
        "imageIdentifier": "1"
    },
    "replyMessage": {
        "title": "You Signed In",
        "subtitle": "",
        "style": "icon",
        "imageIdentifier": "1"
    }
}

Failed Authentication

Request
{
    "type": "interactive",
    "interactiveData": {
        "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
        "data": {
            "version": "1.0",
            "requestIdentifier": "3EF748B5-<truncated>",
            "authenticate": {
                "oauth2": {
                    "responseType": "code",
                    "scope": ["email", "profile"],
                    "state": "security_token",
                    "responseEncryptionKey": "BFz948MTG3OQ0Q69JHUiBG7 <truncated>",
                    "clientSecret": "client_secret"
                }
            },
            "images": [{
                "data": "iVBORw0KGgoAAAANSUhEUgA <truncated>",
                "identifier": "1"
            }]
        },
        "receivedMessage": {
            "title": "Sign In",
            "imageIdentifier": "1"
        }
    }
}
Response
{
    "data": {
        "version": "1.0",
        "requestIdentifier": "8EF748B5-<truncated>",
        "authenticate": {
            "status": "failed",
            "errors": [{
                "code": 2,
                "domain": "com.apple.icloud.messages.business.cryptor",
                "message": "Key is not UTF8"
            }]
        },
        "images": [{
            "data": "iVBORw0KGgoAAAANSUhEUgAA <truncated>",
            "identifier": "1"
        }]
    },
    "bid": "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.icloud.apps.messages.business.extension",
    "receivedMessage": {
        "title": "Sign In",
        "subtitle": "Authentication required to access your customer data",
        "style": "icon",
        "imageIdentifier": "1"
    },
    "replyMessage": {
        "title": "Authentication Failed",
        "subtitle": "",
        "style": "icon",
        "imageIdentifier": "1"
    }
}

AuthenticateRequestBody Dictionary

InteractiveMessageData dictionary with the authenticate key added used in sending an authentication message.

Properties

Name Type Description
authenticate object REQUIRED. A dictionary that describes the authentication request.
images array REQUIRED. An array of image dictionaries
requestIdentifier string REQUIRED. An identifier for the authenticate request.
version string REQUIRED. A numerical version number of the message extension schema.

AuthenticateRequestBody.Authenticate Dictionary

Keys for the Authenticate Data dictionary used in sending an authentication message.

Properties

Name Type Description
oauth2 object REQUIRED. A dictionary that describes the authentication request.

AuthenticateRequestBody.Authenticate.Oauth2 Dictionary

Keys for the OAuth2 Data dictionary used in sending an authentication message.

Properties

Name Type Description
clientSecret string REQUIRED. A string indicating the secret provisioned by the authorization server.
responseEncryptionKey byte REQUIRED. A string indicating the Base64-encoded public key that encrypts the access token returned in the response.
responseType string REQUIRED. A string indicating the type of authentication request.
scope array REQUIRED. An array of scope items that specifies the scope of the request.This dictionary entry gives the exact fields of data that the authentication service provides to the client requesting the authentication.
state string REQUIRED. A string indicating the state of the authentication request.

AuthenticateRequestBody.Authenticate.Oauth2.Scope Dictionary

An array of short text fields that describes the granted access for read and write. This dictionary entry gives the exact fields of data that the authentication service provides to the client requesting the authentication.

object AuthenticateRequestBody.Authenticate.Oauth2.Scope

Authenticate Webhook Event

Webhook Payload

Keys used in the JSON dictionary which is the response body.

Name Type Description
errors object A list of errors for authentication failure cases. See Error Codes.
status string A string indicating the status of the authentication request.
token string A Base64-encoded authentication token string, which is encrypted with the responseEncryptionKey from the request when authentication is successful.

Errors

Name Type Description
code integer A numerical error code. See Error Codes.
domain string A string indicating the error domain.
message string A string indicating the description of the error.

Decrypting the Authentication Token

To authenticate users, you need to decrypt their encrypted authentication token from the response. The authentication token should include the following:

  • A 384-bit elliptic curve secp384r1 public key specified in the authenticate request.
  • An encrypted authentication token, for use by the Messaging Service Provider (MSP) platform. You can create the token on the customer's device using the eciesEncryptionCofactorVariableIVX963SHA256AESGCM algorithm.

The business or MSP platform uses the associated private key generated for the request to decrypt and obtain the clear text authentication token.

For more information on authentication, see Sending an Authentication Message.

About the Authentication Token

When a customer successfully completes authenticating with a business, the MSP platform receives an authentication token. This token includes encrypted information and requires a decryption procedure to retrieve the information to determine the authenticity of the customer.

The authentication token is a Base64-encoded string contained in the JSON payload returned by the interactive message from the Messages for Business server. You can find it nested in the interactiveData/data/authenticate/token folder.

The authentication token uses the Elliptic Curve Integrated Encryption Scheme (ECIES). There are several versions for ECIES and keys, and encrypted data are not always compatible between versions. Some applications use a derivative or a subset of a version, so they may not be compatible with other implementations.

Messages for Business uses the secp384r1 curve for generating public/private key pairs, and X9.63 for encoding the public keys. Libraries compatible with these standards are available across many languages and platforms.

Before developing the production code for your implementation, you should understand the concepts of encryption and be familiar with the libraries to handle these items on your platform. Some libraries have an abstract cryptographic library that requires deep understanding to apply the correct algorithm and parameters. Other libraries implement many methods and are fairly straightforward to use, but require a great deal of research to determine a suitable method for a particular application. Understand these concepts before you begin your production code.

You should validate the compatibility of your particular implementation with the standards by building a comprehensive test. You should also review your implementation with information security experts. It is recommended to perform a security review with an independent security team before deployment.

Decrypt the Authentication Token

In this decryption exercise, you use a Base64-encoded binary data and an X9.63-encoded uncompressed public key. The unsigned scalar private key example has been converted to bytes. The private key is not sent in the request, so businesses can choose any encoding format.

Use the following values so that you can follow along with the exercises. You can use the immediate mode on your favorite language or write sample code on your platform.

  • Public Key

    BNY+I93aHVkXnNWKVLdrMJLXpQ1BsyHYoiv6UNi4rDUsRx3sNNhW8FNy9yUwxYprAwwfj1ZkoJ61Fs+SwjIbGPtXi52arvSbPglyBN4uAxtP3VP3LCP4JtSEjdgsgsretA==

  • Private Key

    pX/BvdXXUdpC79mW/jWi10Z6PJb5SBY2+aqkR/qYOjqgakKsqZFKnl0kz10Ve+BP

  • Encrypted Authentication Token

    BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSmnxUuxrpKxopWnOgyhzUx+mBUTao0pcEgqZFw0Y/qZIJPf1KusCMlz5TAhpjsw=

To decrypt the authentication token, use the following steps:

  1. Extract the ephemeral public key from the encrypted data.
  2. Derive the public numbers from the ephemeral public key.
  3. Obtain a shared key using an Elliptic Curve Cyrptopgraphy Cofactor Diffie-Hellman (ECC CDH).
  4. Generate the derived key and initial vector by running the shared key through the X9.63 Key Derivation Function with SHA256 hash function.
  5. Perform an AES-GCM decryption using the encrypted data string and initialization vector (IV) obtained in step 4.

The following sections take you through the process of decrypting the authentication token, as detailed in the previous steps.

Extract and Confirm the Ephemeral Public Key

Extract the ephemeral public key from the encrypted data. The authentication token contains several parts:

  • Byte 0 is 0x04 and indicates an uncompressed key form.
  • Bytes 0...96 are the ephemeral public key. Note that 0-byte is part of the ephemeral public key in addition to indicating the uncompressed form.
  • Bytes 97...n-16 are the encrypted data, where n is the length of the authentication token.
  • Bytes n-15...n-1 are the encryption tag.

When you compute the key on the secp384r1 curve, the key data is 96 bytes (384/8 * 2). The x and y coordinates can have up to 384-bytes.

Exercise

First, Base64-decode the authentication token string. This results in a 142-byte binary which is the actual authentication token. The first byte, 0x04, indicates the key in an uncompressed form.

Use the Base64 library and binary object manipulation library for your language and platform. Base64-encode the ephemeral public key from the binary form. The following uncompressed ephemeral key should result:

  • BDiRKNnPiPUb5oala31nkmCaXMB0iyWy3Q93p6fN7vPxEQSUlFVsInkJzPBBqmW1FUIY1KBA3BQb3W3Qv4akZ8kblqbmvupE/EJzPKbROZFBNvxpvVOHHgO2qadmHAjHSg==

Derive the binary for the encrypted data portion and Base64-encode it. The resulting encrypted data string is:

  • afFS7GukrGilac6DKHNTH6YFRNqjSlwSCpkXDRj+

The Base64-encoded encryption tag is:

  • pkgk9/Uq6wIyXPlMCGmOzA==

Save the encrypted data string and tag as these are used in Perform an AES-GCM Decryption.

Derive the Public Numbers

Derive the public numbers from the public key. The public numbers are the x and y coordinates of the elliptic curve used in the encryption process. Use a method within the cryptographic library on your platform to derive these values.

Some libraries pass the secp384r1 curve to the routine as a parameter along with the public key. Other libraries have a method for the secp384r1 that accepts the public key as a parameter. Familiarize yourself with the cryptographic library and apply the best method to this step.

Exercise

Pass the secp384r1 curve and the ephemeral public key into your cryptography library method for deriving the public numbers.

Continuing from the values in the previous section, you should receive the following two coordinates:

  • x=8706462696031173094919866327685737145866436939551712382591956952075131891462487598200779332295613073905587629438229
  • y=10173258529327482491525749925661342501140613951412040971418641469645769857676705559747557238888921287857458976966474

Obtain the Shared Key Using the ECC CDH

To obtain the shared key, perform an ECC CDH operation using the ephemeral public key and the private key. You should get the following shared key after using the ECC CDH operation:

  • 2lvSJsBO2keUHRfvPG6C1RMUmGpuDbdgNrZ9YD7RYnvAcfgq/fjeYr1p0hWABeif

Generate the Derived Key and Initial Vector

Run the shared key through the X9.63 Key Derivation Function with SHA256 hash function. This results in a 48-byte payload.

Use the initialization vector to perform the decryption in Perform an AES-GCM Decryption.

The first 32-bytes yields the derived key, for this exercise:

  • mAzkYatDlz4SzrCyM23NhgL/+mE3eGgfUz9h1CFPhZM=

The last 16-bytes serve as the IV:

  • rV3qrszd0PMPgeRhNnlOYA==

Perform an AES-GCM Decryption

Refer back to the saved values from the first step, Extract and Confirm the Ephemeral Public Key. Use the following encrypted data string:

  • afFS7GukrGilac6DKHNTH6YFRNqjSlwSCpkXDRj+

and the IV from Generate the Derived Key and Initial Vector:

  • rV3qrszd0PMPgeRhNnlOYA==

to perform a message authentication code (MAC) validation, include the encryption tag from Extract and Confirm the Ephemeral Public Key:

  • pkgk9/Uq6wIyXPlMCGmOzA==

This yields a plain text string token that you can use for authentication:

  • xXTi32iZwrQ6O8Sy6r1isKwF6Ff1Py

Troubleshooting

Decryption fails if the keys or associated tag derived in Generate the Derived Key and Initial Vector are incorrect. Failed decryptions result in rejected tokens, including the associated tag validation.

Using Password AutoFill to Authenticate Users

Provide customers with an easy solution to perfom authentication on their iOS devices.

Supporting the Password AutoFill feature requires that the authorization input element must annotate the autocomplete HTML attribute in the following format:

<input autocomplete="value">

Possible values for the autocomplete attribute are username, current-password, new-password, and one-time code. For more information about these values, see Enabling Password AutoFill on an HTML Input Element.

Note

Password AutoFill is supported in Safari 12 for iOS 12 and later and Safari 12 for macOS 10.14 and later.

After the customer has been authorized, the system sends an OAuth response. In this step, the customer’s device is redirected to a URL that triggers a login form using an existing third party login system. For more information, see Password AutoFill.

Error Codes

Possible errors thrown by the customer's device.

The device may return various errors as listed in the following tables. All errors in the tables are from the com.apple.icloud.messages.business domain.

Table 1 Authentication domain errors

Error Code Message Description
BCTokenMissingError 1 Missing Token or Missing Code. Thrown when the authentication plugin cannot retrieve a token or a code from the redirect URL.
BCEmptyDataReceivedError 2 Empty data received when exchanging token. Thrown when the authentication plugin receives an empty response when exchanging the code for a token.
BCAccessTokenMissingFromResponseError 3 Missing access token from response. Thrown when the authentication plugin receives a valid response, but the response is missing access_token from the JSON body.

Table 2 Cryptor domain errors

Error Code Message Description
BCPublicKeyIsEmptyError 1 Empty string received for key. Thrown when the cryptor is given an empty public key.
BCPublicKeyIsNotUTF8Error 2 Key is not UTF-8. Thrown when the cryptor Base64-decodes the public key and fails because the encoding is not UTF-8.
BCPublicKeyIsInvalidError 3 Public key is invalid. Thrown when the cryptor fails to validate the key against SecKeyAlgorith.eciesEnCryptionCofactorVariableVX963SHA256AESGCM.
BCPublicKeyInternalError 3 Failed adding key.Failed reading key.Failed deleting key. Thrown when the cryptor cannot complete the given task due to an internal error.
BCEncryptionError 4 Unable to encrypt token. Thrown when the cryptor fails to encrypt a given payload using the provided public key.

Tutorial Exercise

For more help or guidance, see our Tutorial: Exercise: Sending an Authentication Message.