OAuth 2.0 and OpenID Connect

OAuth 2.0 and OpenID Connect

What is OAuth 2.0 ?

To understand OAuth, let us take this classic example of photo printing service you must have seen websites like this where you give them an image file and you pay them to ship printed photos to your home address. Imagine you're starting a new photo printing business that lets people upload photos to your website and they can order prints of these photos. you code your website and apply the people sign up everything is good but nobody keeps photos on their machines anymore they use the cloud and so you keep getting this feature request to provide users the ability to import their photos from somewhere like Google Drive and then print it directly from there without the users having to download and upload again. Now what do you have to do to implement this import from Google Drive feature in your application. You need to connect to the users Google Drive account and access their files but how can your application do that. The users files on Google Drive need Google authentication how can you write code for your website that can authenticate with Google on behalf of your users well. You can ask the user for their Google ID and password you can say hey user do you want me to print your photos on Google. Google doesn't give me access, so here's my screen where you enter your Google ID and password you just give them to me I will log into your Google account and access your photos and print them. It'll work in theory but do you think users will give you their Google ID and password. no they probably won't because they don't trust you what they want to give you is access to just certain photos. They don't want to give you access to their whole Google Drive and email and everything else. Now you can say to your user I promise to access just your files that you mentioned and I promise to throw out the password after I'm done I'm totally not saving that but there's no guarantee that this service is gonna do that. So now we can say Google Drive has a share feature you can ask the user to share the files out and then give the link to them in your service but there are problems here what if the users don't want to share files out to anyone also what if it's a different scenario where sharing isn't an option. For example - Think of the scenario where your service wants to access the list of your users friends to send invites to the application there's no way you can ask the user to share their address book such a feature just doesn't exist. So how do you have a third party service authorize with the Google address book service as your user without the user providing their credentials. This is where OAuth comes in to solve this problem of services trying to access each other on behalf of the user. There was the standard created called OAuth. There was a version 1.0 of the standard but the current version is the most widely used this is OAuth 2.0.

Different identity use case

  • Simple Login -> Forms and Cookies
  • Single Sign On across site -> SAML
  • Mobile App Login -> Authorization code through PKCE
  • Delegated Authorization -> OAuth

We will focus on Delegated authorization as it will cover the whole OAuth perspectives.

Delegated Authorization with OAuth 2.0

We will start with user like you and me who wants to login in to some website called yelp.com

So you have trust on google and you have a little trust on yelp.com and you want this site to just access my contacts but you don't want to give them enough access to let them delete your contacts.

Oauth1.PNG

When user will click on this connect with Google link, user would go to the OAuth flow. It's basically the set of steps that ultimately results in the application being able to access that information or having the authorization to access that information.

oauth2.PNG

This diagram illustrate at high level how this flow works.

So, if the user clicks on this link user will be redirected to google domain accounts.google.com then user will enter the email and password. Now it's little safe as we are sharing the email and password with google.com an not yelp.com

Assuming you logged in successfully, there you get a prompts that says this application yelp is trying to access your list of things. are you sure you want to allow this? Yes or No So users explicitly have to give their consent to whatever they are granting access.

Assuming user click Yes then browser will be redirected back to yelp.com. The application called a callback or redirect URI. That application is the allowed to go an talk to some other APIs like google contacts API.

OAuth 2.0 Terminology

  1. Resource Owner
  2. Client
  3. Authorization Server
  4. Resource Server
  5. Authorization Grant
  6. Redirect URI
  7. Access Token

Resource Owner :-

You, me and number of users who owns the data would give the permission to other application to access their data from google.

Client :-

We are using yelp.com here as an example. so Yelp.com would be a client.

Authorization Server :-

It is a system that you can use to say "Yes I authorize this permission"

Resource Server :-

It is the API or the system that actually holds the data that clients wants to get.

Sometimes the Authorization server and the Resource server are same thing.

Authorization Grant :-

It is a thing that basically proves that user has clicked yes when asked for permission or allow you to have this permission.

Redirect URI :-

The url that we give when user get the permission from the Resource server using the Authorization grant and get back to the site where we have started like yelp.com

Access Token :-

An access token is an object encapsulating the security identity of a process or thread. A token is used to make security decisions and to store tamper-proof information about some system entity. While a token is generally used to represent only security information, it is capable of holding additional free-form data that can be attached while the token is being created.

At higher level client needs something called Access Token.

oauth3.PNG

Because of this access token, client can have the access to the contacts but instead of getting the contacts if they try to delete your contacts they couldn't delete your contacts because you have given the permission to just access the contacts and access token generated according to your permission. so using that access token user can just access your contacts.

