Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Oauth2 Explanation

OAUTH2

The Problem

I’m a web app that wants to allow other web apps access to my users’ information, but I want to ensure that the user says it’s ok.

The Solution

I can’t trust the other web apps, so I must interact with my users directly. I’ll let them know that the other app is trying to get their info, and ask whether they want to grant that permission. Oauth defines a way to initiate that permission verification from the other app’s site so that the user experience is smooth. If the user grants permission, I issue an AuthToken to the other app which it can use to make requests for that user's info.

Note on encryption

Oauth2 has nothing to do with encryption -- it relies upon SSL to keep things (like the client app’s shared_secret) secure.

Example Scenario:

Gmail wants to allow some 3rd party app, PrettyMail, to do stuff with its users’ information.

Gmail stores server-side:      PrettyMail stores server-side:      Note: client_id tracks the user of the
  oauth_clients: [               client_id: ABC                    oauth privileges, i.e., PrettyMail or 
    pretty_mail: {               shared_secret: XYZ                other web app -- not the end-users
      client_id: ABC
      shared_secret: XYZ
    }, ...]
  1. I visit PrettyMail and click “Login thru GMail”

  2. PrettyMail responds REDIRECT gmail.com/oauth2/auth?client_id=ABC&redirect_uri=prettymail.com/oauth_response -- note: also common to include ‘scopes’ in query -- i.e., the scope of the information that PrettyMail is asking to access

  3. gmail makes a session in which it stores provider (PrettyMail, based on client_id -- if client_id doesn’t refer to an authorized oauth_client, render an error) and redirect_uri and then responds:

    a. REDIRECT gmail.com/login (for a login form) if the user isn’t logged in, otherwise

    b. REDIRECT directly to step (4)

  4. gmail shows a page saying “PrettyMail (got that from the aforementioned session) wants to access this, that, and the other thing (again, ‘scope’ of access was stored in the session) about your Gmail account. Do you authorize?” You click “yup” and gmail:

  5. generates a one-time-use code that it associates with PrettyMail and the specified user and the requested scope (so it persists it until the next step) and REDIRECTs to the ‘redirect_uri’ it got in the first place, passing along that code: prettymail.com/oauth_response?code=big_long_thing

    Question: why not pass the AuthToken itself along at that step? Answer: so gmail can ensure that PrettyMail is indeed the requester of the access -- so far, all the requests gmail has gotten have come directly from the user, and the only information that identified PrettyMail was its client_id, which isn’t “secret” (i.e. an attacker could guess it). So GMail so far is confident that the user is ok with everything, but isn’t yet convinced that PrettyMail is really going to be the one using the Token. That’s where the next request comes in, in which PrettyMail identifies itself by including the shared secret.

    Other Question: rather than redirecting to a URL containing the code as a param, why not just send the final AccessToken to PrettyMail right then and there? Answer: (i’m guessing) the redirect basically “gives control” of the browser back to PrettyMail, so they can handle the request any way they want.

  6. PrettyMail takes the code and directly (i.e., not via a REDIRECT in the user’s browser, but via a server-to-server request) queries GMail with both code and shared secret, to prove its identity: GET gmail.com/oauth2/token?client_id=ABC&client_secret=XYZ&code=big_long_thing

  7. gmail verifies and then invalidates the code, and responds with an AccessToken, which PrettyMail can then use (until it expires) to make API requests on the user’s behalf (i.e., to get info about the user, and possibly to perform actions on behalf of the user, if that was in the agreed-upon ‘scope’ of the arrangement)

@LeeU1911

This comment has been minimized.

Copy link

LeeU1911 commented Jun 7, 2016

Hi,

Thanks for the explanation. I found this while searching for a problem related to OAuth2. This confirms pretty much my understanding about the protocol. There's one thing I'm trying to find out the answer: How does the UAA server (Gmail in your example) manage and expires session coming from different user-agent (browser) - not the client, which is the PrettyMail app?

Let's say after step 7, I close my browser, and clear the cache. Then I open up another browser window and launch PrettyMail again. Will I be redirect to login page again?

Thanks,
Vu

@vhmth

This comment has been minimized.

Copy link

vhmth commented Aug 11, 2016

@LeeU1911 I'm assuming a couple things:

  1. That you when you say "clear the cache", you also mean cookies.
  2. PrettyMail is using OAuth as a method of logging someone into their system. That is "login via Facebook or Gmail or whatever".

In this case, you will indeed need to go through this flow again in order for PrettyMail app to be able to identify that you are who you say you are in their own database. Likely they are storing some user/profile id that Gmail returns them in an authenticated call in order to verify that you are PrettyMail user #100 which corresponds with Gmail user #10000 (if you get what I'm saying).

@Vaccano

This comment has been minimized.

Copy link

Vaccano commented Oct 18, 2017

Not sure if this is too old for a question, but here it is.

How did PrittyMail get the shared secret in the first place?

At first I thought the code/Token WAS the shared secret. But you example make it clear that it is not.

Does PrittyMail just say to GMail "hey, I would like a shared secret" before everything else happens?

@dmwyatt

This comment has been minimized.

Copy link

dmwyatt commented Oct 22, 2017

@Vaccano When PrettyMail sets up a Google API account with Google, Google gives you the client_id and shared secret.

@koo9

This comment has been minimized.

Copy link

koo9 commented Nov 15, 2017

@dmwyatt good answer. think it should be included in this write up. excellent explanation btw.

@nirmand

This comment has been minimized.

Copy link

nirmand commented Dec 22, 2017

Very concise and very informative document for oauth protocol. Infact, point #5 is something which clears a lot of confusions. Great explanation.

@ghost

This comment has been minimized.

Copy link

ghost commented Feb 21, 2018

Thanks for the explanation, now it's well understood

@vegaasen

This comment has been minimized.

Copy link

vegaasen commented Mar 21, 2018

Great summary. However, the version could be extended with an refresh token scenario as well :-).

@hexad

This comment has been minimized.

Copy link

hexad commented May 27, 2018

Thanks a ton!

Though i have a question. Can a passport.js server has access to my social media accounts with Oath?

Let's say a server runs node.js and passport.js. Then a user authenticates with OATH2, for example let's say facebook. After the client logs in, in his own browser, if he goes to facebook.com, he will say his profile page. Now, if the server that runs passport.js visits facebook.com, will he see the login/signup page, or will he see the user's profile page?

@ALOK4002

This comment has been minimized.

Copy link

ALOK4002 commented Jun 6, 2018

Nice article.
One question regarding the redirect url: does pretty mail has to register it with google first or is it part of authentication request to google along with client Id?

@rafaeleyng

This comment has been minimized.

Copy link

rafaeleyng commented Jul 18, 2018

👏 Very nice explanation!

A little question: where it reads GET gmail.com/oauth2/token?client_id=ABC&client_secret=XYZ&code=big_long_thing, shouldn't it be shared_secret instead of client_secret?

@tamirOK

This comment has been minimized.

Copy link

tamirOK commented Aug 17, 2018

@rafaeleyng, as dmwyatt mentioned, shared_secret is given to PrettyMail when it set up Gmail API

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.