Add integration guidance that provider abuse controls can apply across related auth endpoints based on source identity, reinforcing backoff and retry discipline.
5.1 KiB
5.1 KiB
Integration Guide (British English)
This guide shows a complete OAuth/OIDC login flow using BlackWall\Auth\AuthClient.
1. Start login
<?php
declare(strict_types=1);
session_start();
require __DIR__ . '/vendor/autoload.php';
use BlackWall\Auth\AuthClient;
use BlackWall\Auth\Config;
$client = new AuthClient(Config::fromArray([
'clientId' => 'your-client-id',
'authorizeUrl' => 'https://blackwall.cx/oauth/authorize',
'tokenUrl' => 'https://blackwall.cx/oauth/token',
'userInfoUrl' => 'https://blackwall.cx/oauth/userinfo',
'redirectUri' => 'https://your-app.example/callback.php',
'scope' => 'openid profile email offline_access',
]));
if (!isset($_SESSION['user'])) {
$auth = $client->buildAuthorisationUrl([
'extra' => [
// Some providers require nonce for OIDC requests.
'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='),
],
]);
// Prevent stale redirects from being reused from cache.
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Location: ' . $auth['url']);
exit;
}
echo 'Already signed in.';
2. Handle callback
<?php
declare(strict_types=1);
session_start();
require __DIR__ . '/vendor/autoload.php';
use BlackWall\Auth\AuthClient;
use BlackWall\Auth\Config;
$client = new AuthClient(Config::fromArray([
'clientId' => 'your-client-id',
'authorizeUrl' => 'https://blackwall.cx/oauth/authorize',
'tokenUrl' => 'https://blackwall.cx/oauth/token',
'userInfoUrl' => 'https://blackwall.cx/oauth/userinfo',
'redirectUri' => 'https://your-app.example/callback.php',
]));
if (isset($_GET['error'])) {
$error = (string) $_GET['error'];
$description = isset($_GET['error_description']) ? (string) $_GET['error_description'] : 'Unknown provider error';
// access_denied is a normal authorisation outcome (for example, membership
// revoked, privilege changed, or user denied consent between request and submit).
http_response_code($error === 'access_denied' ? 403 : 400);
exit('Authorization failed: ' . $description);
}
$result = $client->handleCallback($_GET);
$_SESSION['user'] = [
'email' => $result->user->email,
'privilege_level' => $result->user->privilegeLevel,
'role' => $result->user->role,
];
$_SESSION['access_token'] = $result->tokens->accessToken;
$_SESSION['refresh_token'] = $result->tokens->refreshToken;
header('Location: /');
exit;
3. Single callback for multiple app roles
Using one OAuth client and one callback URL is recommended.
Map users in your application by:
emailclaim to local account recordprivilege_level(orrole) to application role
Typical mapping example:
privilege_level = 1=> admin/superadminprivilege_level = 2=> user/tutor
If privilege_level is absent, the SDK also resolves common role strings (admin, superadmin, user, tutor).
4. Refresh token (optional)
<?php
$tokens = $client->refreshAccessToken($_SESSION['refresh_token']);
$_SESSION['access_token'] = $tokens->accessToken;
if ($tokens->refreshToken !== null) {
$_SESSION['refresh_token'] = $tokens->refreshToken;
}
Exceptions
Catch specific exceptions for clearer handling:
BlackWall\Auth\Exception\StateMismatchExceptionBlackWall\Auth\Exception\TokenExchangeExceptionBlackWall\Auth\Exception\UserInfoExceptionBlackWall\Auth\Exception\TransportException
Example:
try {
$tokens = $client->exchangeCodeForTokens($code);
} catch (\BlackWall\Auth\Exception\TokenExchangeException $e) {
error_log('Token exchange failed: ' . $e->getMessage());
error_log('Auth code: ' . ($e->authCode() ?? 'none'));
http_response_code(502);
}
UserInfoException with invalid_token can occur when provider-side subject scope is no longer active (for example user/project disabled) between token issuance and userinfo retrieval.
Operational guidance
- Keep provider URLs in environment variables, not hard-coded.
- Avoid printing tokens in production pages.
- Expect
429 Too Many Requestsfrom provider control endpoints under abuse protection; implement backoff/retry instead of tight loops. - Apply the same backoff strategy for provider
userinfocalls that return429 Too Many Requests. - For token exchange and refresh, apply bounded retry/backoff on transient provider failures instead of immediate repeated retries.
- If you call provider WebAuthn login challenge/verify endpoints directly, use
POSTonly. - Configure OAuth client redirect URIs as HTTPS in production; reserve HTTP for localhost loopback testing only.
- Assume provider rate limits are enforced per source identity (for example IP) and shared across related auth endpoints.
- Rotate client secrets for confidential clients.
- Add a unique
nonceto each OIDC authorisation request. - Validate
stateon every callback request. - Use secure session cookies (
Secure,HttpOnly,SameSite=Laxor stricter). - HTTPS URLs are enforced by default in
Config::fromArray(). - For localhost-only HTTP testing, explicitly set
allowInsecureHttp => true.