OAuth Grant Types

There are several ways to authenticate when requesting a Token, for a good overview of them checkout https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified.  The most common types are:

  • Authorization Code - For web applications, run on the server.  Also referred to as "Trusted Application"
  • Implicit - For mobile or javascript applications, run on the client.  Also referred to as "Untrusted Application"
  • Resource Owner Password Credentials - Used when the users password is stored in the application, useful for scheduled events like backup scripts or "canonical" apps.
  • Client Credentials - For actions not invoked by a User or when user authentication is done by the Application and any required user details are passed to the backend in the payload.
  • SAML2 Bearer Assertion - Allows the web application to pass along the assertion it received from the user signing into SSO.

Client Credentials are the simplest to implement and therefore a good starting point.

Terms

Speaking about the OAuth flow it is important to clearly define some of the common terms. The terms used throughout this document are defined below.

Terma.k.aDefinition

Example

Resource
The protected data or service.Mary's Facebook Account.

Resource Owner

UserThe entity that grants permission to use a Resource.  Often also the user of the application.Mary

Resource Server

API ServerThe server that hosts the Resource.Facebook's Data Server

Client

ApplicationThe application that wants to use the Resource.GreetingCardMaker
Authorization ServerToken Manager

The server responsible for authenticating the Resource Owner and determining their concent.

The Resource Server trusts the Authorization Server and they are almost always run by the same organization.

Often the Resource Server and Authorization Server are the same thing.

Facebook's OAuth Server
Client ID & SecretApp Username/Password

The credentials that a Client application uses to authenticate with the Authorization Server.

These are usually generated when the Client is registered with the Authorization Server.


Username & Password
The credentials that the Resource Owner uses to authenticate with the Authorization Server.

Mary's Facebook

username and password.

OAuth TokenBearer Token

A short lived token that is issued to the Client by the Authorization Server after authenticating and getting permission from the Resource Owner.

A short random string.
Authorization GrantGrant Code

A representation of the Resource Owner's consent for the Resource to be released to a Client.

The Authorization Grant is provided by the Client to the Authorization Server (along with the Client ID & Secret) in exchange for an OAuth Token.

Each Authorization Grant is limited to a specific Client, Resource Owner and Scope.

A short random string.
Scope
A subset of the Resource.

Facebook Photo's,

Contacts, Status etc.

Authorization Code - Trusted Application

Authorization Code is the most commonly used form, it is used by giants like Facebook and Twitter.  First the application authenticates with the Server, then the user is asked if they allow their data to be released to the application.  This authentication and permission are translated by Server to an access token.

In some Authorization Server implementations it is considered redundant to ask the Resource Owner for consent and authentication is considered consent.  This is the case for UCSD's API Manager; it was determined that users wouldn't know why they were being asked the question and that the answer should always be yes, so the option is never presented.

Flow:

  1. The Client ID & Secret are compiled into the application. 
  2. Users of the application are sent to the Authorization Server to provide their consent.  The Client ID and requested Scope are encoded in the url.
  3. The Authorization Server returns a Authorization Grant to the Client.
  4. The Client gives the Authorization Grant and Client ID & Secret to the Authorization Server.
  5. The Authorization Server returns a OAuth Token.
  6. The Client invokes api on the Resource Server, passing along the OAuth Token.

Example:

Pros and Cons:

  • The Client Secret must be stored in the application.  If the source of the application is readable then this option won't work.
  • The User must be present to grant consent.  Although most Authorization Servers save the Resources Owners preferences.

Implicit - Untrusted Applications

The implicit Grant type is designed specifically for instances where the Client cannot securely store the Client Secret, such as with HTML/Javascript apps.  Because the Client cannot authenticate with the Authorization Server to retrieve the OAuth Token, it is instead passed on the URL of the Client when the user is returned from the Authorization Server.  The OAuth Token will be an Anchor Parameter (Fragment Identifier) in order to reduce the exposure; when rendering a URI the browser does not include the Fragment Identifier when fetching the resource, but it is available to JavaScript that runs in the returned page.

Flow:

  1. Users of the application are sent to the Authorization Server to provide their consent.  The requested Scope is encoded in the url.
  2. The Authorization Server redirects the browser to the Client's callback URL with the OAuth Token as a fragment identifier.
  3. The Client extracts the OAuth Token from the browsers location.
  4. The Client invokes APIs on the Resource Server, passing along the OAuth Token.

Example:

Pros & Cons

  • TheClient Secret does not need to be compiled into the application.  This enables it to run in untrusted environments, like the user's browser.
  • The OAuth Token is passed as part of the URI, not in a response body. 
    • Traditionally the URI is considered less secure than the body, for example webservers often log the incoming URIs but not message bodies.
    • The following facts/choices help mitigate the security concerns:
      • The Fragment Identifier does not get passed to the web server, so it cannot be logged.
      • SSL encrypts everything in the URI except the host and port.  The Fragment Identifier is encrypted during transport.
    • The major remaining concern is the browser history, see below.

Browser History Attack