Now we want some way of being very granular, have specific permission that we can turn on or off.

More OAuth 2.0 Terminology

  1. Scope
  2. Consent

Scope is a specific permission you want to give to the users. for example it can be read contacts, write contacts. when we define the scope user will be allowed to take the information.

List of permission that client is asking for is then used by authorization server to generate that consent screen that is presented to the users that says yelp.com is asking for the permission to do XYZ. Users give an explicit ability to consent or not consent to that particular list of contacts.

For example, Facebook changed the authorization service recently to be really explicit about let you know weather or not an application that you are giving access is to allowed to post on your wall because earlier it was not clear after connecting will they just get your information or they are going to spam you facebook wall with each and every post. Now Facebook made it very granular.

oauth4.PNG

More OAuth 2.0 Terminology

  1. Front Channel (Less secure channel)
  2. Back Channel (High secure channel)

Back Channel

If your server code is running on your server which only you have access to and you can make an API request or some other HTTP request from your server to another server like Google's API and that is going over HTTP, SSL encrypted, no one can intercept that communication. it's highly secure, that's what we call as a Back Channel.

Front Channel

Your Browser can be considered as a front channel, where your browser is secure but there might be loopholes or there is some place where stuff could leak from the browser.

Suppose you are building a web application and you want to store a secret password or any secret key in your web application. If you put it in HTML or JavaScript of your web application then anybody could just right click and view the source code and can see the secret key. That's why browser is considered as Front Channel and less secure.

Why we have to get Authorization code and then exchange that for Access Token

As you would go through this OAuth flow you will find out that the flow is designed including the reason why we have to get the authorization code and exchange that for access token is designed to take the advantages of best things about front channel and back channel to make it more secure.

Authorization code gets exchange with access token at authorization server so that no one could steal that access token and access our information in wrong way.

Some key points regarding the Flow

  • Access Token is very sensitive information.
  • Front channel is used to interact with the user.
  • The last step of the flow happened at back channel.

Starting the flow

client_id=abc123&
redirect_uri=https://yelp.com/callback&
scope=profile&
response_type=code&
state=foobar

Client Secret will be on authorization server

Calling Back / Redirect URI

https://yelp.com/callback?
error=access_denied&
error_description=The user did not consent.


https://yelp.com/callback?
code=oMsCeLvIaQm6bTrgtp7&
state=foobar

Exchange code for Access Token

POST www.googleapis.com/oauth2/v4/token
Content-Type: application/x-www-form-urlencoded
code=oMsCeLvIaQm6bTrgtp7&
client_id=abc123&
client_secret=secret123&
grant_type=authorization_code

Authorization server returns an Access Token

{
"access_token": "fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"token_type": "Bearer",
}

Use the Access Token

GET api.google.com/some/endpoint
Authorization: Bearer fFAGRNJru1FTz70BzhT3Zg

oauth5.PNG

Different types of OAuth 2.0 flows

  • Authorization code (front channel + back channel)
  • Implicit (front channel only)
  • Resource owner password credentials (back channel only)
  • Client credentials (back channel only)

We use the Implicit flows when we have pure JavaScript or Angular web application which doesn't have any backend server.

oauth6.PNG

Although it's less secure but anyway just make sure no body could steal your access token, try to hide it in front end only.

Identity use cases (Earlier)

• Simple login – OAuth 2.0 Authentication • Single sign-on across sites – OAuth 2.0 Authentication • Mobile app login – OAuth 2.0 Authentication • Delegated authorization – OAuth 2.0 Authorization

OAuth 2.0 was originally invented for Authorization but later company like google, facebook and twitter started using in Authentication also by making some changes on the top of the OAuth 2.0.

Problems with OAuth 2.0 for authentication

• No standard way to get the user's information • Every implementation is a little different • No common set of scopes

The reason why we shouldn't use the OAuth 2.0 for Authentication because there is no standard of getting the user info in OAuth 2.0

OAuth 2.0 and OpenID Connect

To standardize the Authentication to get the user information on top of OAuth 2.0, OpenID Connect came in picture.

What OpenID Connect adds to OAuth 2.0

  • ID token
  • UserInfo endpoint for getting more user information
  • Standard set of scopes
  • Standardized implementation

oauth7.PNG

OpenID Connect authorization code flow

oauth8.PNG

Starting the OpenID flow

https://accounts.google.com/o/oauth2/v2/auth?
client_id=abc123&
redirect_uri=https://yelp.com/callback&
scope=openid profile&
response_type=code&
state=foobar

Exchange code for access token and ID token

POST www.googleapis.com/oauth2/v4/token
Content-Type: application/x-www-form-urlencoded
code=oMsCeLvIaQm6bTrgtp7&
client_id=abc123&
client_secret=secret123&
grant_type=authorization_code

