OpenID Connect and OAuth 2.0: Streamlining Authentication/Authorization for Web Applications
Discover How OpenID Connect and OAuth 2.0 Work to Improve Web Security and User Experience

In this article, we will explore how OpenID Connect, combined with OAuth functionality, can streamline the authentication as well as authorization process. By using these technologies, applications with a web server can achieve a secure and efficient mode of authorization & authentication. Before diving into the details, it's essential to understand what OpenID Connect and OAuth 2.0 are, and how they differ from each other.
OAuth 2.0 / OIDC
Often misinterpreted as one another , OpenID Connect (OIDC) extends OAuth 2.0 by adding an identity layer, allowing applications to verify user identity and obtain basic profile information . But before diving straight into the OpenID rabbit-hole we must first understand what OAuth is , why it was needed , what problems it solved and how OpenID developed on top of it
OAuth
Understanding OAuth would be easier if we understand the problem it solves , Let’s take for example -
Imagine there’s a wallpaper site you love, and you want to share it with your friends over email. Before the advent of OAuth, you would have had to share your email ID and password with that site so it could send emails on your behalf. Doesn’t that sound like a terribly unsafe idea?
To solve this problem, the creator of the wallpaper site can integrate an OAuth provider (like Google) into their app. When you choose to share something, you’ll first be redirected to a login screen from the OAuth provider (if you aren’t already signed in). This step helps the provider confirm that it’s really you.
After that, you’ll see a consent screen asking for your approval. Once you grant permission, the site receives an access token from the authorization server (which also may or may not be associated with the OAuth provider).
Using this access token, the wallpaper site can then access your relevant information from the resource server ( which also may or may not be associated with the OAuth provider). This allows the site to retrieve only the specific data it needs—like your contact list—to send invitation emails to your friends, without ever seeing your password or requesting unnecessary permissions.
One of the companies that had to rely on this “terribly unsafe idea” in the pre-OAuth era was Yelp, as shown in the screenshot below.

To solve the security issues that Yelp (and many other apps) faced before OAuth, the protocol defines authorization grants (also called flows) — these are the different methods by which a client obtains permission (a credential) to access protected resources.
Each grant type is optimized for certain use-cases. Here are the most common ones:
Authorization Code — used by web applications with a backend (this is the flow typically used by applications like Yelp) .
PKCE — an extension of Authorization Code flow, more secure for public clients (e.g. mobile or SPAs) .
Client Credentials — used in machine-to-machine or server-to-server scenarios (no user interaction) .
Device Code — used by devices with limited input (e.g. smart TVs) where the user enters a code via another device .
Refresh Token — allows renewing an expired access token without prompting the user again.
In our discussion, we’ll focus on the Authorization Code grant , since that’s the most relevant for web apps like Yelp. The other grant types will be covered in later articles.

To understand how this code flow will work first we have to understand all the Stakeholders in this workflow and the role they play ,
Client ( The Third-Party Application )
The client is the application that is attempting to get access to the user's account. It needs to get permission from the user before it can do so.
The Resource Server
The resource server is the API server used to access the user's information.
The Authorization Server
This is the server that presents the interface where the user approves or denies the request. In smaller implementations, this may be the same server as the API server, but larger scale deployments will often build this as a separate component.
Resource Owner ( The User )
The resource owner is the person who is giving access to some portion of their account.
When we register our app in any OAuth provider ( like google ) , we are given some credentials ( Client ID and optionally Client Secret ) whereas we register some credentials ( Redirect URI ) from our end in the OAuth provider’s console , lets get into them one by one -
Redirect URIs
The service will only redirect users to a registered URI ( with authorization code ), which helps prevent authorization code interception or phishing-style redirection attacks . Any HTTP redirect URIs must be served via HTTPS. This helps prevent tokens from being intercepted during the authorization process.
Client ID and Secret
The Client ID uniquely identifies your app and is included in most requests to the authorization server.
The Client Secret is a confidential key used by your app to securely exchange the authorization code for an access token. However, in scenarios where the deployed app cannot keep the secret confidential — such as in Single Page Applications (SPAs) or native mobile apps — the secret should not be used (and ideally, it should not even be issued). In such cases, OAuth providers generally adopt alternate protections (for example, using PKCE, which removes the need to send a client secret) to maintain security.
Now as we have discussed all the terms and have developed the basic understanding of them lets get deep into the code flow -
Create a login link that takes the user to the authorization server’s login page (authorization endpoint) to sign in and approve access.
https://authorization-server.com/auth?response_type=code&client_id=CLIENT_ID& redirect_uri=REDIRECT_URI&scope=contacts&state=foohere lets break down each of the query params -
response_type = It simply indicates what kind of response the authorization server should return to the client, depending on which grant type (flow) is being used .
client_id = client_id as discussed earlier this is the id we get from OAuth provider and is used as identification of our app for the authorization server .
redirect_uri = As discussed earlier , specifies the URL to which the user will be redirected after the authorization process is complete. This value must exactly match one of the redirect URIs registered with the OAuth provider; otherwise, the authorization server will return an error response.
scope = The permissions your app is requesting (e.g., access to profile, contacts, or photos) , it can be one or many clubbed together .
state = A random string generated by your application, which is used to verify integrity of response and prevent CSRF attacks , we will see its use later .
After logging in through whatever method the authorization server supports or wants user to log in with , user sees authorization prompt which might look something like this