The largest vulnerability that we have identified is that browsers often store URI's in their history.  This history persists across browser restarts, which allows the following attack.

  1. User Alice launches a browser and accesses an application that uses Implicit Grant type.  Alice is issued a OAuth Token which the JavaScript client stores in a cookie.  The token is valid for 15min.
  2. Alice completes her work, closes the browser and leaves the room.
  3. Eve launches the same browser and accesses the same application, within the 15min window.
    • The cookie is not present because it was session scoped.
  4. Eve checks the browser history and selects a recent URI that includes an OAuth Token.
    • The Client detects the OAuth Token on the URI and stores it as a new cookie. 
    • The Client can now invoke APIs with Alice's permissions.

The Client JavaScript could be written to detect and avoid this issue, by setting a "request_sent" cookie when sending the user to the Authorization Server and only parsing OAuth Tokens if that cookie is present.

Fundamentally this does not eliminate the problem as once Eve sees the token in the browser history she can use it in her own custom code.

One possible remedy is to provide a "Logout" feature that invokes the Authorization Server's revoke API.  This however relies on that API call working and the user clicking on LogOut.

Why include the OAuth Token on the URI?

The Implicit Grant type was designed with JavaScript apps in mind.  Lets look at the possible data transmission channels as they pertain to a JavaScript app being served by Apache:

  • POST message body - The request body is used by the server to determine what response to send, or in the case of Apache it is ignored.  JavaScript runs on the HTML included in the response, the request body is not available.
  • HTTP Headers - Headers set by the Authorization Server would likewise be request headers on the receiving end; request headers are not available to JavaScript.
  • Client fetches the OAuth Token - Without a shared secret the Authorization Server has no way to confirm the request is coming from the proper Client.
  • Query Params or URI Filename - The Fragment Identifier is the most protected part of the URI, all other parts are passed by the browser to the web server where it could be logged or worse.

This problem has been the subject of significant consideration and while not optimal the Fragment Identifier seems the best solution.

PKCE

Proof Key of Code Exchange is a replacement for implicit grant type.  It's the same as Implicit Grant with the change that the OAuth Token is retrieved via a separate direct call where the token is stored in the body and thus encrypted by SSL.

Before sending the user off to authenticate the Client generates a random value, it then sends a hash of the value off with the user when they are sent to authenticate.  At the end of the process the Client sends the unhashed random value to the Authorization Server, which then verifies that this value hashes to the hash previously presented.  This proves to the Authorization Server that the Client asking for the token is the same one that sent the user in for authorization.

Flow:

  1. The Client generates a random value (CodeVerifier) and then hashes it (CodeChallenge).
  2. Users of the application are sent to the Authorization Server to provide their consent.  The ClientId and CodeChallenge are sent with the request.
  3. The User authenticates with the Authorization Server.
  4. The Authorization Server redirects the browser to the Client's callback URL with a randomly generated Authorization Code.  It stores this authorization event associated with the Authorization Code.
  5. The Client extracts the Authorization Code from the browsers url.
  6. The Client sends the Authorization Code, ClientId and CodeVerifier to the Authorization Server.
  7. The Authorization Server looks up the authorization event attached to the Authorization Code. It then hashes the CodeVerifier and checks that it matches the CodeVerifier.  It returns a OAuth Token in the payload.
  8. The Client invokes APIs on the Resource Server, passing along the OAuth Token.


Example:

Pros & Cons

  • This process allows authenticating the user even when the Client can't be trusted to protect the Client Secret.
  • The API can not trust the application, as the code may have been modified by the User. 

Resource Owner Password Credentials - Thick Client / Script

With the Resource Owner Password Credentials grant type the Client submits it's own Client ID & Secret along with the Resource Owner's Username & Password.  The motivation for this grant type is "canonical" apps, for example the Facebook app on a mobile device might ask for the users Facebook password and use Resource Owner Password Credentials

Flow:

  1. The Client requests and stores the Username & Password from the Resource Owner.  This can be done in advance of the other steps and persist over sessions.
  2. The Client submits to the Authorization Server the Client ID & Secret along with the Username & Password.
  3. The Authorization Server returns a OAuth Token.  There is now "consent" screen as the user has give all control to the Client by turning over their Password.
  4. The Client invokes APIs on the Resource Server, passing along the OAuth Token.

Example:

Pros & Cons:

  • Requires the user to turn over their Username & Password, which users should be very wary of doing.  Which is why this is usually restricted to "canonical" apps (e.g. the Facebook App -> Facebook API).
  • App has responsibility of securely storing the Password.  The Password cannot be stored as a salted hash as is normally advised, because the request to the Authorization Server requires the original plain text (Base64 Encoded) Password.
  • The User doesn't have the authenticate every time they use the app.
  • The App can act on the users behalf without user input, for example the App can check for new messages in the background.

Client Credentials

The Client Credentials grant type was designed for operations that the App is performing on it own behalf.  This could be a backup script that isn't designed to run as a particular user or a webapp doing a background task that is not related to the user currently invoking it.  This is the simplest of the grant types, but also provides the least information to the API Manager for access decisions and statistics.

Because the APIM will not know what user is driving the operation it can not pass this information onto the Backend.

