Identity & Access Management 4 minutes

How to use Authorization Code + PKCE for login to SPA Applications

Hasitha
Hasitha Amal Da Silva
Integration Consultant
Authorization Code PCKE
Scroll

In this article, we will walk through the steps that you can follow to achieve a more secure and adaptable login flow in Single Page Applications or Native Mobile apps using WSO2 Identity Server. We will first demonstrate how the new flow will interact between different components, and then explain the technical changes in your app/webpage to make it work!

Switch to Authorization Code + PKCE

Many web based applications using their IAM product are using Implicit Grant for their login flow, while Native mobile Apps are using the Password Grant type. However, Multiple vulnerabilities have been found in these approaches, as summarized in OAUTH documents 1 and 2.

The current recommendation for both native apps and web-based applications is to switch to Authorization Code + PKCE flow. While this is the best practice, it does require some effort on the application side to switch to this flow. And this guide, hopefully, will help you to smoothly transition to this flow.

New Flow as a Sequence Diagram:

New login flow Authorization Code PKCE

Change required from WSO2:

If you have an existing Service Provider configured for the application as per this wso2 article, you only need to enable “code” grant type and enable the “PKCE Mandatory” checkbox. Optionally, you can choose to “Allow authentication without client secret”, so that your app or the web page does not have to maintain the wso2 client secret value. This is actually a best practice when using authorization code with PKCE.

Web-based Applications (Single-Page-Applications):

Key differences of the new login flow compared to the Implicit Grant flow are as below. 

  1. Every time the page is loaded or authentication is required, the application back end must
    • generate a “code_verifier” as per https://tools.ietf.org/html/rfc7636#section-4.1 and persist it (if it does not exist already).
    • calculate the code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))). You can use this website as a reference to valid conversion of a code_verifier string to a code_challenge.
  2. In implicit flow, the SPA application (e.g. Angular) always calls the Authorization Server (WSO2) “oauth2/authorize” endpoint, so that WSO2 can validate the user session, and redirect to the login page as required. This call must also happen in the new flow, but with following changes.
    • “response_type” query parameter value changes from “id_token token” into “code”
    • Two new parameters must be added;
      • code_challenge_method = S256
      • code_challenge = calculated in difference #2
  3. In implicit flow, the application receives the ID token as a URL fragment (e.g. http://app.com#id_token=JWT). In the new flow, WSO2 will return a ‘code‘ a query parameter, and the application back end must then call the “oauth2/token” WSO2 endpoint as below where {{AUTHORIZATION_CODE}} is the code received in the callback URL:
curl --location --request POST 'https://localhost:9443/oauth2/token' \

--header 'Content-Type: application/x-www-form-urlencoded' \

--data-urlencode 'grant_type=authorization_code' \

--data-urlencode 'client_id={{CLIENT_ID}}' \

--data-urlencode 'client_secret={{CLIENT_SECRET}}' \

--data-urlencode 'code={{AUTHORIZATION_CODE}}' \

--data-urlencode 'redirect_uri={{redirect_uri}}' \

--data-urlencode 'code_verifier={{code_verifier}}' \

Potential Libraries that can be used:

If the Application is based on Angular, the “angular-oauth2-oidc” library can be used to handle the login flow of your application – https://github.com/manfredsteyer/angular-oauth2-oidc. It is certified and recommended by OpenID foundation which governs the OAUTH2 Protocols.

A reference application which connects to a Local WSO2 Identity Server is here – https://github.com/davebaol/oidc-angular-wso2is

Native Mobile Apps

Key differences of the new login flow compared to Password Grant flow are as below.

In Password flow, the Native App is collecting the user’s credentials. In the new flow, the App must;

  • generate a “code_verifier” as per https://tools.ietf.org/html/rfc7636#section-4.1 and persist it (if it does not exist already)
  • calculate the code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
  • open the “oauth2/authorize” url in the mobile browser, including the query params similar to the web flow (response_type, scope, redirect_uri, client_id, nonce, code_challenge, code_challenge_method). The best practice is to rely on a mobile browser to handle the login rather than an inline web view within app
  • once the user enters the credentials in the browser, and WSO2 redirects the browser to the “redirect_uri”, The app must listen to this url and
  • extract the “code” query parameter
  • exchange the code for a token, also including the saved “code_verifier” (same as Step 3 in the Web-based application flow)

Conclusion

We are now in an era where the Identity and Access Management Landscape is continuously changed and enhanced to provide more adaptability, connectivity across different social media and business tools while maintaining the security of the user at heart. And I believe the OAUTH2 specification enhanced with the PKCE verification is a great step towards our capacity to connect across multiple systems and provide creative authentication solutions to the end user. I hope this article moves you or your organization to hack-proof your systems while balancing the user experience.