Content · Web Development · PHP

Implementing OAuth 2.0 Authorization Code Flow

Redirect users to a configured OAuth 2.0 authorization server and exchange a one-time authorization code for.

1 views Published Oct 17, 2026 Updated Oct 17, 2026 admin

Redirect users to a configured OAuth 2.0 authorization server and exchange a one-time authorization code for tokens.

The examples introduce the underlying control before showing a verification and an application-level safeguard.

What You Will Build


Redirect users to a configured OAuth 2.0 authorization server and exchange a one-time authorization code for tokens.

Prerequisites


Use PHP 8.4 or newer, HTTPS for all authentication operations, and an application session or database where required. Example configuration values are placeholders, never production secrets.

Example 1: Basic Operation


Create one-time state, PKCE verifier and S256 code challenge.

<?php
session_start();
$state = bin2hex(random_bytes(32));
$verifier = rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '=');
$challenge = rtrim(strtr(base64_encode(hash('sha256', $verifier, true)), '+/', '-_'), '=');
$_SESSION['oauth_attempt'] = ['state' => $state, 'verifier' => $verifier];
echo 'PKCE S256 challenge: ' . $challenge;

Example 2: A Different Use Case


Validate the callback state and consume the login attempt once.

<?php
session_start();
$attempt = $_SESSION['oauth_attempt'] ?? [];
$state = $_GET['state'] ?? null;
if (!is_string($state) || !isset($attempt['state']) || !hash_equals($attempt['state'], $state)) {
    http_response_code(400); exit('Invalid OAuth state');
}
$code = $_GET['code'] ?? null;
if (!is_string($code) || $code === '') { http_response_code(400); exit; }
$_SESSION['validated_pkce_verifier'] = $attempt['verifier'];
unset($_SESSION['oauth_attempt']);
// Exchange the code at a fixed token endpoint; expire verifier after this attempt.

Practical Example: Checking the Result


Build an authorization request using fixed provider settings, not user-controlled URLs.

<?php
// Run only after the server has validated and consumed the callback state.
// These values must be kept from the same original authorization attempt.
$authorizationCode = $_GET['code'] ?? null;
$verifier = $_SESSION['validated_pkce_verifier'] ?? null;
if (!is_string($authorizationCode) || !is_string($verifier)) { http_response_code(400); exit; }
$tokenEndpoint = 'https://auth.example.test/token'; // Fixed trusted provider setting.
$payload = http_build_query(['grant_type' => 'authorization_code', 'code' => $authorizationCode,
    'client_id' => getenv('OAUTH_CLIENT_ID'), 'redirect_uri' => 'https://app.example.test/callback',
    'code_verifier' => $verifier], '', '&', PHP_QUERY_RFC3986);
$ch = curl_init($tokenEndpoint);
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload,
    CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
unset($_SESSION['validated_pkce_verifier']);
if (!is_string($response) || $status !== 200) { throw new RuntimeException('Token exchange failed'); }
$tokens = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
// Validate scope, issuer and token type; store tokens server-side only.
// For login via OpenID Connect, also validate the ID token and nonce.

Important Behavior and Edge Cases


Verify state and PKCE, exact redirect URI, issuer and client identity; never trust arbitrary provider URLs.

Enforce controls on the server, test denial paths and do not assume that a snippet alone implements an entire production workflow.

Comparison with Related Functions


ApproachKey distinction
Implementing OAuth 2.0 Authorization Code FlowRedirect users to a configured OAuth 2.0 authorization server and exchange a one-time authorization code for tokens.
Related techniqueOAuth authorizes delegated API access; for user identity use OpenID Connect with ID token validation.

Common Beginner Mistakes


MistakeCorrect approach
Confusing this operation with a neighboring cryptographic or security mechanismOAuth authorizes delegated API access; for user identity use OpenID Connect with ID token validation.
Ignoring a security prerequisite or failure caseVerify state and PKCE, exact redirect URI, issuer and client identity; never trust arbitrary provider URLs.

Key Takeaways


  • Redirect users to a configured OAuth 2.0 authorization server and exchange a one-time authorization code for tokens.
  • Verify state and PKCE, exact redirect URI, issuer and client identity; never trust arbitrary provider URLs.
  • OAuth authorizes delegated API access; for user identity use OpenID Connect with ID token validation.

Apply this behavior to a real application only after confirming the required extension, configuration and failure handling on the deployment runtime.

Share this resourceSend this page to someone who may find it useful.