Detailed working of OAuth 2.0
How does Oauth flow work in web server and SPA applications?
It’s highly recommended to read this article first before you move ahead with this as it’s in continuation of the previous article: https://medium.com/@iamabhikedia74/the-nuts-bolts-of-oauth-2-0-5f73c13f48fc
Front Channel and Back Channel
The OAuth flow involves two channels for data transmission: the front channel and the back channel. Think of the back channel as a secure, direct connection between the client and server, similar to hand-delivering a package. This channel ensures data integrity and authenticity through encryption and HTTPS.
In contrast, the front channel relies on the user’s browser (address bar) to transmit data between systems, similar to using a package delivery service. There is no direct link between the sender and recipient (application and the OAuth server). While convenient, the front channel poses security risks, as data can be intercepted or tampered with during transmission.
A significant concern with the front channel is the lack of assurance regarding data delivery and authenticity. Like sending a package through a delivery service, there’s no guarantee that the intended recipient receives it or that its contents remain intact.
To address these issues, OAuth typically employs the back channel for secure data exchange. However, for user consent purposes, the front channel becomes essential. It allows the user to actively participate in the authorization process, ensuring their explicit permission is obtained.
How does the flow work?
There are two flows available:
Implicit Flow
Back in early 2000 browser-based apps were restricted to sending requests to their server’s origin only. Because of the Same Origin Policy, there was no way to call an authorization server’s token endpoint at a different host.
Thus, frontend applications were not able to get an access token from another origin using Authorization Code flow, and Cross Origin Resource Sharing was not commonly available (it was accepted as a W3C Recommendation in 2014). Even if it was available, SPA’s have the problem of keeping a client secret securely, which is another limitation.
For these reasons, Implicit Flow was mainly designed for SPA’s and JavaScript applications with no backend channel.

- Authorization Request: The application starts by telling the authorization server what it wants to do, like accessing certain data. This request includes details like the application’s ID and what permissions it needs.
On fizzbuzz, when user clicks on a button named “login with google”, the app is redirected to accounts.google.com with the following:
{
client_id = ‘fizzbuzz’
redirect_uri = ‘https://fizzbuzz.com/callback’
response_type= ‘code’
scope = ‘profile contacts calendar’
} - Sending the Request: The application sends this request to the authorization server, usually through the browser’s address bar.User Authentication: The user logs into the authorization server and approves the application’s request.
- Token Delivery: After the user approves, the authorization server sends back an access token to the application.
- Security Concerns: Sending the access token back in the browser’s address bar (the “front channel”) isn’t secure because it could be intercepted. This method, called the Implicit flow, used to be accepted but is now discouraged due to its security risks.
In the Implict Flow, both the request and access token response happens in the front channel and there is no back channel involved.
To address security concerns, OAuth now recommends using the back channel to send the access token securely. This involves making a secure request from the app to the server. Modern browsers support this method through Cross-Origin Resource Sharing (CORS).
Even JavaScript apps can use the back channel to securely send requests to the server. This provides similar security to requests made from backend servers.
Application Identity
In OAuth, applications (also called clients) have their own identity. When you log into an app and see a message like “This application would like to access your account,” it refers to the app’s identity. Each app has a unique identifier called a client ID, which it uses throughout the OAuth process.

