A complete guide to Oauth2 authentication

When we visit most of the sites these days, we have seen a screen that says log in with Facebook, Twitter, GitHub, Google, and many more. It is a fairly common thing on the internet. What this does is take your current account information from one of these providers and use it to signup. This makes it a lot easier to signup as a user because we do not need to add our profile information such as our picture, name, or email. We all have used these as a user to sign up and also as a developer to integrate these services into our application.

The one thing that is common among all these service providers like facebook and google is that they use the same protocol, OAuth2 authentication and OpenID connect. Oauth2 authentication was designed to solve the delegation problem. OpenID is a protocol on top of Oauth2 for authentication.

The delegation problem

Let us take a scenario where you want to create a new account in skype. You join skype, but you do not have any contacts there yet. You used a Gmail account to signup for your account. You want to add all your contacts in Gmail who are in skype. In this scenario, skype will need to get access to your Gmail contacts and recommend you the contacts who are in skype. 

The simple solution to this would be to provide Skype, your Gmail account password. Skype can access your account and recommend you the contacts. 

There are a few problems with this approach:

  1. You have no mechanism to revoke the access
  2. Even though it needs access for a couple of minutes you cannot limit the duration of access.
  3. You cannot provide only read access to the contacts. You are giving all read/write access. With this skype can write/read your email and do everything that you can do.
  4. There is no mechanism to know who accessed your account.

How Oauth2 solves the delegation problem

Oauth2 authentication was designed as an industry pattern to solve the delegation problem. Oauth2 authentication provides a secure resource delegation between services. 

Let us use the same Skype-Gmail example to explain the solution. There are four different roles:

  1. Resource owner
  2. Client
  3. Resource-Server
  4. Authorization-Server

The resource owner is the actual owner of the resource. In our example, the end-users login into the skype is the owner.

The server which wants to access data is called a client-server. In our case, Skype is a client-server.

The resource-server provides the resource the client wants to access. Here, the resource server is Gmail. The resource-server has details about the ‘contacts’ resource.

The authorization-server provides the client-server access to the resource on the resource server.

Let us look into how there 4 roles interact while granting resource access. Here, the Resource owner(we) wants to provide the Client(Skpye), access to the resource-server(Gmail contacts).

  1. The client (Skype) requests authorization from the resource owner. 
  2. The client requests the authorization server for a token, based on the grant flow.
  3. The authorization server validates the grant and the client and provides the access token
  4. The client uses this access token to access the resource(Gmail contacts)
Oauth2 Flow diagram
Diagram: Oauth2 Grant Flow

Different Oauth2 grants:

Oauth2 provides different grant flows for different use cases. Let us take a look into the details of each auth flow.

Code grant

Code grant flow is the most used auth flow for public clients to exchange the authorization code with a token. The resource owner wants to grant access to a resource to a client. In this case, the client redirects the user to the login server. Here the user is authenticated and redirected back to the client with an authorization code. This code can be used by the client to exchange it with a token.

Let us look at the Skype-Gmail example here as well:

  1. The client(Skype) requests authorization from the resource owner
  2. The resource owner is redirected to the authorization server with a Client ID, redirect URL and scope of access.
  3. The authorization server authenticates the resource owner and redirects to the provided redirect URL from step 2. It also validates if the Client ID provided in step 2 is valid.
  4. In the client, the authorization code provided by the authorization server is used to exchange it with the token. In this phase, the client provides a client secret. The authorization server validates the client’s secret.

The code should be invalidated to protect from repetitive token fetch.

The code should not be valid for a long duration and should expire after a few minutes.

While a client requests code a state parameter is generated in the client and send to the auth server. The auth server redirects the user to the redirect URL with the same state. This state is validated by the client to protect against XSRF.

There are two API calls needed for the steps above.

Get Authorization Code 

URL: https://auth-server.com/auth
request params:

With the above request, code is returned in response to the provided redirect URL.

Exchange Code for a Token

URL: https://auth-server.com/token
request params:
code: nao1n3f
grant_type: authorization_code
client_id: 29352915982374239857
client_secret: uf1ie98f2kda2vu25uye3k1h

The response of the API will provide a token:

  "scope":"create delete"

The client can use the “access_token” to access the resource.

Refresh token

The access token provided by any other grant flow has an expiration time. The client can use the refresh token as a grant to fetch the access token after the access token is expired.

A refresh token generally has a longer expiry duration. With the refresh token, the client can get the access token without reauthorization from the resource owner.

The client needs to provide refresh_token, client_id and client_secret while using this flow. 

  1. The client tries to access the resource and get a response that the token is expired.
  2. The client uses the existing refresh token and requests the auth server for a new token.
  3. Auth server validates the refresh token and response with a new access token.
  4. The client uses this new token to access the resource
URL: https://auth-server.com/token
request params:
grant_type: refresh_token
client_id: 29352915982374239857
client_secret: uf1ie98f2kda2vu25uye3k1h

The response of API is the same as the access token.

Client Credential grant

This auth flow is used to grant the token outside the context of a user. The trusted client can use this to access resources that are not related to a user. 

  1. Client provides client id and client secret to auth server for an access token
  2. Auth server validates the client
  3. Auth server returns an access token
  4. The client uses the access token to access the resource
URL: https://auth-server.com/token
request params:
grant_type: client_credential
client_id: 29352915982374239857
client_secret: uf1ie98f2kda2vu25uye3k1h

The response of API is the same as the access token. 

Besides, the above grants there are other auth grants available too:

  • Implicit – Implicit grant flow provides the token directly without the code step. This grant flow is not recommended for security reasons.
  • Password – This flow is used by the trusted first-party client only. In this flow, the username and password are directly provided to the client. The client can directly use it to access the token.
  • Device Code

Oauth2 is a protocol that solves the deligation problem in a secure way. It is an industry-standard protocol. On top of the oauth2 is OpenID connect which helps in the authentication of a user. I will be writing about OpenID in my next blog.

More discussions on this can be found here https://news.ycombinator.com/item?id=20856443

Interested in learning Golang? Get started here: https://milapneupane.com.np/2019/07/06/learning-golang-from-zero-to-hero/