- Why you may want to read this article
- Definitions and Terms
- Purpose
- Flow
- Authorization Grants & Flow
- Endpoints
- Access & Refresh Tokens
- DEMO
Why you may want to read this article
Attention!
This article is about definitions and abstract understanding and flow of OAuth for those who struggle with RFC understanding. The concrete flows with implementation (Authorization Code, Client Credentials, etc) will be discussed in subsequent articles.
For better understanding - you could go to my previous article for definitions and basic flows of auth that were discussed.
During the article, the main source of information is my experience + official RFC
This topic is one of the hardest for understanding. After 3 projects that were using OAuth
+ OpenId Connect
, after researching .NET Core source code
, etc eventually I got some understanding.
This article is addressed to me in the past. I’ll show the easy and simple way to understand OAuth, on top of that we will implement OAuth flow on our own: Resource Server + Authorization Server + Client in the subsequent articles.
Definitions and Terms
Server - the piece of software running on some hardware. In the scope of this article, this software should be able to receive requests and respond to them via HTTP protocol.
Authentication
- from basics article
Authorization
- from basics article
As explained in the article above we will use auth
term most of the time referring to authentication
& authorization
.
Resource Owner
- the user that has access to Resource Server.
Resource Server
- the server that is hosting and serving protected resources. In scope of the article, this server should be able to verify Access Token and decide what resources the Client has access to.
Authorization Server
- the server authenticates Resource Server and issues Access Tokens to be used by Client. It could exchange Refresh Tokens for Access Tokens.
By the OAuth specification, the communication between Authorization Server and Resource Server is not mentioned. They could be different servers, they could be 2 entities inside one server.
Client
- the application that communicates with Resource Server and Authorization Server on behalf of Resource Server. It could be Mobile, Desktop, and Web Applications..
Third-party application
- the application which is isolated from Resource Server, typically developed by another team in another scope, but in our case wants to use Resource Server API.
User Agent
- almost always it is browser, as mentioned in rfc
Authorization Grant
- Client ’s credential that Client will exchange with Authorization Server to get an Access Token. Since there are 4 flows of OAuth protocol there are 4 Authorization Grants.
Access Token
- the credential (a string of symbols usually) used to access protected resource. Resource Server should be able to verify them.
Refresh Token
- the credential used to obtain Access Token without initiating full OAuth flow again.
Giving more real-world examples:
We have a third-party
mobile application (or web) that communicates to Google Calendar API.
The user (Resource Owner
) is making or following OAuth protocol by authenticating itself in Google (Authorization Server
). After Google verifies the user (Resource Owner
) it provides the mobile application (Client
) an Access Token.
The user (Resource Owner
) then sends the request to Google Calendar API (Resource Server
) with Access Token via mobile application (Client
) to interact with protected resources (Google Calendar data like events, tasks, reminders, etc).
Example from RFC:
“ For example, an end-user (resource owner) can grant a printing service (client) access to her protected photos stored at a photo- sharing service (resource server), without sharing her username and password with the printing service. Instead, she authenticates directly with a server trusted by the photo-sharing service (authorization server), which issues the printing service delegation- specific credentials (access token)”
Purpose
Historically the main use case for OAuth was solving auth problems that come up with third-party applications.
So, imagine we have developed a photo storage web application. There is a user (Resource Owner
) and photo storage (Resource Server
). Resource Owner
can directly access Resource Server
by authenticating let’s say by username + password.
Now some third-party applications, developed by other guys would like to use photo storage.
They have NO choice other than just to get a username + password from Resource Owner and use those credentials to interact with photo storage.
This brings some problems:
- Most probably for convenience third-party applications store credentials (e.g. username + password)
- Servers are required to support credentials authentication (to use them in Resource Server authentication)
- The resource server has access to Resource Owner credentials, so Resource Owner has no control over it, he cannot revoke access.
- Compromising credentials in one third-party application - leads to compromising those credentials in all apps that used those.
OAuth was introduced to address those problems. It uses separate credentials for third-party apps rather than Resource Owner’s credentials. Those Client credentials will be exchanged in some way with the Authorization Server for Access Token, during that process Resource Owner will grant necessary permissions for the Client. The Client then will make all requests with this Access Token.
Flow
The first thing that brings you close to understanding OAuth
is that it is not a protocol for authentication
. So it does not explain how you can authenticate users with login & password or any other way.
The OAuth is about using first-party applications that already have authentication mechanisms in place by other third-party applications. Mainly you will use this when you would like to use data of the user that is inside a first-party application by your third-party application.
Later on with OpenId Connect borning it became closer to authentication itself on top of OAuth.
Generally, we have the following use case: there is Resource Owner who wants to use some Client (third party) that required Resources from Resource Server.
The general flow
:
- The
Resource Owner
wants to useClient
(third-party) and starts interacting with it. Theclient
needs Resource fromResource Server
. - The
Client
redirects toAuthorization Server
to authenticate theResource Owner
- Once
Resource Owner
is authenticated theAuthorization Server
sends Access Token toClient
. - The
Client
performs operations with Resources using Access Token
Authorization Grants & Flow
There are 4 main flows and consequently 4 Authorization Grants for OAuth protocol: Authorization Code
, Implicit
, Resource Owner Password Credentials
, and Client Credentials
.
They differ in security guarantees, performance implications, and amount of actors (e.g. Client Credentials does not have Resource Owner in place).
I personally differentiate the flows by
Browserfull
(Authorization Code and Implicit). They require Client to be able to use Browser (User Agent).Browserless
(Resource Owner Password Credentials and Client Credentials). They don’t require to use Browser and could be used from servers using plain HTTP.
Authorization Code
One of the safest grant types. Canonically required browser (user agent according to specification).
To make a better separation of concepts, let’s say, that the Client in our case is a mobile app. Because the first time I was discovering OAuth I didn’t understand the separation between User Agent
and Client
.
Basically, the flow is the following:
- The
Resource Owner
goes to the third-party application (Client
) and initiates some operation that needsResource Server
data. - The
Client
initiatesResource Owner
authentication: it directsResource Owner
toAuthorization Server’s
login page via browser. By doing this theClient
authenticates itself (notResource Owner
) with theAuthorization Server
. - The
Resource Owner
authenticates with theAuthorization Server
usually with login and password, and also he grants access to Resources for theClient
. - The
Authorization Server
redirectsResource Owner
(which is in the browser now) to theClient
withAuthorization Code
via mobile deep linking. If it is a browser - then it redirects to the web app (browser as well). - The
Client
makes a request to exchange theAuthorization Code
forAccess Token
. - The
Client
makes a request toResource Server
with Access Token to get data on behalf of theResource Owner
.
Implicit
Implicit flow is basically the same as Authorization Code, except it does not authenticate the Client, it only authenticates Resource Owner. This implies some Security drawbacks against Authorization Code flow.
- The
Resource Owner
goes to the third-party application (Client
) and initiates some operation that needs Resource Server data. - The
Client
initiatesResource Owner
authentication: it directsResource Owner
toAuthorization Server’s
login page via browser. By doing this theClient
authenticates itself (notResource Owner
) with theAuthorization Server
. - The
Resource Owner
authenticates with theAuthorization Server
usually with login and password, and also he grants access to Resources for theClient
. - The
Authorization Server
redirectsResource Owner
(which is in the browser now) to theClient
withAccess Token
via mobile deep linking. If it is a browser - then it redirects to the web app (browser as well). - The
Client
makes a request to Resource Server withAccess Token
to get data on behalf of theResource Owner
.
Resource Owner Password Credentials
The simplest and weakest from a security standpoint flow.
The Client
gets the Resource Owner’s
credentials and authenticates him with the Authorization Server
. The Authorization Server
returns Access Token in that case.
Good question what this flow solves in the first place?
The client has access to Resource Owner’s credentials. But this flow allows the Client to not remember credentials. It uses credentials only once per user session to get Access Token.
On top of that, this is a good flow if you are migrating Clients from Basic or Digest authentication to OAuth.
- The
Resource Owner
goes to the third-party application (Client
) and initiates some operation that needsResource Server
data - The Client sends
Resource Owner’s
credentials via HTTP (without the need of a browser). As a response, it receives Access Token. - The Client makes a request to
Resource Server
withAccess Token
to get data on behalf of theResource Owner
.
Client Credentials
This flow is used usually without Resource Owner, or where the Client is Resource Owner
.
The Client authenticates itself with the Client’s credentials with the Authorization Server. The Authorization Server gives the Client the Access Token that is used to interact with Resource Server.
This flow should ONLY be used for Confidential Clients (not web-based applications and not mobile-based applications). Mostly it means the usage of Server2Server communication with HTTP-only interaction.
- The
client
authenticates itself with theAuthorization Server
. Usually, it is Basic authentication with client credentials (client id + client password). It receives Access Token in response. - The
Client
makes a request toResource Server
with Access Token to get data.
Endpoints
Authorize Endpoint
The endpoint is implemented in Authorization Server.
This endpoint should authenticate Resource Owner. After this, its behavior depends on Authorization Grant (Flow)
From RFC:
“The authorization endpoint is used to interact with the resource
owner and obtain an authorization grant. The authorization server
MUST first verify the identity of the resource owner. The way in
which the authorization server authenticates the resource owner
(e.g., username and password login, session cookies) is beyond the
scope of this specification.
”
This endpoint is only used by the Authorization Code
and Implicit
grant types. For Resource Owner Password Credentials and Client Credentials the Token Endpoint is used directly.
Redirect Endpoint
The endpoint is implemented in Client.
This is the endpoint on the Client where Authorization Server redirects the user after authentication.
This endpoint MUST be registered in OAuth provider, to be validated when redirection is performed. Otherwise, it is vulnerable to an Open Redirection attack, when an attacker can set up a redirect endpoint to its own and get sensitive information.
Token Endpoint
The endpoint is implemented in Authorization Server.
This endpoint is used by Client to get an Access Token.
Access & Refresh Tokens
The Authorization Token
could be some identifier for authorization information that will be retrieved, or it could be a self-containing verifiable pack of data (data + signature). Most usually we mean Bearer tokens.
The Refresh Token
is a token that the Client could exchange to renew an expired Access Token.
DEMO
For this demo:
My application is a third-party app (web application), and we can name it the Client
. I think we even can name my PC as my Client from a device standpoint, it does not matter much.
I - am Resource Owner
, because I have an account in GitHub and some data I would like to interact with through my client (my application).
GitHub API - is Resource Server
that contains profile data I would like to have access to.
GitHub itself - is Authorization Server
. I mean not the whole GitHub, but you will see Authorization requests that go to the GitHub domain.
In this demo, I will demonstrate the Authorization Code flow with Github. you could see Github source code
Steps of registering Client in Github are omitted - you easily can find them by googling.
Let’s launch the application.
Not Authenticated Resource Owner
Open the browser in incognito mode.
Let’s click on “Authorize via Github“.
You should see now Github login page.
The first request here is Authorize Endpoint (https://github.com/login/oauth/authorize) request
We have sent client_id
, redirect_uri
, scope
and state
. The Authorization Server recognizes that we are not signed to GitHub now, so it returns a 302 Found status code with “location” header that points to the Authentication endpoint (https://github.com/login) in Github to authenticate the Resource Owner (me).
Login request returns us HTML of login page
We should authenticate (submit login & pass) then you will see https://github.com/session request that sends your credentials to GitHub’s Authorization Server.
After that “session” request, from “location” header it will redirect us to our Authorize Endpoint (https://github.com/login/oauth/authorize) again, but with authentication cookies this time.
Then it will send callback to our “redirect_uri” (https://localhost:7000/signin-github) with Authorize Code.
Already Authenticated Resource Owner
Let’s launch our application inside the browser that already authenticated in GitHub account.
Click “Authorize via Github”
We will send the first request to Authorize Endpoint (https://github.com/login/oauth/authorize).
We got 302 Found status code with “location” that points to our “redirect_uri” (https://localhost:7000/signin-github) already. This is because we already have authentication cookies for GitHub in browser.
Use Access Token
Then we handled callback (redirect_uri) (https://localhost:7000/signin-github) in our server:
We got Authorization Code and State from the query parameters.
Line 27: we sent a request to the Token endpoint to exchange Authorization Code for Access Token:
Line 36: we sent a request to GitHub API with Access Token to get user data
Then we just put the response from Github Api as a response to our callback (to show it in the browser).
Please subscribe to my social media to not miss updates.: Instagram, Telegram
I’m talking about life as a Software Engineer at Microsoft.
Besides that, my projects:
Symptoms Diary: https://symptom-diary.com
Pet4Pet: https://pet-4-pet.com