When the application is invoking an API because of input from the User, Authorization Grant should be used instead.  However that requires the user be sent to the APIM to authenticate and give consent.  In circumstances where consent is automatic or assumed and the User has already authenticated to the Application (e.g. webapp behind SSO) it is acceptable to use Client Credentials.  The application should include any User details needed by the backend server in the payload as the APIM won't be able to provide any User information.

Flow:

  1. Client requests a token from the Authorization Server, including the Client ID & Secret.
  2. The Authorization Server returns an OAuth Token.
  3. The Client invokes APIs on the Resource Server, passing along the OAuth Token.

Example:

Pros & Cons:

  • Simple.
  • No need for "fake" users or service accounts.
  • API Manager can not consider User when determining permissions (if there is one).
  • API Manager cannot log which User was involved (if there is one)

SAML2 Bearer Assertion

When a web app sends the user to SSO for authentication, the SSO server returns a signed SAML Assertion.  This assertion includes the known data about the current user, such as username.  If the Authorization Server also trusts the SSO Server, then that signed SAML Assertion can be exchanged for a OAuth Token.  

Flow:

  1. Client sends user to SSO for authentication.
  2. The user authenticates with the SSO server, usually with a username/password.
  3. The SSO returns an assertion to the Client, proving that the current user has authenticated.
  4. The Client requests an OAuth Token from the Authorization Server, including the SAML Assertion.
  5. The Authorization Server verifies the assertion was signed by a trusted IDP and returns an OAuth Token.

Example:

Pros & Cons:

  • User only has to authenticate once.
    • However in the normal scenarios, if the Authorization Server uses the same SSO IDP, when the user is sent to authenticate they will already have a session and be returned immediately.  The end result is that the user only gets prompted for their username/password once.
  • The SAML Assertion has to be in a format that both the Client and Authorization Server can process. 
    • In particular, the WSO2's Identity Server has configurations for extracting and transforming SAML assertions but these are not available in the SAML2 Bearer Assertion grant type.

Notes:

Below is the code used on https://www.websequencediagrams.com/ to generate the diagrams above.

Authorization Code
title Authorization Code
participant FB Auth
participant Mary
participant GreetingCardMaker
participant FB Photos
Mary->GreetingCardMaker: Click "Load Facebook Photos"
GreetingCardMaker->Mary: Redirect (ClientID: GreetingCardMaker, Scope: Photos)
Mary->FB Auth: Authorization Request
note over Mary, FB Auth: Authenticate & Grant Permission
FB Auth->Mary: Redirect (Grant Code)
Mary->GreetingCardMaker: (Grant Code)
GreetingCardMaker->FB Auth: Request Token (Client ID & Secret, Grant Code)
FB Auth->GreetingCardMaker: OAuth Token
GreetingCardMaker->FB Photos: Request Photos (OAuth Token)
FB Photos->GreetingCardMaker: Mary's Photos
Implicit Grant Type
title Implicit Grant Type

participant FB Auth
participant Mary
participant GreetingCardLite.html
participant FB Photos

Mary->GreetingCardLite.html: Click "Load Facebook Photos"

GreetingCardLite.html->Mary: Redirect (ClientID: GreetingCardLite, Scope: Photos)

Mary->FB Auth: Authorization Request

note over Mary, FB Auth: Authenticate & Grant Permission

FB Auth->Mary: Redirect (OAuth Token)\nhttps://server/GreetingCardLite.html#access_token=8de...

Mary->GreetingCardLite.html: OAuth Token

GreetingCardLite.html->GreetingCardLite.html: Extract OAuth Token\nfrom window.location.href

GreetingCardLite.html->FB Photos: Request Photos (OAuth Token)

FB Photos->GreetingCardLite.html: Mary's Photos
Resource Owner Password Credentials
title Resource Owner Password Credentials
participant Mary
participant FB App
participant FB Auth
participant FB Photos
Mary->FB App: Stores Username & Password
FB App->FB Auth: Get Token\n(Client ID & Secret, Username & Password, Scope)
FB Auth->FB App: OAuth Token
FB App->FB Photos: Request Photos (OAuth Token)
FB Photos->FB App: Mary's Photos
Client Credentials
title Client Credentials
participant Auth Server
participant BackupScript
participant API Manager
BackupScript->Auth Server: Request OAuth Token (Client Id & Secret)
Auth Server->BackupScript: OAuth Token
BackupScript->API Manager: Report Successful backup (OAuth Token)
SAML2 Bearer Assertion
title SAML2 Bearer Assertion
participant A4
participant Mary
participant MyTime
participant Auth Server
Mary->MyTime: Access MyTime
MyTime->Mary: Redirect to A4
Mary->A4: Authenticate
note over Mary, A4: Authenticate
A4->Mary: SAML Assertion
Mary->MyTime: Access MyTime (SAML Assertion)
MyTime->MyTime: Process Assertion, \nextract user data.
MyTime->Auth Server: Request OAuth Toke (SAMl Assertion)
Auth Server->Auth Server: Verify Signed by trusted IDP
Auth Server->MyTime: OAuth Token
MyTime->Leave Balances API: get user's vacation time (OAuth Token)