OAuth2 authorization code flow | Ory

OAuth2 Authorization Code Flow

OAuth2 and OpenID Connect are widely used authorization and authentication delegation protocols that enable secure access to APIs and web applications. This document explains how to obtain ID tokens and refresh tokens, and also discusses various parameters, such as grant_type, redirect_uri, prompt, scope, state. Additionally, this document describes how to perform PKCE on top of the Authorization Code flow.

The Authorization Code flow is the most secure and widely used OAuth2 flow for web applications. Here is the high-level overview of the Authorization Code flow:

  1. The user clicks on a link or button on a web page that requests access to a resource.
  2. The user is redirected to the Authorization Server, where they authenticate themselves and grant permission to the requesting application.
  3. The Authorization Server generates an authorization code and redirects the user back to the requesting application with the authorization code.
  4. The requesting application exchanges the authorization code for an access token that can be used to access the protected resource.

Step 1: Get the user's permission

The user clicks on a link or button on a web page that requests access to a resource. The requesting application sends a request to the Authorization Server with the following parameters:

Step 2: Redirect to the Authorization Server

The user is redirected to the Authorization Server, where they authenticate themselves and grant permission to the requesting application. The Authorization Server could ask the user to log in or prompt them to authorize the access request.

Step 3: Redirect back to the app

If the user grants permission, the Authorization Server generates an authorization code and redirects the user back to the requesting application with the authorization code.

Step 4: Exchange code for token

The requesting application exchanges the authorization code for an access token that can be used to access the protected resource. The requesting application sends a POST request to the Authorization Server with the following parameters:

The Authorization Server validates the request and responds with an access token and a refresh token (if enabled). The requesting application can use the access token to access the protected resource.

Modifying the authorization code flow

Get a refresh token

By default, the Authorization Code flow returns an access token that expires after a certain period of time. To get a refresh token, you need to include the offline_access scope in the access request.

Get an OpenID Connect ID token and validate it

To obtain an ID token, you need to include the openid scope in the access request. The ID token is a JSON Web Token (JWT) that contains information about the authenticated user. The ID token can be used to obtain information about the user such as their name and email address.

To validate the ID token, you need to decode the JWT and verify the signature using the public key of the Authorization Server which is available at

https://$PROJECT_SLUG.projects.oryapis.com/.well-known/jwks.json

Perform PKCE

PKCE (Proof Key for Code Exchange) is a security extension to the Authorization Code flow that is designed to prevent code injection attacks. In the PKCE flow, the client generates a random code verifier and transforms it into a code challenge that is sent to the Authorization Server.

Here's a JavaScript code example that demonstrates how to generate a code verifier and code challenge using the SHA-256 hash algorithm:

// Generate PKCE code challenge and verifier

async function generatePKCES256() {

const array = new Uint8Array(64)
  crypto.getRandomValues(array)
  const codeVerifier = Buffer.from(array).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\/g, "_")

const codeChallenge = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier)).then((buffer) => {
    return Buffer.from(buffer).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\/g, "_")
  })

return { codeChallenge, codeVerifier }
}

const { codeChallenge, codeVerifier } = await generatePKCES256()

const redirectUri = "..."
const clientId = "..."

// Send the code challenge along with the authorization request
const authorizationUrl = `https://$PROJECT_SLUG.projects.oryapis.com/oauth2/auth?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&code_challenge=${codeChallenge}&code_challenge_method=S256`

// Exchange the authorization code for a token using the code verifier
const code = new URLSearchParams(window.location.search).get("code")
const tokenUrl = "https://$PROJECT_SLUG.projects.oryapis.com/oauth2/token"
const tokenRequestBody = new URLSearchParams({
  grant_type: "authorization_code",
  client_id: clientId,
  redirect_uri: redirectUri,
  code_verifier: codeVerifier,
  code: code,
})

fetch(tokenUrl, {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: tokenRequestBody.toString(),
})
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error))

In this example, generatePKCES256() generates a random code verifier with a length of 64 characters, as well as the base64url-encoded SHA-256 hash of the code verifier as the code challenge.

Examples

This section demonstrates how to use Ory OAuth2 and OpenID Connect in different types of web applications. The examples cover the use of public clients with PKCE, confidential clients, custom redirect schemes in mobile/native apps, and more.