Authorization server returns access and ID tokens

{
"access_token": "fFAGRNJru1FTz70BzhT3Zg",
"id_token": "eyJraB03ds3F..."
"expires_in": 3920,
"token_type": "Bearer",
}

ID token is just a token encoding the bunch of information. it's also called as JWT.

it looks something like gibberish words but underneath it contains all the information of the users.

Example of ID Token or JWT

eyJhbGciOiJSUzI1NiIsImtpZCI6IkRNa3Itd0JqRU1EYnhOY25xaVJISVhu
YUxubWI3UUpfWF9rWmJyaEtBMGMifQ
.
eyJzdWIiOiIwMHU5bzFuaWtqdk9CZzVabzBoNyIsInZlciI6MSwiaXNzIjoi
aHR0cHM6Ly9kZXYtMzQxNjA3Lm9rdGFwcmV2aWV3LmNvbS9vYXV0aDIvYXVz
OW84d3ZraG9ja3c5VEwwaDciLCJhdWQiOiJsWFNlbkx4eFBpOGtRVmpKRTVz
NCIsImlhdCI6MTUwOTA0OTg5OCwiZXhwIjoxNTA5MDUzNDk4LCJqdGkiOiJJ
RC5oa2RXSXNBSXZTbnBGYVFHTVRYUGNVSmhhMkgwS2c5Ykl3ZEVvVm1ZZHN3
IiwiYW1yIjpbImtiYSIsIm1mYSIsInB3ZCJdLCJpZHAiOiIwMG85bzFuaWpr
aWpLeGNpbjBoNyIsIm5vbmNlIjoidWpwMmFzeHlqN2UiLCJhdXRoX3RpbWUi
OjE1MDkwNDk3MTl9
.
dv4Ek8B4BDee1PcQT_4zm7kxDEY1sRIGbLoNtlodZcSzHzXU5GkKyl6sAVmdXOIPUlAIrJAhNfQWQ-
_XZLBVPjETiZE8CgNg5uqNmeXMUnYnQmvN5oWlXUZ8Gcub-GAbJ8-
NQuyBmyec1j3gmGzX3wemke8NkuI6SX2L4Wj1PyvkknBtbjfiF9ud1-
ERKbobaFbnjDFOFTzvL6g34SpMmZWy6uc_Hs--n4IC-ex-
_Ps3FcMwRggCW_-7o2FpH6rJTOGPZYrOx44n3ZwAu2dGm6axtPIsqU8b6sw7DaHpogD_hxsXgMIOzOBMbYsQEiczoGn71ZFz_1O7FiW4dH6g

If you paste this value in jwt.io , you will get a lot of information contained by this jwt.

There is different segment of this id token like header portion, signature portion and payload portion.

  • Header
{
  "alg": "RS256",
  "kid": "DMkr-wBjEMDbxNcnqiRHIXnaLnmb7QJ_X_kZbrhKA0c"
}
  • Payload
{
"iss": "https://accounts.google.com",
"sub": "you@gmail.com",
"name": "Nate Barbettini"
"aud": "s6BhdRkqt3",
"exp": 1311281970,
"iat": 1311280970,
"auth_time": 1311280969,
}

Signature can be used to verify the ID Token has not been modified or compromised or rather changed in any way.

Identity use cases (Today)

• Simple login – OpenID Connect Authentication

• Single sign-on across sites – OpenID Connect Authentication

• Mobile app login – OpenID Connect Authentication

• Delegated authorization – OAuth 2.0 Authorization

OAuth OpenID Connect

oauth9.PNG

Which flow (grant type) should we use?

  • Web application w/ server backend: authorization code flow
  • Native mobile app: authorization code flow with PKCE
  • JavaScript app (SPA) w/ API backend: implicit flow
  • Microservices and APIs: client credentials flow

Example: web application with server backend

oauth10.PNG

Example: native mobile app

oauth11.PNG

Example: SPA with API backend

oauth12.PNG

Example: SSO with 3rd-party services

oauth13.PNG

Token validation

  • The fast way: local validation
  • Check expiration timestamp
  • Validate cryptographic signature
  • The strong way: introspection

oauth14.PNG

Keeping the user signed in

For both local validation and introspection, the token is invalid once it expires, so:

  • If there's a user at the keyboard, just redirect through the
  • authorization server again.
  • If there's no user (automated tasks), request a refresh token (offline scope).

Thank you for reading out this blog! I hope now you have very good understanding of OAuth 2.0 and OpenID Connect.

Did you find this article valuable?

Support Hussain Code by becoming a sponsor. Any amount is appreciated!