auth0-php

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Auth0 PHP Web App Integration

Auth0 PHP Web应用集成

Add login, logout, and user profile to a PHP web application using
auth0/auth0-php
.

使用
auth0/auth0-php
为PHP Web应用添加登录、登出和用户功能。

Prerequisites

前置条件

  • PHP 8.2+ with extensions:
    mbstring
    ,
    openssl
    ,
    json
  • Composer installed
  • Auth0 Regular Web Application configured (not an API - must be an Application)
  • If you don't have Auth0 set up yet, use the
    auth0-quickstart
    skill first
  • PHP 8.2+ 及扩展:
    mbstring
    openssl
    json
  • 已安装Composer
  • 已配置Auth0常规Web应用(非API,必须是应用类型)
  • 若尚未设置Auth0,请先使用
    auth0-quickstart
    技能

When NOT to Use

不适用于以下场景

  • PHP APIs with JWT Bearer validation - Use
    auth0-php-api
    for stateless API token validation
  • Laravel applications - Use a dedicated Laravel integration with
    auth0/laravel-auth0
  • Symfony applications - Use a dedicated Symfony integration with
    auth0/symfony
  • Single Page Applications - Use
    auth0-react
    ,
    auth0-vue
    , or
    auth0-angular
    for client-side auth
  • Next.js applications - Use
    auth0-nextjs
    which handles both client and server
  • Node.js web apps - Use
    auth0-express
    or
    auth0-fastify
    for session-based auth

  • 带JWT Bearer验证的PHP API - 使用
    auth0-php-api
    进行无状态API令牌验证
  • Laravel应用 - 使用专用的Laravel集成包
    auth0/laravel-auth0
  • Symfony应用 - 使用专用的Symfony集成包
    auth0/symfony
  • 单页应用 - 使用
    auth0-react
    auth0-vue
    auth0-angular
    进行客户端身份验证
  • Next.js应用 - 使用
    auth0-nextjs
    处理客户端和服务端身份验证
  • Node.js Web应用 - 使用
    auth0-express
    auth0-fastify
    实现基于会话的身份验证

Quick Start Workflow

快速开始流程

1. Install SDK

1. 安装SDK

bash
composer require auth0/auth0-php vlucas/phpdotenv guzzlehttp/guzzle guzzlehttp/psr7
  • auth0/auth0-php
    - The Auth0 SDK
  • vlucas/phpdotenv
    - Load
    .env
    files into
    $_ENV
  • guzzlehttp/guzzle
    +
    guzzlehttp/psr7
    - PSR-18 HTTP client required by the SDK
bash
composer require auth0/auth0-php vlucas/phpdotenv guzzlehttp/guzzle guzzlehttp/psr7
  • auth0/auth0-php
    - Auth0 SDK
  • vlucas/phpdotenv
    - 将
    .env
    文件加载到
    $_ENV
  • guzzlehttp/guzzle
    +
    guzzlehttp/psr7
    - SDK所需的PSR-18 HTTP客户端

2. Configure Environment

2. 配置环境变量

Create
.env
:
bash
AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
AUTH0_COOKIE_SECRET=your_generated_secret
AUTH0_REDIRECT_URI=http://localhost:3000/callback
AUTH0_DOMAIN
is your Auth0 tenant domain (without
https://
).
AUTH0_CLIENT_ID
and
AUTH0_CLIENT_SECRET
come from your Auth0 Application settings.
AUTH0_COOKIE_SECRET
is used for encrypting session cookies - generate with
openssl rand -hex 32
.
创建
.env
文件:
bash
AUTH0_DOMAIN=your-tenant.us.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
AUTH0_COOKIE_SECRET=your_generated_secret
AUTH0_REDIRECT_URI=http://localhost:3000/callback
AUTH0_DOMAIN
是你的Auth0租户域名(不带
https://
)。
AUTH0_CLIENT_ID
AUTH0_CLIENT_SECRET
来自Auth0应用设置。
AUTH0_COOKIE_SECRET
用于加密会话Cookie - 使用
openssl rand -hex 32
生成。

3. Configure Auth0 Dashboard

3. 配置Auth0控制台