User has two options , deny or allow
first let’s cover the options which doesn’t require much explaining to do deny option -
User will be redirected to
https://yelp.com/cb?error=access_deniedHere , we have taken , yelp.com/cb as a sample Redirect URI of yelp for this example ,
In the case of deny from the user authorization server will redirect user with some kind of access denied message embedded in the params , which can be dealt by application frontend as they like .
When they click on allow , authorization server redirects to the provided Redirect URI , with authorization code and state in the params
https://yelp.com/cb?code=AUTHORIZATION_CODE&state=fooHere
code = The authorization server response with an Authorization Code to the client .
state = The authorization server returns with the state
You should first compare this state value to ensure it matches the one you started with. You can typically store the state value in a cookie or session, and compare it when the user comes back. This helps ensure your redirection endpoint isn't able to be tricked into attempting to exchange arbitrary authorization codes .
Now as you have checked the state and confirmed that you are getting getting authorization code from the original authorization server from which it is intended to , there is another dilemma , of what to do with the authorization code , till now everything we had done that is every call between our application and authorization server has been done in the front channel ( i.e. through our frontend ) but now as we are dealing with confidential information ( Client Secret and access token ) we cannot do the exchange for access token in the front channel as users browser are at risk with multiple fronts ( for example - some malicious code in any of the browser extension , users tendency to click any of the malicious website ) , so in general we don’t trust user with the sensitive information .
So we will send the authorization code to our web-server via the frontend , and our server will perform the exchange and then store the access token or the information extracted from the token in our application database based ( or can even perform an action right away like in this case of sending mails to all the contacts and not storing contacts info in database if not needed ) on our needs .
For this exchange we will trigger a POST request on authorization server’s “/token” endpoint
which will look something like this
POST /token HTTP/1.1 Host: api.authorization-server.com Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=REDIRECT_URI& client_id=CLIENT_ID& client_secret=CLIENT_SECRETgrant_type= The grant type for this flow is authorization_code .
code= This is the code you received earlier in the query string .
redirect_uri= Must be identical to the redirect URI provided in the original call to the authorization server .
client_id= The client ID you received when you first created the application .
client_secret= Since this request is made from server-side code, the secret is included .
Authorization server will respond with
{ "access_token":"access token", "expires_in":3600, }an access token , token expiry ( which will tell us when access token will expire ) and in some cases a refresh token ( can be used to get a new access token generated in case the old one expires ) as well , we will keep these confidential tokens in our server side only and wont expose them to the client side . in case of invalid request we will get an error message as response .
So we will use the access token by sending it to the resource server to get the authorization of doing something on users behalf or getting some of the data regarding user from the resource server .
Request to resource server will look something like
GET /userinfo HTTP/1.1 Host: api.resource-server.com Authorization: Bearer ACCESS_TOKENSo , basically this is almost everything which is to be covered under OAuth in authorization code grant type .
Open ID Connect
As discussed earlier OIDC was built on top of OAuth 2.0 Standard , Primary motive behind introduction of OIDC was to reduce the malpractice that was to use OAuth for authentication purposes , Initially most of the companies used OAuth as work around to implement authentication in their application .
So as a way to streamline the process of authentication Open ID was introduced , there isn’t much difference in code flow of OIDC from OAuth in case of Authorization code grant type .

The main difference is ,
There is no other resource server here authorization server is our resource server.
An extra openid scope is added to our initial request to authorization server .
When we do code — token exchange for access token we get an ID token , which is JWT token , which can be used to extract basic info about the user on the go and as it is JWT it is temper proof .
The ID Token when decoded comes out in a format somewhat similar to this
{ "iss": "https://accounts.google.com", "sub": "10769150350006150715113082367", "aud": "CLIENT_ID", "exp": 1311281970, "iat": 1311280970, "email": "user@example.com", "name": "John Doe" }with some of the important keys here being
-sub(subject) - unique user identifier-
iss(issuer) - who issued the token-
aud(audience) - who the token is for i.e. the client app-
exp(expiration) - when it expiresAnd if we want to get some more information about the user we can use the access token to get more info from the authorization server.
Apart from this there isn’t much that separate both , basically OpenID was introduced as a way to differentiate the task of authentication and authorization .
I am starting a series on authentication and everything in between , next article will be about implementing OpenId Connect for authentication along with two token authentication , and further will go in details about using implementing OTP and magic links for authentication , email verification and password recovery , I have many things planned for the future of this series . Meanwhile if you want to learn more about OAuth and OpenID Connect , watch this video from okta’s youtube channel
and special thanks to Aaron Parecki and his article on OAuth and OIDC do check it out as well ,
& if you want learn more about the code flow of OAuth and OIDC try Google's OAuth Playground & another OAuth playground directly from OAuth 2.0

