New to Rust? Grab our free Rust for Beginners eBook Get it free →
Implement OAuth 2.0 Login in PHP with Auth0

Auth0 login for a PHP web application works best when your server uses the Authorization Code Flow through the maintained Auth0 PHP SDK.
I installed the current SDK in a clean PHP 8.4 workspace and verified that its Auth0\SDK\Auth0 constructor loads, which matters because the legacy configuration in older examples does not match the SDK you install today.
Use Authorization Code Flow for a PHP web app
OAuth 2.0 delegates access.
OpenID Connect adds identity information through the openid scope, which is why a login integration usually uses both.
For a regular PHP web application, the browser goes to Auth0.
Auth0 returns a single-use code to your callback URL, and your server exchanges that code for tokens.
The client secret stays on the server during that exchange.
Configure an Auth0 application first
Create a Regular Web Application in the Auth0 dashboard.
Copy its domain, client ID, and client secret into environment variables that stay outside version control.
Add the exact callback URL before you test.
For a local app at http://127.0.0.1:3000, Auth0’s PHP quickstart uses http://127.0.0.1:3000/ as the callback URL and http://127.0.0.1:3000 as the logout URL.
AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
AUTH0_COOKIE_SECRET=generate-a-long-random-value
AUTH0_BASE_URL=http://127.0.0.1:3000
The cookie secret protects the local session cookie.
Generate a new high-entropy value for each deployment environment, then keep the file unreadable from your web root.
Install the PHP dependencies
Auth0’s current SDK documentation lists PHP 8.2 or newer, Composer, mbstring, and PSR HTTP components as requirements.
Install the SDK and its HTTP dependencies from your project directory.
composer require auth0/auth0-php guzzlehttp/guzzle guzzlehttp/psr7 http-interop/http-factory-guzzle vlucas/phpdotenv steampixel/simple-php-router
Composer creates vendor/autoload.php, which your application must load before it creates the SDK client.
My clean installation resolved auth0/auth0-php 8.19.0 and loaded the SDK constructor on PHP 8.4.24.
Initialize the Auth0 SDK
Load the environment file, then create one Auth0 instance.
Keep this setup in the same bootstrap path used by your login, callback, and logout routes.
<?php
require __DIR__ . '/vendor/autoload.php';
(Dotenv\Dotenv::createImmutable(__DIR__))->load();
$auth0 = new Auth0\SDK\Auth0([
'domain' => $_ENV['AUTH0_DOMAIN'],
'clientId' => $_ENV['AUTH0_CLIENT_ID'],
'clientSecret' => $_ENV['AUTH0_CLIENT_SECRET'],
'cookieSecret' => $_ENV['AUTH0_COOKIE_SECRET'],
]);
Do not place the client secret in browser JavaScript.
A server-rendered PHP app can keep it in a protected environment, while a single-page application must use Authorization Code Flow with PKCE instead of a client secret.
Add login, callback, and logout routes
The SDK handles the redirect, callback exchange, and session state.
Define the URLs once so the callback passed to login() matches the value registered in Auth0.
use Steampixel\Route;
define('BASE_URL', rtrim($_ENV['AUTH0_BASE_URL'], '/'));
define('CALLBACK_URL', BASE_URL . '/callback');
Route::add('/login', function () use ($auth0) {
$auth0->clear();
header('Location: ' . $auth0->login(CALLBACK_URL));
exit;
});
Route::add('/callback', function () use ($auth0) {
$auth0->exchange(CALLBACK_URL);
header('Location: ' . BASE_URL);
exit;
});
Route::add('/logout', function () use ($auth0) {
header('Location: ' . $auth0->logout(BASE_URL));
exit;
});
Clear the previous local state before beginning a new login.
Auth0’s PHP quickstart calls out that step because an interrupted earlier transaction can otherwise produce an invalid-state error.
Read the authenticated session safely
Use getCredentials() on a page that needs a signed-in user.
A missing session is an ordinary branch, so send the visitor to your login route instead of assuming profile fields exist.
Route::add('/', function () use ($auth0) {
$session = $auth0->getCredentials();
if ($session === null) {
echo '<p><a href="/login">Log in</a></p>';
return;
}
$name = $session->user['name']
?? $session->user['nickname']
?? $session->user['email']
?? 'Unknown';
echo '<p>Signed in as ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '</p>';
});
Route::run('/');
Identity providers do not guarantee every profile field.
The fallback chain prevents a missing display name from becoming a PHP notice or a broken page.
Keep the security boundaries intact
Your callback URL must exactly match an Allowed Callback URL in Auth0.
Treat that URL as application configuration, not as a value supplied by the request.
Authorization Code Flow separates the browser redirect from the server-side token exchange.
State binds the callback to the transaction your app started, and the SDK manages that state for this flow.
Request only the scopes your application uses.
Add openid when you need identity, then include profile or email only when the application consumes those claims.
Choose the flow by application type
Use a regular web application and the server-side SDK when PHP owns the session and can protect a client secret.
Use Authorization Code Flow with PKCE for a browser-only or mobile application, where a secret cannot remain private.
OAuth 2.0 gives your application delegated authorization.
Login also needs OpenID Connect, so request the openid scope and use the SDK session instead of treating an access token as a user profile.
Test the registered callback, login, and logout
Start the PHP development server, open the login route, complete Universal Login, and confirm that the callback returns to your index route.
Then use logout and confirm that Auth0 accepts your registered return URL.
php -S 127.0.0.1:3000 index.php
A local SDK constructor check proves that the installed package and bootstrap load.
Your tenant configuration is a separate test, so exercise it with a development application before you deploy credentials or callback URLs to production.
Sources
- Auth0 PHP quickstart
- Auth0 PHP SDK documentation
- Auth0 Authorization Code Flow
- Auth0 OAuth 2.0 overview
- Microsoft Authorization Code Flow reference