In your Auth0 Application settings:
  • Application Type: Regular Web Application
  • Allowed Callback URLs:
    http://localhost:3000/callback
  • Allowed Logout URLs:
    http://localhost:3000
在Auth0应用设置中:
  • 应用类型:常规Web应用
  • 允许的回调URL
    http://localhost:3000/callback
  • 允许的登出URL
    http://localhost:3000

4. Create Auth Configuration

4. 创建Auth配置

Create
auth0.php
to initialize the SDK:
php
<?php

require 'vendor/autoload.php';

use Auth0\SDK\Auth0;
use Auth0\SDK\Configuration\SdkConfiguration;

// Load environment variables
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$configuration = new SdkConfiguration(
    strategy: SdkConfiguration::STRATEGY_REGULAR,
    domain: $_ENV['AUTH0_DOMAIN'],
    clientId: $_ENV['AUTH0_CLIENT_ID'],
    clientSecret: $_ENV['AUTH0_CLIENT_SECRET'],
    cookieSecret: $_ENV['AUTH0_COOKIE_SECRET'],
    redirectUri: $_ENV['AUTH0_REDIRECT_URI'],
    scope: ['openid', 'profile', 'email'],
);

$auth0 = new Auth0($configuration);
Create one
Auth0
instance and reuse it. Never hardcode credentials - always use environment variables.
How this works: The SDK encrypts session data (tokens, user profile) using AES-256-GCM with a key derived from
cookieSecret
via HKDF-SHA256. Session data is stored in an encrypted cookie by default - no server-side database required.
创建
auth0.php
初始化SDK:
php
<?php

require 'vendor/autoload.php';

use Auth0\SDK\Auth0;
use Auth0\SDK\Configuration\SdkConfiguration;

// 加载环境变量
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

$configuration = new SdkConfiguration(
    strategy: SdkConfiguration::STRATEGY_REGULAR,
    domain: $_ENV['AUTH0_DOMAIN'],
    clientId: $_ENV['AUTH0_CLIENT_ID'],
    clientSecret: $_ENV['AUTH0_CLIENT_SECRET'],
    cookieSecret: $_ENV['AUTH0_COOKIE_SECRET'],
    redirectUri: $_ENV['AUTH0_REDIRECT_URI'],
    scope: ['openid', 'profile', 'email'],
);

$auth0 = new Auth0($configuration);
创建一个
Auth0
实例并复用。切勿硬编码凭证 - 始终使用环境变量。
工作原理:SDK使用AES-256-GCM加密会话数据(令牌、用户信息),密钥由
cookieSecret
通过HKDF-SHA256生成。会话数据默认存储在加密Cookie中 - 无需服务器端数据库。

5. Create Index Page (Router)

5. 创建首页(路由)

Create
index.php
as a simple front controller. Create the
routes/
directory first:
php
<?php

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path === '/style.css') {
    header('Content-Type: text/css');
    readfile(__DIR__ . '/style.css');
    exit;
}

require 'auth0.php';

switch ($path) {
    case '/':
        require 'routes/home.php';
        break;
    case '/login':
        require 'routes/login.php';
        break;
    case '/callback':
        require 'routes/callback.php';
        break;
    case '/profile':
        require 'routes/profile.php';
        break;
    case '/logout':
        require 'routes/logout.php';
        break;
    default:
        http_response_code(404);
        echo 'Not found';
        break;
}
The static file handler for
/style.css
is placed before
require 'auth0.php'
so stylesheets load without initializing the SDK.
创建
index.php
作为简单的前端控制器。先创建
routes/
目录:
php
<?php

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path === '/style.css') {
    header('Content-Type: text/css');
    readfile(__DIR__ . '/style.css');
    exit;
}

require 'auth0.php';

switch ($path) {
    case '/':
        require 'routes/home.php';
        break;
    case '/login':
        require 'routes/login.php';
        break;
    case '/callback':
        require 'routes/callback.php';
        break;
    case '/profile':
        require 'routes/profile.php';
        break;
    case '/logout':
        require 'routes/logout.php';
        break;
    default:
        http_response_code(404);
        echo 'Not found';
        break;
}
/style.css
的静态文件处理器放在
require 'auth0.php'
之前,这样样式表加载时无需初始化SDK。

6. Add Stylesheet

