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 Ownerto 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 Serverthat it could understands.Consent: Normally a page thatAuthorization Servergenerated to let users know clearly what scope they want to have. These scopes later would be attached to theAccess TokenResource Server: A system(app, backend server,...) contain the targeted resource that user want to access.Authorization Grant: Normally, a http request byAuthorization Serverrespond back to the client that user cliked yes on the poped-up consent form.Redirect Uri: When the request fromAuthorization Serverwas made to the client, normally they need a redirectURI, The one we provided forAuthorization Server. Usually interchangeable withcallback UriAccess Token: Is what theClientneeds to access targeted resource fromResource ServerId Token: An Jwt Token that used to Identify (not authorize). Basically the same asAccess Tokenbut using for difference purpose and make a clear separate between authentication and authorization.Refresh Token: Using for get theAccess Tokenlater directly from theAuthorization Server, not require the whole complex flow, just a http request and respond, that's done.code_verifierandcode_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_verifierand 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 Serverredirects 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_challengeand 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_challengeandcode_verifier. - Authorization Server responds with an
ID TokenandAccess Token(and optionally, aRefresh Token). - Client app now can use the
Access Tokento 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!