CIBA (Backchannel Authentication)
Client Initiated Backchannel Authentication (CIBA) is an OpenID Connect extension that allows a client application to initiate authentication on behalf of a user without requiring the user to interact with the client directly. Instead, the user receives a notification (via SMS, email, or push) on a separate device and approves or denies the request there.
Common use cases:
- A call center agent authenticates a customer over the phone by triggering an approval on the customer’s mobile device
- A payment terminal requests approval from the account holder’s phone before processing a high-value transaction
- A desktop application delegates login to the user’s phone for a passwordless experience
- A backend service initiates step-up authentication when a sensitive operation is requested
How It Works
CIBA decouples the device where authentication is initiated from the device where the user provides consent:
- The client sends a backchannel authentication request to
/api/oauth/cibawith alogin_hint(email, phone number, or user ID) identifying the user - Auris validates the request and sends a notification to the user on their registered device or channel
- The user sees the request details (application name, binding message) and approves or denies
- The client receives the result via one of three modes: polling, ping (callback), or push
Notification Modes
Auris supports three modes for delivering the authentication result to the client:
| Mode | How It Works | Best For |
|---|---|---|
| Poll | Client polls the token endpoint at regular intervals until the user responds | Simple integrations, server-side clients |
| Ping | Auris sends a notification to a pre-registered callback URL, then the client exchanges the auth request ID for a token | Event-driven architectures |
| Push | Auris delivers the token directly to a pre-registered callback URL | Low-latency requirements |
Poll mode is the simplest to implement and is recommended for most use cases. Ping and push modes require a publicly accessible callback URL and proper webhook security.
Console Setup
Enable CIBA
In the Auris Console, go to Applications and select your application. Under the Settings tab, toggle Enable CIBA to on.
Configure Notification Mode
Select the notification mode (Poll, Ping, or Push). For Ping and Push modes, provide a Callback URL where Auris will send notifications.
Set Notification Channel
Choose how users receive the authentication request notification:
| Channel | Requirements |
|---|---|
| User must have a verified email address | |
| SMS | User must have a verified phone number. Requires SMS provider configuration (Twilio). |
| Push | Requires a custom push notification integration (advanced) |
Configure Request Lifetime
Set the maximum time a CIBA authentication request remains valid before expiring:
| Setting | Default | Notes |
|---|---|---|
| Request Lifetime | 300 seconds (5 minutes) | Maximum time the user has to approve or deny |
| Polling Interval | 5 seconds | Minimum interval for poll mode clients |
Copy Credentials
CIBA requires a confidential client. Copy the Client ID and Client Secret from the Credentials tab.
Implementation
JavaScript (Poll Mode)
const AURIS_DOMAIN = 'https://auth.yourdomain.com'
const CLIENT_ID = 'your-client-id'
const CLIENT_SECRET = 'your-client-secret'
// Step 1: Initiate backchannel authentication
const cibaResponse = await fetch(`${AURIS_DOMAIN}/api/oauth/ciba`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
},
body: new URLSearchParams({
scope: 'openid profile',
login_hint: '[email protected]',
binding_message: 'Approve login to Dashboard',
}),
}).then(r => r.json())
console.log('Auth request ID:', cibaResponse.auth_req_id)
console.log('User will receive a notification...')
// Step 2: Poll for the token
const token = await pollForCibaToken(cibaResponse)
async function pollForCibaToken(cibaResponse) {
const interval = cibaResponse.interval * 1000
const expiresAt = Date.now() + cibaResponse.expires_in * 1000
while (Date.now() < expiresAt) {
await new Promise(resolve => setTimeout(resolve, interval))
const response = await fetch(`${AURIS_DOMAIN}/api/auth/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
},
body: new URLSearchParams({
grant_type: 'urn:openid:params:grant-type:ciba',
auth_req_id: cibaResponse.auth_req_id,
}),
})
if (response.ok) {
return await response.json()
}
const error = await response.json()
if (error.error === 'authorization_pending') continue
if (error.error === 'slow_down') {
await new Promise(r => setTimeout(r, 5000))
continue
}
if (error.error === 'expired_token') {
throw new Error('CIBA request expired. User did not respond in time.')
}
if (error.error === 'access_denied') {
throw new Error('User denied the authentication request.')
}
throw new Error(`CIBA error: ${error.error}`)
}
throw new Error('CIBA request timed out.')
}CIBA Request Parameters
The backchannel authentication request accepts the following parameters:
| Parameter | Required | Description |
|---|---|---|
scope | Yes | OpenID Connect scopes (must include openid) |
login_hint | Yes | Identifies the user. Can be an email address, phone number, or user ID. |
binding_message | No | Short message displayed to the user on the approval screen (e.g., “Approve login to Dashboard”). Max 128 characters. |
requested_expiry | No | Requested lifetime of the authentication request in seconds. Capped by the application configuration. |
acr_values | No | Requested Authentication Context Class Reference values for step-up auth |
The Binding Message
The binding_message is a critical security feature. It is displayed to the user on the approval notification and should contain enough context for the user to confirm what they are approving:
- “Approve login to Dashboard” (login)
- “Confirm payment of EUR 49.99 to ACME Corp” (payment approval)
- “Authorize support agent to access your account” (call center)
Always include a meaningful binding message. Without it, users cannot distinguish a legitimate CIBA request from a phishing attempt. The binding message should be specific to the current action — never use a generic “Approve login” message for payment or sensitive operations.
Error Handling
| Error Code | HTTP Status | Meaning |
|---|---|---|
authorization_pending | 400 | User has not yet responded to the notification |
slow_down | 400 | Client is polling too fast |
expired_token | 400 | Auth request has expired (user did not respond) |
access_denied | 400 | User explicitly denied the request |
invalid_request | 400 | Missing or invalid parameters |
unknown_user_id | 400 | The login_hint does not match any known user |
unauthorized_client | 401 | Client is not authorized for CIBA |
Security Considerations
- Confidential client required: CIBA always requires client authentication (client ID + secret). Public clients cannot use CIBA.
- Short request lifetime: Default 300 seconds. Shorter lifetimes reduce the window for social engineering attacks.
- User consent required: The user must explicitly approve the request. Auris never auto-approves.
- Binding message display: The approval UI always shows the binding message, application name, and requested scopes.
- Notification channel verification: Auris only sends CIBA notifications to verified email addresses or phone numbers.
- Audit logging: All CIBA requests (initiated, approved, denied, expired) are logged for audit purposes.
API Endpoints
/api/oauth/cibaInitiate a backchannel authentication request. Requires client authentication (Basic auth or client_id/client_secret in body). Returns auth_req_id, expires_in, and interval.
/api/auth/tokenToken endpoint. For CIBA, set grant_type=urn:openid:params:grant-type:ciba and auth_req_id. Returns access token on user approval, or a polling error code.
/api/oauth/ciba/requestsRequires: view:ciba_requestsList active CIBA authentication requests for the tenant. Admin endpoint for monitoring.
Required Permissions
| Operation | Permission |
|---|---|
| Enable CIBA on an application | manage:applications |
| Configure CIBA settings | manage:ciba_config |
| List active CIBA requests | view:ciba_requests |
| Initiate/poll for token | Client authentication only (no user permission) |
Related Guides
- Device Authorization Flow — Similar decoupled flow for input-constrained devices
- Hosted Login (PKCE) — Standard browser-based authentication
- Multi-Factor Authentication — CIBA can integrate with MFA for step-up auth