6. 添加样式表

Create
style.css
:
css
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: #f5f7fa;
    color: #1a1a2e;
    line-height: 1.6;
    min-height: 100vh;
}

.container {
    max-width: 800px;
    margin: 0 auto;
    padding: 40px 20px;
}

.card {
    background: #fff;
    border-radius: 12px;
    padding: 28px;
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    border: 1px solid #e8ecf0;
}

.card.center {
    text-align: center;
    padding: 60px 28px;
}

h1 {
    font-size: 1.5rem;
    font-weight: 600;
    margin-bottom: 4px;
}

h2 {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 16px;
    color: #444;
}

.subtitle {
    color: #666;
    font-size: 0.95rem;
}

.card.center .subtitle {
    margin: 12px 0 28px;
}

.user-header {
    display: flex;
    align-items: center;
    gap: 16px;
}

.avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.avatar-lg {
    width: 72px;
    height: 72px;
}

.nav-links {
    margin-top: 20px;
    display: flex;
    gap: 12px;
}

.top-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.btn {
    display: inline-block;
    padding: 10px 20px;
    border-radius: 8px;
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    transition: all 0.15s ease;
}

.btn-primary {
    background: #635bff;
    color: #fff;
}

.btn-primary:hover {
    background: #4b44d4;
}

.btn-secondary {
    background: #f0f0f5;
    color: #444;
}

.btn-secondary:hover {
    background: #e4e4ec;
}

.btn-back {
    background: none;
    color: #635bff;
    padding: 10px 0;
}

.btn-back:hover {
    color: #4b44d4;
}

.info-table {
    width: 100%;
    border-collapse: collapse;
}

.info-table tr {
    border-bottom: 1px solid #f0f0f5;
}

.info-table tr:last-child {
    border-bottom: none;
}

.info-table td {
    padding: 10px 0;
    vertical-align: top;
}

.info-table .label {
    font-weight: 500;
    color: #666;
    width: 160px;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.info-table .value {
    color: #1a1a2e;
    word-break: break-all;
}

.token-box {
    background: #f8f9fb;
    border: 1px solid #e8ecf0;
    border-radius: 8px;
    padding: 14px;
    font-size: 0.8rem;
    font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
    word-break: break-all;
    white-space: pre-wrap;
    max-height: 120px;
    overflow-y: auto;
    margin-bottom: 16px;
}
创建
style.css
css
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: #f5f7fa;
    color: #1a1a2e;
    line-height: 1.6;
    min-height: 100vh;
}

.container {
    max-width: 800px;
    margin: 0 auto;
    padding: 40px 20px;
}

.card {
    background: #fff;
    border-radius: 12px;
    padding: 28px;
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    border: 1px solid #e8ecf0;
}

.card.center {
    text-align: center;
    padding: 60px 28px;
}

h1 {
    font-size: 1.5rem;
    font-weight: 600;
    margin-bottom: 4px;
}

h2 {
    font-size: 1.1rem;
    font-weight: 600;
    margin-bottom: 16px;
    color: #444;
}

.subtitle {
    color: #666;
    font-size: 0.95rem;
}

.card.center .subtitle {
    margin: 12px 0 28px;
}

.user-header {
    display: flex;
    align-items: center;
    gap: 16px;
}

.avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.avatar-lg {
    width: 72px;
    height: 72px;
}

.nav-links {
    margin-top: 20px;
    display: flex;
    gap: 12px;
}

.top-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.btn {
    display: inline-block;
    padding: 10px 20px;
    border-radius: 8px;
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    transition: all 0.15s ease;
}

.btn-primary {
    background: #635bff;
    color: #fff;
}

.btn-primary:hover {
    background: #4b44d4;
}

.btn-secondary {
    background: #f0f0f5;
    color: #444;
}

.btn-secondary:hover {
    background: #e4e4ec;
}

.btn-back {
    background: none;
    color: #635bff;
    padding: 10px 0;
}

.btn-back:hover {
    color: #4b44d4;
}

.info-table {
    width: 100%;
    border-collapse: collapse;
}

.info-table tr {
    border-bottom: 1px solid #f0f0f5;
}

.info-table tr:last-child {
    border-bottom: none;
}

.info-table td {
    padding: 10px 0;
    vertical-align: top;
}

.info-table .label {
    font-weight: 500;
    color: #666;
    width: 160px;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.info-table .value {
    color: #1a1a2e;
    word-break: break-all;
}

.token-box {
    background: #f8f9fb;
    border: 1px solid #e8ecf0;
    border-radius: 8px;
    padding: 14px;
    font-size: 0.8rem;
    font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
    word-break: break-all;
    white-space: pre-wrap;
    max-height: 120px;
    overflow-y: auto;
    margin-bottom: 16px;
}

7. Add Home Route

7. 添加首页路由

Create
routes/home.php
:
php
<?php

$credentials = $auth0->getCredentials();
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Auth0 PHP App</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container">
        <?php if ($credentials): ?>
            <div class="card">
                <div class="user-header">
                    <img src="<?= htmlspecialchars($credentials->user['picture'] ?? '') ?>" alt="avatar" class="avatar" />
                    <div>
                        <h1>Hello, <?= htmlspecialchars($credentials->user['name'] ?? 'User') ?>!</h1>
                        <p class="subtitle"><?= htmlspecialchars($credentials->user['email'] ?? '') ?></p>
                    </div>
                </div>
                <nav class="nav-links">
                    <a href="/profile" class="btn btn-primary">View Profile & Tokens</a>
                    <a href="/logout" class="btn btn-secondary">Logout</a>
                </nav>
            </div>
        <?php else: ?>
            <div class="card center">
                <h1>Auth0 PHP Web App</h1>
                <p class="subtitle">Session-based authentication with Auth0 SDK</p>
                <a href="/login" class="btn btn-primary">Login</a>
            </div>
        <?php endif; ?>
    </div>
</body>
</html>
创建
routes/home.php
php
<?php

$credentials = $auth0->getCredentials();
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Auth0 PHP App</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container">
        <?php if ($credentials): ?>
            <div class="card">
                <div class="user-header">
                    <img src="<?= htmlspecialchars($credentials->user['picture'] ?? '') ?>" alt="avatar" class="avatar" />
                    <div>
                        <h1>Hello, <?= htmlspecialchars($credentials->user['name'] ?? 'User') ?>!</h1>
                        <p class="subtitle"><?= htmlspecialchars($credentials->user['email'] ?? '') ?></p>
                    </div>
                </div>
                <nav class="nav-links">
                    <a href="/profile" class="btn btn-primary">查看个人信息与令牌</a>
                    <a href="/logout" class="btn btn-secondary">登出</a>
                </nav>
            </div>
        <?php else: ?>
            <div class="card center">
                <h1>Auth0 PHP Web应用</h1>
                <p class="subtitle">基于会话的Auth0 SDK身份验证</p>
                <a href="/login" class="btn btn-primary">登录</a>
            </div>
        <?php endif; ?>
    </div>
</body>
</html>

8. Add Login Route

8. 添加登录路由

Create
routes/login.php
:
php
<?php

header('Location: ' . $auth0->login());
exit;
login()
returns a URL string pointing to Auth0's Universal Login page. You must redirect the user to it.
创建
routes/login.php
php
<?php

header('Location: ' . $auth0->login());
exit;
login()
返回指向Auth0通用登录页面的URL字符串。必须将用户重定向到该页面。

9. Add Callback Route

9. 添加回调路由

Create
routes/callback.php
:
php
<?php

if (null !== $auth0->getExchangeParameters()) {
    try {
        $auth0->exchange();
        header('Location: /');
        exit;
    } catch (\Exception $e) {
        error_log('Auth0 callback error: ' . $e->getMessage());
        http_response_code(400);
        echo "Authentication failed. Please try again.";
        exit;
    }
}

header('Location: /');
exit;
getExchangeParameters()
checks if the callback contains authorization code parameters.
exchange()
exchanges the code for tokens and establishes the session. Always wrap in try/catch since the token exchange can fail (e.g. expired code, CSRF mismatch).
创建
routes/callback.php
php
<?php

if (null !== $auth0->getExchangeParameters()) {
    try {
        $auth0->exchange();
        header('Location: /');
        exit;
    } catch (\Exception $e) {
        error_log('Auth0回调错误: ' . $e->getMessage());
        http_response_code(400);
        echo "身份验证失败,请重试。";
        exit;
    }
}

header('Location: /');
exit;
getExchangeParameters()
检查回调是否包含授权码参数。
exchange()
将代码兑换为令牌并建立会话。始终用try/catch包裹,因为令牌兑换可能失败(例如代码过期、CSRF不匹配)。

10. Add Profile Route (Protected)

10. 添加个人信息路由(受保护)

Create
routes/profile.php
:
php
<?php

$credentials = $auth0->getCredentials();

if (null === $credentials) {
    header('Location: /login');
    exit;
}

$user = $credentials->user;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Profile - Auth0 PHP App</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container">
        <nav class="top-nav">
            <a href="/" class="btn btn-back">&larr; Back to Home</a>
            <a href="/logout" class="btn btn-secondary">Logout</a>
        </nav>

        <div class="card">
            <div class="user-header">
                <img src="<?= htmlspecialchars($user['picture'] ?? '') ?>" alt="avatar" class="avatar avatar-lg" />
                <div>
                    <h1><?= htmlspecialchars($user['name'] ?? 'User') ?></h1>
                    <p class="subtitle"><?= htmlspecialchars($user['email'] ?? '') ?></p>
                </div>
            </div>
        </div>

        <div class="card">
            <h2>User Profile Claims</h2>
            <table class="info-table">
                <?php foreach ($user as $key => $value): ?>
                <tr>
                    <td class="label"><?= htmlspecialchars($key) ?></td>
                    <td class="value"><?= htmlspecialchars(is_array($value) ? json_encode($value) : (string)$value) ?></td>
                </tr>
                <?php endforeach; ?>
            </table>
        </div>

        <div class="card">
            <h2>ID Token</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->idToken ?? 'N/A') ?></pre>
        </div>

        <div class="card">
            <h2>Access Token</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->accessToken ?? 'N/A') ?></pre>
            <table class="info-table">
                <tr>
                    <td class="label">Expires</td>
                    <td class="value"><?= $credentials->accessTokenExpiration ? date('Y-m-d H:i:s', $credentials->accessTokenExpiration) . ' (' . ($credentials->accessTokenExpired ? 'EXPIRED' : 'valid') . ')' : 'N/A' ?></td>
                </tr>
                <tr>
                    <td class="label">Scopes</td>
                    <td class="value"><?= htmlspecialchars(implode(', ', $credentials->accessTokenScope ?? [])) ?></td>
                </tr>
            </table>
        </div>

        <?php if ($credentials->refreshToken): ?>
        <div class="card">
            <h2>Refresh Token</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->refreshToken) ?></pre>
        </div>
        <?php endif; ?>
    </div>
