Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenID Connect for Dummies #2

Open
acappella2017 opened this issue Dec 15, 2017 · 0 comments
Open

OpenID Connect for Dummies #2

acappella2017 opened this issue Dec 15, 2017 · 0 comments
Labels

Comments

@acappella2017
Copy link
Owner

acappella2017 commented Dec 15, 2017

We have learned OAuth from"Julia's Pictures" in #1 . Let's refresh your memories before we start to talk about OpenID Connect.

A typical OAuth scenario: Julia has a lot of pictures stored in Pictures.py, she wants to use Print.py to print some of these pictures for her without giving her username/password in pictures.py.

OAuth resolves this issue by DELEGATION. Julia delegate permission to print.py. So print.py work on behalf of Julia to access her pictures at pictures.py.

Now Julia has a new requirement. She want print.py to print her pictures, besides that, she want print.py to add her name in each picture as a watermark.

A typical OpenID Connect scenario: Julia has a lot of pictures stored in Pictures.py, she wants to login Print.py with Pictures.py, let print.py print some of these pictures for her, and add her name as a watermark.

img_1605 3

Pretty easy, right? Let's go over the OAuth process, Julia authenticate with pictures.py, after several steps, print.py get an ACCESS_CODE from pictures.py and can use the ACCESS_CODE to get pictures from pictures.py.

Wait! In the whole process, print.py only hold the ACCESS_CODE (for a while), it knows nothing about Julia except the ACCESS_CODE which is meaningless to it. How can print.py print Julia's name at her pictures without know her pictures?

The problem turns to "How can print.py know Julia is Julia from Pictures.py?". Before OpenID Connect is introduced, people sometimes workaround this issue by adding Julia's username ( or other information they believe print.py may need) to ACCESS_CODE. Then print.py can parse the ACCESS_CODE and get the information they need.

Obviously it is not a good solution. ACCESS_CODE is intended to keep opacity to CLIENTs. That's why we need OpenID Connect. It provides a standard ( and also safe) way for print.py to obtain Julia's information from pictures.py.

Let's start a new play "Julia's Pictures - 2"

Cast of Characters:

Julia (Me! The End User, who owns a lot of cute pictures in pictures.py)

Print.py (The Relying Party, a website which can print pictures for people)

Pictures.py (The OpenID Provider, a website holds pictures)

Synopsis

Julia has a lot of pictures stored in Pictures.py, she wants to use Print.py to print some of these pictures for her without giving her username/password in pictures.py. Besides that, she want print.py to add her name in each picture as a watermark.

Scenes

Scene 1 ~ 4 is quite similar to the previous play. That's not a surprise. Because OpenID Connect is build on top of OAUTH2. I will highlight all the difference parts.

Scene 1 - Everything still starts with a GET

Julia (of course, her browser works for her) ask Print.py to print some pictures for her, and also print her name in every pictures as a watermark. The pictures are located at Pictures.py.
Print.py is happy to serve. But the hardest part is, how can he access pictures at Pictures.py? He has a great idea. He can send Julia to Pictures.py, then Pictures.py can ask for her permission directly!

img_1419

Scene 2

So Julia is redirected to Pictures.py by a 302 Redirection response from Print.py. Print.py sends a CLIENT_ID along with Julia, the CLIENT_ID is pre-registered at Pictures.py so that Pictures.py knows which client is asking for permission.

img_1422

Scene 3

Since Julia is not logged in Pictures.py, Pictures.py will ask her to login (By any means).
After that, Pictures.py asks Julia, Print.py wants to access your pictures and also your user profile? Are you allow?
If Julia says yes, Pictures.py created a AUTH_TOKEN for Print.py. it means "Julia has authorized Print.py to access my pictures and also my user profile".
img_1426

Scene 4

Julia gives the AUTH_TOKEN to Print.py. Now it is Print.py's turn to work!
img_1429

Scene 5 (New Scene!)

Print.py sends the AUTH_CODE to Pictures.py: "I have already got Julia's permission, could you let me access your pictures and Julia's user profile?"
Pictures.py verified the token, and send Print.py 2 different tokens:

img_1598

ID_TOKEN. It is a JSON Web Token which represent Julia's user profile.
ACCESS_CODE. The ACCESS_CODE is the last permission to access resources.

Let's take a closer look at the ID_TOKEN. It may look like this:

{
   "iss": "https://pictures.py",
   "sub": "Julia",
   "aud": "https://print.py",
   "exp": 2017-12-15, 22:00:00
   "iat": 2017-12-15, 20:00:00
   ...
  }

Now we know it is Julia who is accessing print.py!

Scene 6 (New Scene!)

ID_Token holds limited information. Print.py may want to know more informations about Julia, that's ok. Send the ACCESS_TOKEN to a specific endpoint in Pictures.py, then you can get additional informations!

img_1609

Scene 7 Don't forget the pictures

Of course, print.py can still use the ACCESS_CODE to get Julia's pictures. This is the same as in previous OAuth play.

img_1436

Scene 8 Happy Endings. Again!

img_1440

Q & A

Q: In scene 5, how does pictures.py know which token to be sent? ID_TOKEN, ACCESS_TOKEN, or both?
A: Oh, I missed this part in my illustration.

In OAuth protocol, a parameter SCOPE is used to define the authorization granted to the client. For example, when print.py is asking for permissions to access Julia's pictures, it may send request like this: SCOPE=read.pictures
OpenID Connect has a fixed SCOPE name for client to get user's public profile: SCOPE=openid
So pictures.py may work like this:

  • SCOPE=openid in parameter--> send ID_TOKEN
  • SCOPE=read.pictures in parameter-> send ACCESS_TOKEN
  • SCOPE=openid%20read.picutures in parameter ->send ID_TOKEN & ACCESS_TOKEN

Q : why we said OpenID Connect is for authentication + authorization? I didn't see the authentication part in your pictures?
A: When print.py get Julia's ID_TOKEN in scene 5, print.py usually created a user session for Julia. In this case, the ID_TOEKN works similarly as her password. You can consider it as "Julia uses her ID_TOKEN got from pictures.py to authenticate with print.py".

Further Readings

OpenID Connect 协议入门指南
http://www.jianshu.com/p/be7cc032a4e9

OpenID Connect
https://auth0.com/docs/protocols/oidc

OpenID Connect Scopes
https://auth0.com/docs/scopes/current

API Security: Deep Dive into OAuth and OpenID Connect
https://nordicapis.com/api-security-oauth-openid-connect-depth/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant