IUserDeviceAuthenticationHandler Interface
Abblix.Oidc.Server
Abblix.Oidc.Server.Features.BackChannelAuthentication.Interfaces
IUserDeviceAuthenticationHandler Interface
Defines the contract for initiating user authentication on a device in the context of a backchannel authentication flow. This interface is responsible for handling the initiation of the authentication process for the end-user on their device, based on a validated backchannel authentication request.
public interface IUserDeviceAuthenticationHandler
Remarks
Implementation Guide:Implement this interface to integrate your authentication mechanism with CIBA. Your implementation should:
- Send authentication request to user's device (push notification, SMS, email, etc.)
- Display binding_message if present in the request
- Handle user approval/denial asynchronously
- Update authentication status when user responds
public class MyUserDeviceAuthenticationHandler : IUserDeviceAuthenticationHandler
{
private readonly IBackChannelAuthenticationStorage _storage;
private readonly IBackChannelDeliveryModeRouter _notifier;
private readonly ISessionIdGenerator _sessionIdGenerator;
private readonly IMyPushNotificationService _pushService;
public async Task<Result<AuthSession, OidcError>> InitiateAuthenticationAsync(
ValidBackChannelAuthenticationRequest request)
{
// Extract user hint and send authentication request to their device
var userIdentifier = ExtractUserIdentifier(request);
var bindingMessage = request.Model.BindingMessage;
// Send push notification to user's device
await _pushService.SendAuthRequestAsync(userIdentifier, bindingMessage);
// Return pending - authentication completes asynchronously
// User will approve/deny on their device
return new OidcError(ErrorCodes.AuthorizationPending, "Waiting for user approval");
}
// Called when user approves on their device
public async Task OnUserApprovedAsync(string authReqId, string userId)
{
// Retrieve the stored authentication request
var storedRequest = await _storage.TryGetAsync(authReqId);
if (storedRequest == null) return;
// Create authenticated session
var authSession = new AuthSession(
userId,
sessionId: _sessionIdGenerator.GenerateSessionId(),
authenticationTime: DateTimeOffset.UtcNow,
identityProvider: "local");
// Update request with authenticated status
storedRequest.Status = BackChannelAuthenticationStatus.Authenticated;
storedRequest.AuthorizedGrant = new AuthorizedGrant(authSession, storedRequest.AuthorizedGrant.Context);
// Notify completion - automatically selects and delegates to the appropriate
// mode-specific notifier (PollModeNotifier, PingModeNotifier, or PushModeNotifier)
await _notifier.NotifyAuthenticationCompleteAsync(
authReqId,
storedRequest,
TimeSpan.FromMinutes(5));
}
// Called when user denies on their device
public async Task OnUserDeniedAsync(string authReqId)
{
var storedRequest = await _storage.TryGetAsync(authReqId);
if (storedRequest == null) return;
storedRequest.Status = BackChannelAuthenticationStatus.Denied;
await _storage.UpdateAsync(authReqId, storedRequest, TimeSpan.FromMinutes(5));
}
}
The CompleteAsync(string, BackChannelAuthenticationRequest, TimeSpan) method automatically handles
mode-specific behavior based on the client's registered backchannel_token_delivery_mode:
- Poll Mode: Stores tokens in IBackChannelRequestStorage.
Client polls the token endpoint with
auth_req_iduntil tokens are ready. - Ping Mode: Stores tokens and sends HTTP POST notification via
INotificationDeliveryService to the client's
client_notification_endpointwith theauth_req_id. Client then retrieves tokens from the token endpoint. - Push Mode: Generates tokens via ITokenRequestProcessor and delivers
them directly via INotificationDeliveryService to the client's
client_notification_endpoint. Tokens are removed from storage after successful delivery per CIBA specification section 10.3.1.
- Binding Message: Display request.Model.BindingMessage to user for transaction confirmation
- User Code: If request.Model.UserCode is present, require user to confirm it
- Authentication: All notifications use Bearer token from
client_notification_token
The library validates only the presence of user_code when the provider and client
require it (see UserCodeValidator); it
deliberately does not — and cannot — verify the code's value, because the secret is known
only to the end-user and the user's authentication device, which this handler owns. Your
implementation therefore MUST verify request.Model.UserCode against the
user's actual code as part of the device interaction, and MUST NOT return a
successful AuthSession unless that check passed. A wrong or absent code MUST resolve
to a failed Abblix.Utils.Result<> (typically access_denied).
Treating presence-validation as sufficient leaves the code unenforced and defeats its purpose.
Methods
IUserDeviceAuthenticationHandler.InitiateAuthenticationAsync(ValidBackChannelAuthenticationRequest) Method
Initiates the authentication process for the user on their device, based on a validated backchannel authentication request. This may involve sending a notification to the user's device, starting an out-of-band authentication process, or performing other steps required to authenticate the user asynchronously.
System.Threading.Tasks.Task<Abblix.Utils.Result<Abblix.Oidc.Server.Features.UserAuthentication.AuthSession,Abblix.Oidc.Server.Common.OidcError>> InitiateAuthenticationAsync(Abblix.Oidc.Server.Endpoints.BackChannelAuthentication.Interfaces.ValidBackChannelAuthenticationRequest request);
Parameters
request ValidBackChannelAuthenticationRequest
The validated backchannel authentication request containing user and client information required to initiate the authentication process.
Returns
System.Threading.Tasks.Task<Abblix.Utils.Result<AuthSession,OidcError>>
A System.Threading.Tasks.Task representing the asynchronous operation to initiate the authentication process.