</body>
</html>
getCredentials()
returns the user's session data, or
null
if not logged in. The profile page displays all user claims and tokens for verification during development.
创建
routes/profile.php
php
<?php

$credentials = $auth0->getCredentials();

if (null === $credentials) {
    header('Location: /login');
    exit;
}

$user = $credentials->user;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人信息 - Auth0 PHP应用</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container">
        <nav class="top-nav">
            <a href="/" class="btn btn-back">&larr; 返回首页</a>
            <a href="/logout" class="btn btn-secondary">登出</a>
        </nav>

        <div class="card">
            <div class="user-header">
                <img src="<?= htmlspecialchars($user['picture'] ?? '') ?>" alt="avatar" class="avatar avatar-lg" />
                <div>
                    <h1><?= htmlspecialchars($user['name'] ?? 'User') ?></h1>
                    <p class="subtitle"><?= htmlspecialchars($user['email'] ?? '') ?></p>
                </div>
            </div>
        </div>

        <div class="card">
            <h2>用户信息声明</h2>
            <table class="info-table">
                <?php foreach ($user as $key => $value): ?>
                <tr>
                    <td class="label"><?= htmlspecialchars($key) ?></td>
                    <td class="value"><?= htmlspecialchars(is_array($value) ? json_encode($value) : (string)$value) ?></td>
                </tr>
                <?php endforeach; ?>
            </table>
        </div>

        <div class="card">
            <h2>ID令牌</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->idToken ?? 'N/A') ?></pre>
        </div>

        <div class="card">
            <h2>访问令牌</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->accessToken ?? 'N/A') ?></pre>
            <table class="info-table">
                <tr>
                    <td class="label">过期时间</td>
                    <td class="value"><?= $credentials->accessTokenExpiration ? date('Y-m-d H:i:s', $credentials->accessTokenExpiration) . ' (' . ($credentials->accessTokenExpired ? '已过期' : '有效') . ')' : 'N/A' ?></td>
                </tr>
                <tr>
                    <td class="label">权限范围</td>
                    <td class="value"><?= htmlspecialchars(implode(', ', $credentials->accessTokenScope ?? [])) ?></td>
                </tr>
            </table>
        </div>

        <?php if ($credentials->refreshToken): ?>
        <div class="card">
            <h2>刷新令牌</h2>
            <pre class="token-box"><?= htmlspecialchars($credentials->refreshToken) ?></pre>
        </div>
        <?php endif; ?>
    </div>
