Securely receiving authorization code in SPAs using form_post
If you have used the OIDC protocol to implement single sign-on, you would be used to receiving the authorization code as a query parameter from the identity server. However, did you know that receiving the authorization code this way can actually compromise your authorization code?
Yes, when the authorization code is sent as a part of your redirect URL, it can be stored in the browser history. This becomes a threat vector that can compromise the security of your application. So, what is the alternative? Well, you can use the form_post response mode to address this issue.
The form_post response mode
The OIDC protocol supports two response modes. The response mode specifies how the authorization code is returned to the client application. The first and the most used response mode is the query mode. This simply returns the authorization code as a query parameter in the URL. The second is the form_post method.
When you use the form_post method, the identity server, first, encodes the authorization code as an HTML form value. In other words, the server assigns the authorization code as the value of a hidden input element within a form. The action attribute of the form is set to the redirect URL you have configured and the method is set to POST. Then, the identity server triggers submit automatically so the authorization code is sent to your redirect URL in the body of a POST request.
Obtaining the authorization code when response mode is set to form_post
Now is the tricky part. How do you get hold of this authorization code in a Single-Page Application? Since the code is sent as a POST request, you cannot access it in the frontend. The request goes to the client’s server directly. So, how do you get the code from the client’s server? There are two common ways and let us discuss both these ways here.
1. The first method of using form_post
The first way is to store the authorization code in a JavaScript variable during server-side rendering. Your SPA will be served by a server that usually just returns the index.html page as a response to requests. When you set the redirect URL to the endpoint of the server that servers this HTML page, the server can get the authorization code from the request body.
Once the server gets the authorization code from the request, it can then use template tags to store the authorization code in a JavaScript variable during the server-side rendering of the page. The SPA can then read this JavaScript variable to get the authorization code.
An SPA that uses a tomcat server might implement this method using JSP as follows.
However, the problem with this method is that the authorization code will be rendered as a part of the HTML code of the page. If the page is saved for some reason, the code will be saved along with the page as well.
2. The Second Method of using form_post
We can avoid this by using our second method. Here, we will get the authorization code from the POST request and persist it somewhere. The code can be stored either in a session variable or in a database. The choice is yours.
Then, we can create a GET request endpoint that will return this authorization code. Once the code is returned, the code should be deleted so that any more calls to this endpoint will not return the code.
The SPA will then send a GET request to this endpoint to safely obtain the authorization code from the server.
The advantage of this method is that the authorization code appears neither in the URL nor on the HTML page.
The following is a sample implementation of this method using JSP in a tomcat server.
The index.jsp page:
The API endpoint:
Summary
Thus, we learned that the best way to safely obtain the authorization code in an SPA is to use the form_post response mode and create an API endpoint in the client’s server to allow the SPA to fetch the code from. I demonstrated these implementations using JSP but you can do the same with any server-side scripting language and servers.
We use the above method in both the Console and My Account apps of theWSO2 Identity Serverto secure the OIDC authentication flow. You can check out our codebase inour GitHub repository.
Leave a Reply