Wednesday, October 5, 2022

OAuth 2.0: Authorization Code Vs Implicit Flow

OAuth 2.0 is something I believe most of us can get confused with (I still do at times). 

Sometimes people get confused with OAuth 2.0 and OIDC (OpenID Connect) as well.

OAuth 2.0 is a standard protocol for Authorization. But in the past, different major companies have started using OAuth 2.0 for Authentication by extending it in their own ways.  Then some genius set of people thought to make it a standard, thus they came up with  OIDC (OpenID Connect) specification which is to be used for Authentication.

So the key concept is that OIDC is an additional identity layer built on top of the OAuth 2.0 protocol. 

Anyway, in this post, thought of writing a post about the most widely used OAuth flow: Authorization Code, and have it compared with the Implicit flow. (Implicit flow is considered legacy now and its use is recommended to replace with Authorization Code with PKCE which is a slight variation of Authorization Code)

For this post, I am considering Microsoft Identity Platform as the Identity Provider, this can be Auth0, Okta, Google, or even your own Identity Server implementation. The URLs and scopes are simplified for brevity.

Authorization Code Flow

The Authorization Code grant type is used by confidential and public clients that use server-side technologies.

Authorization Code Flow
#1: The authorization code flow begins with the client directing the user (Resource Owner) to the /authorize endpoint. It's an HTTP GET request, something like follows.
One of the most important thing here is the response_type=code, we are basically asking for an Authorization code. Now the user will be redirected to the Identity provider login page, in this case it's Microsoft.

#2: After the user has entered their Email and Password, upon successful login, the user will be presented with a consent screen. There the scopes requested will be visible.

#3: Upon accepting the consent, the user will be redirected to the redirect_uri with an authorization code.

#4: Client now makes a Back channel request to /token endpoint to exchange the authorization code received to an access_token. 
content type application/x-www-form-urlencoded
#5: For above request, the client will receive a response, something like below.
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI...",
    "token_type": "Bearer",
    "not_before": 1664733775,
    "expires_in": 3600,
    "expires_on": 1664737375,
    "scope": "Calendars.Read"
#6: Now the client has the access_token in the form of a JWT token, the client can call the Resource Server using that.

A couple of important things to note here. In the picture above, note that the steps from #1 to #3 is happening on the Front channel, while the steps from #4 to #6 happen on the Back channel. The reason is, in step #3, a client_secret is involved and we shouldn't be exposing that to the outside.

Note: It is now recommended to use the Authorization Code with PKCE flow to provide better security even though a client is using a client_secret.

Implicit Flow (Legacy)

Implicit Flow
This flow was a simplified OAuth flow previously recommended for native apps and JavaScript apps (SPA). Here we are directly asking for the access_token in the first place by setting response_type=code, so the authorization code exchange step is skipped. That introduces a security risk when returning access tokens in an HTTP redirect without any confirmation that it has been received by the client. Because of that reason, Implicit flow is now deprecated and public clients such as native apps and JavaScript apps should now use the Authorization Code with PKCE flow instead.

Hope this helps.

Happy Coding.


No comments:

Post a Comment