</body>
</html>
getCredentials()
返回用户的会话数据,若未登录则返回
null
。个人信息页面在开发期间显示所有用户声明和令牌以供验证。

11. Add Logout Route

11. 添加登出路由

Create
routes/logout.php
:
php
<?php

header('Location: ' . $auth0->logout(returnUri: 'http://localhost:3000'));
exit;
logout()
returns the Auth0 logout URL. Redirect the user to it. The
returnUri
is where Auth0 sends the user after logout - it must be listed in Allowed Logout URLs. In production, replace with your actual domain.
创建
routes/logout.php
php
<?php

header('Location: ' . $auth0->logout(returnUri: 'http://localhost:3000'));
exit;
logout()
返回Auth0登出URL。将用户重定向到该页面。
returnUri
是Auth0登出后发送用户的地址 - 必须在允许的登出URL列表中。生产环境中替换为实际域名。

12. Test the App

12. 测试应用

bash
php -S localhost:3000 index.php
Visit
http://localhost:3000/login
to start the login flow.

bash
php -S localhost:3000 index.php
访问
http://localhost:3000/login
开始登录流程。

Common Mistakes

常见错误

MistakeFix
Hardcoding
domain
,
clientId
, or
clientSecret
in source
Always read from environment variables - never embed credentials in code
Using an old
auth0-PHP
version < 8.0
Require PHP 8.2+ and v8.x of the SDK; older versions have different APIs
Installing without a PSR-18 HTTP clientMust have a PSR-18 client (e.g.
guzzlehttp/guzzle
) or the SDK cannot make HTTP requests
Using
STRATEGY_API
for a web app
Web apps must use
SdkConfiguration::STRATEGY_REGULAR
for session-based auth
Passing
domain
as full URL with
https://
domain
should be the bare domain, e.g.
my-tenant.us.auth0.com
, not
https://my-tenant.us.auth0.com
Forgetting
cookieSecret
Required for session encryption - without it, the SDK throws a ConfigurationException
Not checking
getExchangeParameters()
before
exchange()
Calling
exchange()
without parameters causes errors; always check first
Not handling errors in callback
exchange()
can fail - always wrap in try/catch
Created app as SPA type in Auth0Must be Regular Web Application type for server-side auth
Not configuring callback URL in Auth0 DashboardMust add
http://localhost:3000/callback
to Allowed Callback URLs
Using
$_SESSION
directly
The SDK manages its own encrypted cookie session - do not use
$_SESSION
unless you configure a custom
SessionStore
Deploying without
cookieSecure: true
Must set to
true
in production - cookies are sent over HTTP otherwise
Calling
login()
or
logout()
without redirecting
Both return URL strings, not responses - must use
header('Location: ...')
"Network error resulted in unfulfilled request" on callbackUsually means
AUTH0_CLIENT_SECRET
is wrong, not an actual network issue - verify your credentials in
.env