Some apps have a client secret, which acts like a password. It ensures that only the authorized application can access certain data. Without this secret, there’s no guarantee that the app using the client ID is genuine (or in other words, without client secret, there is no assurance that an app claiming to be let’s say X is actually X.
Authorization Flow
Authorization Flow uses both front-channel and back-channel. Once authorized (with consent) the request is redirected back to a registered endpoint with the Authorization Code. Then this code is exchanged with an Access Token thru back channel. Then the app uses access token for resource access.
Here we imagine a web application with backend, registered to google and anyone using a google account can authenticate against account.google.com to grant access and get her contact list into the application.

- Initial Request from the Application:
1. The application, also known as the client, initiates the OAuth process by constructing a request to the authorization server.
2. This request typically includes various parameters:client_id
: The unique identifier assigned to the application.redirect_uri
: The URL where the user should be redirected after authentication.scope
: Specifies the permissions or scope of access requested by the application.
Other optional parameters may also be included based on the specific requirements of the OAuth implementation. - Redirecting the User to the Authorization Server:
1. Once the request is prepared, the application redirects the user’s browser to the authorization server.
2. The URL used for redirection includes the parameters mentioned earlier, such as the client ID, redirect URI, and scope. - User Authentication and Authorization:
1. The user is prompted to log in to their account on the authorization server.
2. After successful authentication, the authorization server presents the user with a consent screen or authorization prompt.
3. Here, the user can review the requested permissions or scope and choose whether to grant access to the application.
4. If the user consents, they authorize the application to access the requested resources. - Redirecting Back to the Application:
1. Once the user grants consent, the authorization server redirects the user’s browser back to the specified redirect URI.
2. The redirection includes additional information, such as an authorization code, appended to the redirect URI as a query parameter.
3. This authorization code serves as a temporary token that the application can exchange for an access token. This token is valid for very short period of time(typically under a minute) and for single use. - Exchange Authorization Code for Access Token:
1. Upon receiving the authorization code, the application must exchange it for an access token.
2. To do this, the application sends a request to the authorization server’s token endpoint, typically using HTTP POST.
3. The request includes the authorization code obtained earlier, along with other parameters like the client ID, client secret (if applicable), and the redirect URI.
4. In response, the authorization server verifies the authorization code and issues an access token to the application. - Accessing Protected Resources:
1. With the access token obtained, the application can now access the user’s protected resources on the resource server.
2. The application includes the access token in subsequent API requests to the resource server.
3. The resource server validates the access token to ensure that the request is authorized, granting or denying access accordingly.
Now, keep in mind that it’s possible that that authorization code might be stolen or copied, which means the server can’t really ever be sure whoever is redeeming that code is the real application. So we need some way to verify that. And that is with a client secret is for. Remember, the client secret is like the application’s password.
So if the application redeems this authorization code and proves it’s the real application by authenticating with its password, then the authorization server knows it’s being redeemed by the real application and it hasn’t been stolen. And this works because the application uses its client secret to prove its identity at the authorization server when it makes that request for an access token.
But what happens if the app can’t prove its identity?
And that would be the case for mobile apps or a single page apps which can’t be deployed with a client secret since these kinds of applications don’t have a client secret. If they were to try to use the authorization code flow, the OAuth server would effectively be letting any application that could steal the code get an access token.
So we need some sort of solution to this, which it turns out is the PKCE extension, short for Proof Key for Code Exchange.
Authorization Code Flow for Server Side Applications

The flow begins with the user accessing the client application through their browser. The application requires an access token from the OAuth server to interact with an API securely. Ideally, the application should receive the access token via the back channel to maintain security and keep the token out of the browser’s view.
Steps in PKCE flow:
- User Interaction: The user initiates the flow by clicking the login button on the client application.
- Generating PKCE Code Verifier: Before redirecting the user, the application generates a random code_verifier for this specific flow. This is called PKCE code verifier. This code_verifier is used to create a hashed code challenge. Hash is one-way operation and it cannot be reversed back to generate the secret.
- Redirection to Authorization Server: The application constructs a URL with various parameters, including the code challenge, client ID, redirect URL, and scope, and redirects the user to the OAuth server.
- The OAuth server redirects the user to the login prompt.
- User Authentication and Authorization: The user logs in and grants permissions to the application.
- Delivery of Authorization Code: Upon user approval, the OAuth server redirects the user back to the application with a one-time-use authorization code. So it takes the app’s redirect URI, adds the authorization code in the query string and then sends the user’s browser there to deliver that back to the app.
- Token Exchange: The application makes a backchannel request to the OAuth server, exchanging the authorization code for an access token. This request includes the authorization code, client credentials, and the plaintext code verifier.
- Verification and Access Token Issuance: So the server looks at this request and says, ok, cool, I see that I just issued this code. It hasn’t been used yet and it was intended for this client. And here’s the matching client secret. And when the request was started, I saw this hash, the code challenge. So I’m going to go calculate the hash of this code verifier and compare the hashes. And if they match, then I know that the thing redeeming this code is the same as the thing that started the flow.
- Access Token Issuance: So the server generates the access token and returns it in the response.
- Accessing Protected Resources: With the access token, the application can securely access the user’s resources on the API.
Authorization Code Flow for Single Page Applications
One of the more straightforward limitations of JavaScript apps is that there’s no way to ship any sort of credentials in the app. That’s why js applications are considered public in OAuth terms.
If you imagine trying to put in API key into a JavaScript app, it’s trivial for anybody using the app to click View Source and the browser and then poke around the source code and they’d be able to find the key. And there’s nothing you can do to hide it. Any attempts you make to try to hide the key will be able to be reverse engineered.
Now, that said, if you do have a dynamic server backend hosting your single page app, then that back end piece might be a confidential client.

This flow is pretty much similar to the server side flow, the differences are:
- The application is running on user’s device.
- There is no client secret.
So while exchanging the authorization code with the access token, we don’t send client secret. These are the params included: grant_type=authorization_code, code, redirect_uri, code_verifier, client_id
Let’s Get in Touch
You are most welcome to follow me here on Medium. In addition, feel free to check out:
- My portfolio
- My LinkedIn Profile: Let’s connect!
- My Twitter Profile
References
https://www.deepnetwork.com/blog//2019/11/08/oauth2-oicd-pkce.html
https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce
https://cloudsundial.com/auth-code-with-pkce
https://www.udemy.com/share/103UzM/