Authenticate for customer service

In certain customer service scenarios, users are required to authenticate in order to authorize agents to access their accounts and share potentially sensitive information, such as when users contact a call center for support or request service in a bank branch. Transmit recommends using Client-Initiated Backchannel Authentication (CIBA) for these scenarios.

Backchannel flow extends OpenID Connect by providing a decoupled authentication flow where a user doesn't directly interact with a device they want to access. The authentication request comes from a consumption device through a backchannel and then is completed on a different device, called an authentication device.

Example: a customer contacts a call center for support. To verify customer identity, the call center operator sends a link for a customer to authenticate themselves. Once the customer completes authentication, the operator logs in on their behalf.

How it works

Transmit supports the OIDC CIBA flow for authentication. The CIBA flow wraps around your regular Transmit-based authentication procedure such as email magic link, social login, or WebAuthn that runs on the user's device.

Before you can start integrating CIBA, review the flow prerequisites:

  • Users are already registered to the app. You cannot create new users using CIBA flow.
  • Users had their phone numbers or emails verified within Transmit.

Below is an example of the backchannel flow that can be implemented using the steps in this guide. Transmit APIs are shown in pink along with the relevant integration step, described below.

  1. A client (e.g., a call center) wants to authenticate a user on a consumption device and sends a backchannel authorization request to Transmit ( Step 3 ). Transmit sends an SMS or email with the auth link to the user. It also returns an acknowledgment that the auth link has been sent.
  2. The client backend starts polling for a token ( Step 4 ).
  3. When a user clicks the auth link, they are taken to the application login experience ( Step 1 ).
  4. After the user logs in, the application notifies Transmit that the process has been completed ( Step 1 ).
  5. With the next polling, the client that requested access receives a token ( Step 4 ) and is granted access.

Step 1: Create the login endpoint

Create the login endpoint that will perform the authentication process on the user's authenticating device and send a callback to Transmit.

  1. The endpoint should respond to GET requests and accept request_id and binding_message as query parameters. The request_id should be stored and then passed in a callback to complete the CIBA process while binding_message needs to be displayed to provide a user with more context.
  2. The endpoint should invoke the authentication process. Implement one of the Transmit-based authentication processes. See Authentication overview for available options.
  3. The endpoint needs to send a callback to Transmit whenever a user completes the authentication process. Implement code that sends a POST request to /auth/backchannel/complete . This call has to pass the request ID and define if the access is approved by the user.

Below is a sample request that notifies Transmit that the user has completed authentication. Replace placeholders with values before executing.


Authorize this request using the user access token returned upon authentication.

curl -i -X POST \
  '' \
  -H 'Authorization: Bearer USER_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "request_id": "REQUEST_ID",
    "approved": true

Step 2: Enable CIBA

In order to perform the backchannel flow, CIBA needs to be enabled for the application that initiates a backchannel authentication. To enable it, update your app by sending a PUT request to /applications/{appId}. The request should contain login_uri that you have already created in Step 1 and which will be later invoked on the user's authentication device. If you don't already have an application, you'll need to create one first (see Create application).

Below is a sample request that enables CIBA. Replace placeholders with values before executing.


Make sure you have a valid client access token to authorize the request. If not, you'll need to get one. Learn more

curl -i -X PUT \
  '{APP_ID}' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "ciba_authorization": {
      "enabled": true,
      "login_uri": "LOGIN_URI"

Step 3: Initiate CIBA flow

Implement the code that sends a POST request to /oidc/backchannel whenever a client wants to initiate a backchannel authentication. The request should include an identifier of the user that has been already registered within Transmit; new users cannot be created at this point. This request will trigger Transmit to send an auth link to the user. The link can either be sent by SMS (default) or by email.


Before choosing a delivery channel, check what user data is stored in Transmit. I.e., do users provide and verify phone numbers during registration? If you don't store user phone numbers, you won't be able to deliver SMS with auth links.

Below is a sample request that sends an auth link to the user's phone number. To learn how to send an auth link by email and explore a complete API reference, see Backchannel authentication request. Replace placeholders with values before executing.

curl -i -X POST \ \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d scope=openid \
  -d login_hint=PHONE_NUMBER\
  -d binding_message=MESSAGE \
Field Description
client_id Client ID. Can be obtained from your application settings in the Transmit Admin Portal.
client_secret Client secret. Can be obtained from your application settings in the Transmit Admin Portal.
login_hint An identifier of the user for whom authentication is requested: email, phone, or user_id.
binding_message (Optional) An explanatory message for a user that can be dispalyed on the authentication device and that is returned along with login_uri.

A successful response to the /oidc/backchannel endpoint returns the auth_req_id and expires_in parameters and acknowledges that the backchannel authentication flow has been initiated.

Step 4: Poll for a token

As soon as your client receives a response from /oidc/backchannel, you can start polling for the user token with at least 5 seconds between each request until the client receives it or until the backchannel authentication request expires. To poll for a token, implement a code that sends a POST request to /oidc/token with the same auth_req_id you received in the /oidc/backchannel response in Step 3.

Below is a sample request that polls for a token. Replace placeholders with values before executing.

curl -i -X POST \ \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d client_id=CLIENT_ID \
  -d client_secret=CLIENT_SECRET \
  -d auth_req_id=AUTH_REQ_ID \
  -d grant_type=urn:openid:params:grant-type:ciba

You can expect the following responses from Transmit and here is how to handle them:

Response Description Action
400 "authorization_pending" A user hasn't completed authentication yet Keep polling
400 "slow_down" The token is polled too frequently Increase polling interval, keep polling
400 "access_denied" A user denied access through a backchannel Stop polling
400 "expired_token" A user hasn't completed authentication within the backchannel request lifespan Stop polling
200 A user completed an authentication procedure and approved access Receive a token, stop polling