December 03, 2020

Securing APIs in Banking with OAuth and PKCE

6 min. read

Financial institutions are embracing application programming interfaces (APIs) and open banking to adapt to a rapidly changing consumer landscape. The first volume of the F5 Labs 2020 Application Protection Report finds that over 50% of the cases studied for API breaches and disclosures were authentication and authorization related. The solution to this problem is to correctly use OAuth and OpenID Connect (OIDCOpenID Connect is an identity layer built on top of the OAuth 2.0 protocol, allowing clients to validate the identity of the end user.). The OpenID foundation1 has developed financial-grade APIs (FAPI), a set of specifications to secure APIs in the banking sector. FAPI2 is built on top of OAuth 2.0 and OIDC and addresses security gaps. This article series on Financial APIs discusses these kinds of security controls with this part focusing on OAuth and Proof Key for Code Exchange (PKCE).

OAuth and Challenges with Public Client

OAuth3 is an open standard protocol for authorization that allows for unrelated services to share access without the need to share user credentials. OAuth 2.0 (the current version) provides for an access token used to grant access to APIs. The OAuth specification supports multiple ways to get the access token, known as Grant Types. One of the most widely used grant types is “Authorization Code Flow,”4 used by both web and mobile applications. Authorization Code Flow provides additional security cover because, in its workflow, the application receives an authorization code, which it needs to exchange with the Authorization Server for an Access Token. Figure 1 explains the authorization code grant flow for a native mobile application.

OAuth authorization code flow sequence diagram
Figure 1. OAuth authorization code grant flow

What Happens on the User Device During the Authorization Code Flow Grant?

native application uses external user agent to gain authorization code
Figure 2. Native application using a browser to get authorization code

The best practice document from Internet Engineering Task Force (IETF)1 recommends the use of an external user agent (such as a browser) to complete the flow in authorization flow code grant. When a native app wants to access private information, it needs to first get an authorization code. The native app starts its authorization request via the browser, which completes Step 3 and 4 (as shown in Figure 1) to get an authorization code. The browser then passes the authorization code back to the native application via a mechanism facilitated by the client operating system. The native application then exchanges the authorization code for an access token. Figure 2 illustrates the communication between a native application and the browser.

Authorization Code Interception Attack

The authorization code grant flow is supported by both confidential and public clients. It is possible for an attacker to reverse engineer a mobile application to gain access to the client secret. In the case of single page applications (SPA), the client secret is available in the web code, openly accessibly in the browser. With a client secret and authorization code, a malicious application can effectively impersonate the original application for which the authorization code was issued. This is called an authorization code interception attack. The idea is to exchange that authorization code for “Access Token” and optionally “Refresh Tokens” from the token endpoint and gain access to a user’s account. Figure 3 illustrates the weakness in this authorization code flow sequence.

Sequence diagram from authorization code flow interception attack
Figure 3. Sequence diagram from authorization code flow interception attack

PKCE Mitigates Authorization Code Interception Attack

RFC 76361 describes a mechanism to mitigate authorization code interception attacks. It’s known as Proof Key for Code Exchange or PKCE. It is an extension to the authorization code grant flow in OAuth2.0 and will become mandatory in OAuth 2.1. It requires the use of a dynamically generated random key known as a code verifier. A transformed value of the code verifier known as a code challenge is transferred during the request for an authorization code. The application will later need to provide the same code challenge when exchanging the authorization code for the access token. The code challenge is transmitted over an encrypted channel, protecting it from interception. The code verifier is dynamically generated by the application and cached for the specific request. Both generation and storage mechanisms need to be impervious to attacks. The ephemeral nature of the code verifier prevents it from being misused if an attacker gains access to it. Figure 4 illustrates how PKCE negates the use of stolen or intercepted authorization codes.

Sequence diagram from authorization code flow interception attack negation
Figure 4. Sequence flow for rejecting intercepted authorization codes


Financial institutions are progressing with their digital transformations and efforts to provide customers greater control of their data with open banking. An understanding of FAPI specifications can really help the journey. Securing APIs with OAuth with PKCE can ease APIs authorization challenges, such as authorization code flow interception attacks.


Expertly picked stories on threat intelligence

Hundreds of apps will be attacked by the time you read this.

So, we get to work. We obsess over effective attack methods. We monitor the growth of IoT and its evolving threats. We dive deep into the latest crypto-mining campaigns. We analyze banking Trojan targets. We dissect exploits. We hunt for the latest malware. And then our team of experts share it all with you. For more than 20 years, F5 has been leading the app delivery space. With our experience, we are passionate about educating the security community-providing the intel you need to stay informed so your apps can stay safe.


9 hrs

a critical vulnerability—with the potential for remote code execution—is released.