Oauth, OpenId and PKCE in simple form
Khanh Nguyen • 30 April 2022 •
Why should I read about Oauth ?
In containerize era, there'll be a gap between basic authentication, cookie session and Jwt. As how to solve them as the request was load balancing between various backend instance(or we would sacrifice high availability benefit somehow).
Therefore, is the some fundamental mechanism that we could use to overcome the issue ?
That's just one of various benefit of Oauth, an open standard for authorization and anyone can implement it. Ofcourse, the most convenience way would be using some famous library for each programing language. Unless you would like to make a multi millions dollars out of it(then this article was clearly not for you... loll).
I'm not gonna compare the benefit and downside of this standard comparing to others traditional way. But in most case we should adapt to the standard that widely accepted by almost every modern services and systems.
In this article, we'll focus on OpenId
, Authorization code flow
and Authorization code flow with PKCE
.
There was 2 versions of Oauth, which is the classic Oauth and the more modern Oauth 2.0
In this article, we only reference Oauth 2.0
Overview of Oauth
Opinionated best describe, easy to understand Oauth overview so far. Highly watching recommended.
Some useful terminology#
Resource Owner
: The user tried to access a targeted resource.Client
: The application that wants to access data (could be a webapp, mobile app, desktop app,...)Authorization Server
: A dedicated system responsible for authorize permission forResource Owner
to access data.Scope
: A collections of keywords that can be customized to allows the client application to specify what permission it needs. This collection was also specified onAuthorization Server
that it could understands.Consent
: Normally a page thatAuthorization Server
generated to let users know clearly what scope they want to have. These scopes later would be attached to theAccess Token
Resource Server
: A system(app, backend server,...) contain the targeted resource that user want to access.Authorization Grant
: Normally, a http request byAuthorization Server
respond back to the client that user cliked yes on the poped-up consent form.Redirect Uri
: When the request fromAuthorization Server
was made to the client, normally they need a redirectURI
, The one we provided forAuthorization Server
. Usually interchangeable withcallback Uri
Access Token
: Is what theClient
needs to access targeted resource fromResource Server
Id Token
: An Jwt Token that used to Identify (not authorize). Basically the same asAccess Token
but using for difference purpose and make a clear separate between authentication and authorization.Refresh Token
: Using for get theAccess Token
later directly from theAuthorization Server
, not require the whole complex flow, just a http request and respond, that's done.code_verifier
andcode_challenge
: The additional information that made PKCE
Authorization code flow
Simplified the consecutive flow would look like: User -> Client -> Authorization Server -> Authorization Code returned at the redirect URI -> Client exchange the code to access token with Authorization Server (which cannot protect Clietn credential) -> Access token were returned to Client -> Attach the token to access targeted resource.
This could be done entirely on front-end side, which the Resource Server
trust and using the same Access Token
as
Authorization Server
provided. But this mechanism required the client secret (which is kind of Client credential by
raw Client app Id and secret to be store on the client side, also mean no secure way to protect them).
Simplified the consecutive flow would look like: User -> Client -> Authorization Server -> Authorization Code returned at the redirect URI -> Client send the Authorization Code to backend side -> Backend side attach the Client Credential and exchange the Access token with Authorization Server -> Access token were returned to backend side -> Backend side return the Access Token to Client -> Attach the token to access targeted resource.
We could resolve this issue by secure the Client credential on the backend side, which mean the client would pass
the Authorization code
to backend side and it would attach the Client credential then exchange the Access Token
for the Client. That way, Client credential is secured.
Authorization code flow with PKCE
Understanding the Authorization code flow
was fundamental, PKCE is just an additinal ingredient that make the
whole flow more secure.
Let's say we have a mechanism that could generate a code_challenge
from a code_verifier
(they both usually is just a string),
that both client and server understand. Then the flow now would look like:
- User trying to login the Client app(or any action that trigger the flow).
- Client app creates a cryptographically-random
code_verifier
and from this generates code_challenge that we mention before. - Client app redirects the user to the Authorization Server along with the
code_challenge
. - Your
Authorization Server
redirects the user to the login and authorization prompt. - The user authenticates by using a login option and may see a consent page listing the permissions (scopes) will be given to the Client app.
- Authorization Server stores the
code_challenge
and redirects the user back to the callback URI on the client side with an authorization code, which is good for one use. - Callback Uri sends this code and the
code_verifier
(created in step 2) to the Authorization Server for exchange anAccess Token
. - Authorization Server verifies the
code_challenge
andcode_verifier
. - Authorization Server responds with an
ID Token
andAccess Token
(and optionally, aRefresh Token
). - Client app now can use the
Access Token
to call an API to access information about the user.
Pretty much the same as classic Authorization code flow
, and to secure client credential would also be the same when
using back-channel(backend side involve, code_challenge
and code_verifier
was still generated by client and code_verifier
would be pass to backend-side when it exchange for Access Token
).
OpenId Connect
So far, we just saw the whole flow serving authorization purpose but not the authentication purpose.
Then to separate these 2 purpose. There's a subset of standardized implementation called OpenId
appear.
Which provide the additional specific definitions:
- Id Token
- User Info endpoint (just for getting the user information)
- A standard set of scopes related to authentication purpose
- Standardized implementation
As we can see, the flow was pretty much the same as Authorization Code Flow
, except for the target Client was
asking here is Id Token
not Access Token
.
Conclusion
That's it, three flow but mostly the same so far. Just remember to understand clearly Authorization Code Flow
, we can
approach others flow easily. Including some others we're not mention here like Implicit flow
and Client credentials flow
.
Happy coding!