错误修复方案
在代码中硬编码
domain
clientId
clientSecret
始终从环境变量读取 - 切勿在代码中嵌入凭证
使用旧版
auth0-PHP
(版本<8.0)
要求PHP 8.2+和SDK v8.x;旧版本API不同
未安装PSR-18 HTTP客户端必须有PSR-18客户端(如
guzzlehttp/guzzle
),否则SDK无法发起HTTP请求
Web应用使用
STRATEGY_API
Web应用必须使用
SdkConfiguration::STRATEGY_REGULAR
实现基于会话的身份验证
domain
传入带
https://
的完整URL
domain
应为纯域名,例如
my-tenant.us.auth0.com
,而非
https://my-tenant.us.auth0.com
遗漏
cookieSecret
会话加密必需 - 没有它SDK会抛出ConfigurationException
调用
exchange()
前未检查
getExchangeParameters()
无参数调用
exchange()
会导致错误;始终先检查
未处理回调中的错误
exchange()
可能失败 - 始终用try/catch包裹
在Auth0中创建SPA类型应用服务器端身份验证必须使用常规Web应用类型
未在Auth0控制台配置回调URL必须将
http://localhost:3000/callback
添加到允许的回调URL
直接使用
$_SESSION
SDK管理自己的加密Cookie会话 - 除非配置自定义
SessionStore
,否则不要使用
$_SESSION
部署时未设置
cookieSecure: true
生产环境必须设为
true
- 否则Cookie会通过HTTP传输
调用
login()
logout()
但未重定向
两者都返回URL字符串而非响应 - 必须使用
header('Location: ...')
回调时出现“Network error resulted in unfulfilled request”通常意味着
AUTH0_CLIENT_SECRET
错误,而非实际网络问题 - 验证
.env
中的凭证

Key SDK Methods

关键SDK方法

MethodSignaturePurpose
login
$auth0->login(?string $redirectUrl, ?array $params): string
Returns authorization URL string - redirect user to it
exchange
$auth0->exchange(?string $redirectUri, ?string $code, ?string $state): bool
Exchanges authorization code for tokens, establishes session
getCredentials
$auth0->getCredentials(): ?object
Returns current session credentials or
null
getExchangeParameters
$auth0->getExchangeParameters(): ?object
Checks if callback contains exchange parameters
logout
$auth0->logout(?string $returnUri, ?array $params): string
Returns Auth0 logout URL string
renew
$auth0->renew(?array $params): self
Refreshes expired access token (requires
offline_access
scope)
clear
$auth0->clear(bool $transient = true): self
Clears local session without Auth0 logout

方法签名用途
login
$auth0->login(?string $redirectUrl, ?array $params): string
返回授权URL字符串 - 将用户重定向到该地址
exchange
$auth0->exchange(?string $redirectUri, ?string $code, ?string $state): bool
将授权码兑换为令牌,建立会话
getCredentials
$auth0->getCredentials(): ?object
返回当前会话凭证或
null
getExchangeParameters
$auth0->getExchangeParameters(): ?object
检查回调是否包含兑换参数
logout
$auth0->logout(?string $returnUri, ?array $params): string
返回Auth0登出URL字符串
renew
$auth0->renew(?array $params): self
刷新过期的访问令牌(需要
offline_access
权限范围)
clear
$auth0->clear(bool $transient = true): self
清除本地会话,无需Auth0登出

Credentials Object

凭证对象

After successful authentication,
getCredentials()
returns an object with:
php
$credentials = $auth0->getCredentials();

$credentials->user;                    // array - user profile claims
$credentials->idToken;                 // string - raw ID token
$credentials->accessToken;             // string - access token
$credentials->refreshToken;            // string|null - refresh token (requires offline_access)
$credentials->accessTokenExpiration;   // int - expiration timestamp
$credentials->accessTokenExpired;      // bool - whether token is expired
$credentials->accessTokenScope;        // array - granted scopes
User profile claims (
$credentials->user
):
  • sub
    - unique user identifier
  • name
    ,
    nickname
    ,
    picture
  • email
    ,
    email_verified
  • given_name
    ,
    family_name
  • updated_at
    ,
    locale

身份验证成功后,
getCredentials()
返回包含以下属性的对象:
php
$credentials = $auth0->getCredentials();

