All postsOAuth2 / OpenID Connect

CIBA and the Case for Matching Auth Flows to Threat Models, Not Popularity

Jul 22, 2026·6 min read

For native mobile apps, OAuth 2.0 Authorization Code Flow with PKCE has been the default answer for so long that it's easy to stop asking whether it's actually the right answer for a given app. It usually is. RFC 8252, the IETF's best-current-practice document for native apps, is explicit that public clients must implement PKCE and should authenticate through the system browser rather than an embedded web view — and for the vast majority of consumer apps, that combination remains the correct, well-understood choice.

But a banking app isn't the vast majority of consumer apps, and it's worth asking what changes when the thing being protected is a customer's money rather than their shopping cart.

Authorization Code Flow Solves a Specific Problem Extremely Well

It's worth being precise about what Authorization Code Flow with PKCE was actually designed to do, because the design tells you where it fits. PKCE exists to solve one specific vulnerability: a native app is a public client that can't hold a secret safely, so if an authorization code gets intercepted — by a malicious app registered to the same URI scheme, for instance — that code alone shouldn't be redeemable for tokens. PKCE closes that gap by requiring the client to prove it initiated the original request before the code can be exchanged. RFC 8252 also steers native apps toward the system browser specifically, because it gives the app a separate security boundary from the browser's cookie jar and page content — a native app shouldn't be able to read or inject into the login page it's redirecting the user to.

That's an excellent model when the client is a third-party consumer of an identity provider's authentication — social login, a shopping app authenticating through Google or Apple, any scenario where the app and the identity provider are, in some sense, separate parties negotiating trust through a browser handshake.

Banking Apps Aren't Really in That Relationship

A bank's own mobile app isn't a third party asking a stranger's identity provider to vouch for a user. The bank is the identity provider. It already has a relationship with the device, the customer, and frequently a risk engine that's been scoring this exact login attempt before the authentication request even starts. Routing that interaction through a full browser redirect — with all the phishing surface, redirect handling, and session management a browser introduces — solves a trust problem the bank and its own app don't actually have with each other.

This is where Client-Initiated Backchannel Authentication (CIBA), an OpenID Foundation specification finalized in 2021, becomes worth a serious look. CIBA separates the consumption device — where the user is interacting with the client — from the authentication device, where the user actually authenticates and grants consent, and lets the client talk to the identity provider directly over a backchannel rather than bouncing the user through a browser redirect. In practice, that's the flow behind "we sent a push notification to your registered device — approve the login there" patterns that already feel native to how mobile banking apps work today.

Where That Distinction Actually Matters

The appeal isn't that CIBA is inherently more secure in the abstract — it's that it removes a step (the browser redirect) that was solving a problem the bank's own first-party app doesn't have, while adding a step (authenticate-and-approve on a known, registered device) that maps much more directly onto what banking security actually needs to verify: not just "does this person know a password," but "is this the customer's own trusted device, approving this specific action, right now."

That last part matters more in banking than almost anywhere else, because banking isn't only about login. It's about authorizing specific, consequential actions — a wire transfer, a new payee, a change to account limits — and a push-based backchannel approval model generalizes naturally to "approve this $4,000 transfer" in a way that a generic login redirect doesn't. The same underlying mechanism that authenticates a session can be reused to get explicit, user-present approval for the transaction that actually matters.

CIBA Isn't a Security Upgrade by Itself

None of this makes CIBA automatically safer than Authorization Code Flow — it removes one attack surface (browser redirects) while introducing requirements of its own: strong device binding so the "authentication device" really is the customer's device, robust protection against social-engineering attacks that trick a user into approving a push notification they didn't initiate, and the same baseline of secure key management and token handling any OAuth flow needs regardless of which grant type it uses. A poorly implemented CIBA deployment — weak binding, sloppy consent screens, no fraud signal feeding the approval decision — can be just as exploitable as a poorly implemented redirect flow. The flow is a tool, not a guarantee.

The Actual Decision Isn't "Which Protocol Is Better"

The useful question was never "is CIBA better than Authorization Code Flow." It's "what relationship does this client actually have with this identity provider, and what does that relationship's threat model require." A third-party app requesting delegated access to a user's data through an external identity provider is exactly the scenario Authorization Code Flow with PKCE was built for, and it remains an excellent, mature, broadly supported answer there. A bank's own first-party app, authenticating its own known customer on an already-registered device, and increasingly needing to authorize specific high-value transactions rather than just establish a session, is a meaningfully different relationship — and CIBA was built with exactly that shape of problem in mind.

Picking a flow because it's the most standardized option, without asking which relationship it was designed for, is how teams end up bolting transaction-approval requirements onto a login flow that was never meant to carry them. The stronger habit is starting from the threat model — who owns the client, who owns the identity, what's actually being authorized — and letting that answer determine the protocol, rather than the other way around.


References and Further Reading