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.
What Happens on the User Device During the Authorization Code Flow Grant?
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.
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.
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.