$credentials->user;                    // array - 用户信息声明
$credentials->idToken;                 // string - 原始ID令牌
$credentials->accessToken;             // string - 访问令牌
$credentials->refreshToken;            // string|null - 刷新令牌(需要offline_access)
$credentials->accessTokenExpiration;   // int - 过期时间戳
$credentials->accessTokenExpired;      // bool - 令牌是否过期
$credentials->accessTokenScope;        // array - 授予的权限范围
用户信息声明 (
$credentials->user
):
  • sub
    - 唯一用户标识符
  • name
    ,
    nickname
    ,
    picture
  • email
    ,
    email_verified
  • given_name
    ,
    family_name
  • updated_at
    ,
    locale

Related Skills

相关技能

  • auth0-php-api
    - For protecting PHP APIs with JWT Bearer token validation
  • auth0-quickstart
    - Basic Auth0 setup and framework detection
  • auth0-cli
    - Manage Auth0 resources from the terminal
  • auth0-mfa
    - Add Multi-Factor Authentication

  • auth0-php-api
    - 使用JWT Bearer令牌验证保护PHP API
  • auth0-quickstart
    - 基础Auth0设置和框架检测
  • auth0-cli
    - 从终端管理Auth0资源
  • auth0-mfa
    - 添加多因素身份验证

Quick Reference

快速参考

SdkConfiguration for web apps:
php
$configuration = new SdkConfiguration(
    strategy: SdkConfiguration::STRATEGY_REGULAR,        // required
    domain: $_ENV['AUTH0_DOMAIN'],                        // required
    clientId: $_ENV['AUTH0_CLIENT_ID'],                   // required
    clientSecret: $_ENV['AUTH0_CLIENT_SECRET'],           // required
    cookieSecret: $_ENV['AUTH0_COOKIE_SECRET'],           // required
    redirectUri: $_ENV['AUTH0_REDIRECT_URI'],             // required
    scope: ['openid', 'profile', 'email'],               // recommended
);
Route protection pattern:
php
$credentials = $auth0->getCredentials();
if (null === $credentials) {
    header('Location: /login');
    exit;
}
Environment variables:
  • AUTH0_DOMAIN
    - your Auth0 tenant domain (e.g.
    tenant.us.auth0.com
    )
  • AUTH0_CLIENT_ID
    - your Application's client ID
  • AUTH0_CLIENT_SECRET
    - your Application's client secret
  • AUTH0_COOKIE_SECRET
    - encryption secret key (generate:
    openssl rand -hex 32
    )
  • AUTH0_REDIRECT_URI
    - callback URL (e.g.
    http://localhost:3000/callback
    )

Web应用的SdkConfiguration:
php
$configuration = new SdkConfiguration(
    strategy: SdkConfiguration::STRATEGY_REGULAR,        // 必填
    domain: $_ENV['AUTH0_DOMAIN'],                        // 必填
    clientId: $_ENV['AUTH0_CLIENT_ID'],                   // 必填
    clientSecret: $_ENV['AUTH0_CLIENT_SECRET'],           // 必填
    cookieSecret: $_ENV['AUTH0_COOKIE_SECRET'],           // 必填
    redirectUri: $_ENV['AUTH0_REDIRECT_URI'],             // 必填
    scope: ['openid', 'profile', 'email'],               // 推荐
);
路由保护模式:
php
$credentials = $auth0->getCredentials();
if (null === $credentials) {
    header('Location: /login');
    exit;
}
环境变量:
  • AUTH0_DOMAIN
    - 你的Auth0租户域名(例如
    tenant.us.auth0.com
  • AUTH0_CLIENT_ID
    - 应用的客户端ID
  • AUTH0_CLIENT_SECRET
    - 应用的客户端密钥
  • AUTH0_COOKIE_SECRET
    - 加密密钥(生成方式:
    openssl rand -hex 32
  • AUTH0_REDIRECT_URI
    - 回调URL(例如
    http://localhost:3000/callback

Detailed Documentation

详细文档

  • Setup Guide - Automated setup scripts, environment configuration, Auth0 CLI usage
  • Integration Guide - Protected routes, calling APIs, session management, error handling
  • API Reference - Complete Auth0 SDK API, configuration options, session storage, security

  • 设置指南 - 自动化设置脚本、环境配置、Auth0 CLI使用
  • 集成指南 - 受保护路由、API调用、会话管理、错误处理
  • API参考 - 完整的Auth0 SDK API、配置选项、会话存储、安全

References

参考链接