Find out how the most widely-used protocols for authentication and authorization really workWe’ve all seen the “sign in with Google” and “connect to Facebook” buttons on websites and mobile apps. Click the button and a screen opens that says, “This app wants to access your public profile, contacts…” and asks you whether you want to give access. This is OAuth at a high level. Understanding these protocols is crucial for every software engineer, security expert, and even hacker. TL;DRA complete guide to OAuth 2.0 and OpenID Connect, the two most widely used protocols on the internet today for authorization and authentication. OAuth 2.0 is used for authorization and OpenID Connect is used for authentication. There are two most common OAuth 2.0 authorization flows, authorization code flow for server-side applications, and implicit flow for browser-based applications. OpenID Connect is an identity layer on top of the OAuth 2.0 protocol to make OAuth suitable for the authentication use cases. Why OAuth?To understand the reason for the birth of OAuth we need to understand a term called Delegated Authorization. Delegated authorizationDelegated authorization is an approach to allowing a third-party application access to a user’s data. Two approaches to delegated authorizationThere are two approaches for delegated authorization, whether you give the third-party application your account password so they can login into your account on your behalf and access your data or you grant the application to access your data using OAuth without giving your password (and none of us will give our password!). Now we know the need and importance of OAuth, let’s dive deeper into the protocol. What is OAuth?OAuth (Open Authorization) is a standard protocol for delegated authorization. It allows applications to access user data without the user’s password. OAuth 2.0 terminologyUnderstanding this protocol requires us to understand its terminology:
Take a look at this terminology in the OAuth 2.0 abstract flow: ![]() The authorization key/grant can be of type code or token. We’ll learn about different authorization grants later. Now, let’s take a look at the authorization flow in detail:
That’s how users give third-party applications access to their data without giving them the password. At this point, the following questions arise:
These questions take us to another important piece of OAuth terminology: scopes. Scopes in OAuthScopes in OAuth 2.0 are used to limit an application’s access to a user’s data. By issuing an authorization grant that is limited only to the scopes granted by the user. When the client makes a request to the authorization server for authorization grant, it sends a list of scopes with it. The authorization server uses this list of scopes to generate a consent screen and grants permission from the user. If the user agrees to the consent screen, the authorization server issues a token or authorization code that is limited only to the scopes granted by the user. For instance, if I grant a client application to see the list of my Google contacts then the token issued to the client by the authorization server can’t be used to delete my contacts or see my calendar events — it’s only scoped to read my Google contacts. Setup for OAuth 2.0Before moving on to OAuth flows, it’s good to know some prior OAuth configuration. When the request for authorization grant is initiated, the client sends some configuration data to the authorization server as query params. The basic query params are:
Understanding Different OAuth FlowsThe two most commonly used OAuth 2.0 flows are authorization code flow for server-based applications and implicit flow for pure JavaScript Single Page Applications (SPAs). To explain the OAuth flows, I’m considering Google as the OAuth service provider. Authorization code flowThe authorization code flow or authorization code grant is an ideal OAuth flow which is considered to be highly secured because it uses both the front-end channel (browser) and the backend-channel (server) to implement the OAuth 2.0 mechanism. ![]() The client begins the authorization sequence by redirecting the user to the authorization server with https://accounts.google.com/o/oauth2/v2/auth? In the above request, the client is requiring the user’s permission to access his public profile and contacts by defining them in the 4/W7q7P51a-iMsCeLvIaQc6bYrgtp9 Why exchange code for a token?An access token is the only thing that can be used to access data on the resource server, not the application code. So why is the client set ![]() Problem: An access token is a secret piece of information that we don’t want someone to access. If the client requests an access token directly and stores it in the browser, it can be stolen because browsers are not fully secure. Anyone can see the page source or potentially use dev tools to acquire the access token. Solution: To avoid exposure of the access token in the browser, the front end channel of the client gets the application code from the authorization server, then it sends the application code to the client’s back end channel. Now to exchange this application code for an access token, a thing called POST /token HTTP/1.1 The authorization server validates the client secret and application code and responds with an access token. The back end channel stores the access token and potentially use this token to access a resource server. In this way, the browser cannot access the access token. Implicit flowThe OAuth 2.0 implicit flow is used when you don’t have a back end channel and your website is a static site that uses only the browser. In this case, you skip the last step that happens on the backchannel when you exchange the application code for an access token. In the implicit flow, the authorization server responds with an access token right away. ![]() The client redirects the browser to the authorization server URI to start the authorization flow with Implicit flow is considered less secure because the browser is responsible for managing the access token, so it could potentially be stolen. Still, it’s widely used for single-page applications. Authentication vs AuthorizationAs we know, OAuth solves the delegated authorization problem, but it doesn’t provide a standard way to authenticate the user. You could say that:
If you’re confused by these terms, here’s the difference between them:
In other words, authentication cares who you are, authorization cares what permissions you have. OpenID ConnectOpenID Connect is an identity layer on top of the OAuth 2.0 protocol. It extends OAuth 2.0 to standardize a way for authentication. ![]() OAuth does not provide user identity right away but rather it provides an access token for authorization. OpenID Connect enables the client to identify the user based on the authentication performed by the authorization server. This is achieved by defining a scope named The URI for OpenID Connect authentication request made by the client looks like this: https://accounts.google.com/o/oauth2/v2/auth? The result of the request is an application code that the client can exchange for an access token and ID token. If the OAuth flow is implicit then the authorization server responds with an access token and an ID token right away. The ID token is a JWT or JSON Web Token. A JWT is an encoded token that consists of three parts: header, payload, and signature. After acquiring the ID token, the client can decode it to get the user info encoded in the payload part — like this: { ClaimsThe payload of the ID token contains some fields known as claims. Basic claims are:
However, claims are not limited to these fields. It’s up to the authorization server to encode claims. The client can use this information to authenticate the user. If the client needs more user information, the client can specify standard OpenID Connect scopes to tell the authorization server to include the required information in the ID token’s payload. These scopes are End NoteIt’s always good to practice what you have learned. To play with OAuth 2.0 scopes, authorization codes, and tokens go to Google OAuth 2.0 Playground. |
Security >