1. Go to this page and download the library: Download zoreal/oauth2 library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
zoreal / oauth2 example snippets
use Zoreal\OAuth2\Client;
use Zoreal\OAuth2\ClientAuth;
$zoreal = new Client(
clientId: $_ENV['ZOREAL_CLIENT_ID'], // ast_...
auth: ClientAuth::clientSecretBasic($_ENV['ZOREAL_CLIENT_SECRET']),
issuer: $_ENV['ZOREAL_ISSUER'] ?? Client::DEFAULT_ISSUER,
);
$login = $zoreal->authenticate(
code: $body['code'],
codeVerifier: $body['code_verifier'], // PKCE is mandatory; the SDK hands it over
nonce: $body['nonce'], // binds the ID token to this login
);
$login->sub(); // "TC5X-JN7G-YTSE-6E63" -- pairwise, stable for YOUR domain
$login->acr(); // "zoreal.live" | "zoreal.device" | "zoreal.session"
$login->assurance(); // uniqueness basis, verification month, chip liveness, trust tier
$login->email(); // from /userinfo, when your client has the email scope
$login->emailVerified();
$login->name(); // from /userinfo, profile.name scope
$login = $zoreal->authenticate(
code: $body['code'],
codeVerifier: $body['code_verifier'],
nonce: $body['nonce'],
acr: 'zoreal.live', // throws VerificationError unless the signed token says so
);
$login->acr(); // "zoreal.live" -- what actually happened
$login->live(); // convenience: acr() === 'zoreal.live'
$login->satisfiesAcr('zoreal.device'); // true (live is stronger than device)
$login = $zoreal->authenticate(
code: $body['code'],
codeVerifier: $body['code_verifier'],
nonce: $body['nonce'],
);
if (!$login->satisfiesAcr('zoreal.live')) {
// step the user up, or refuse the sensitive action
}
use Zoreal\OAuth2\ClientAuth;
ClientAuth::none(); // public client: PKCE is the only proof
ClientAuth::clientSecretBasic('zcs_...'); // the secret travels as HTTP Basic
ClientAuth::privateKeyJwt($pemPrivateKey, kid: 'key-1'); // RFC 7523, signed here per exchange
ClientAuth::tlsClientAuth('/path/client.crt', '/path/client.key');
$a = $login->assurance() ?? [];
if (($a['uniqueness'] ?? null) !== 'personal_number' || ($a['trust_tier'] ?? null) !== 'high') {
// not strong enough for this action -- refuse or step up
}
// POST /auth/zoreal
//
// Your frontend's ZorealLogin onSuccess posts { code, code_verifier, nonce }
// here over your own TLS. Protect this endpoint with your normal CSRF /
// same-origin controls, exactly as you would any login route -- the ZOREAL
// nonce protects the token, not your endpoint.
use Zoreal\OAuth2\Client;
use Zoreal\OAuth2\ClientAuth;
use Zoreal\OAuth2\ExchangeError;
use Zoreal\OAuth2\VerificationError;
use Zoreal\OAuth2\UserinfoError;
$zoreal = new Client(
clientId: $_ENV['ZOREAL_CLIENT_ID'],
auth: ClientAuth::clientSecretBasic($_ENV['ZOREAL_CLIENT_SECRET']),
);
$body = json_decode((string) file_get_contents('php://input'), true) ?: [];
header('Content-Type: application/json');
try {
$login = $zoreal->authenticate(
code: $body['code'] ?? '',
codeVerifier: $body['code_verifier'] ?? '',
nonce: $body['nonce'] ?? null,
// acr: 'zoreal.live', // add for a step-up / high-value login
);
$user = $users->findByProviderUid('zoreal', $login->sub());
if ($user === null) {
// Claim an existing account that owns this verified email rather than
// colliding on the unique index; otherwise create one.
if ($login->emailVerified()) {
$user = $users->findByEmail($login->email());
}
$user ??= $users->create([
'email' => $login->email(),
'name' => $login->name(),
]);
$users->linkProvider($user, 'zoreal', $login->sub());
}
session_regenerate_id(true); // fixation defence
$_SESSION['user_id'] = $user->id;
echo json_encode(['ok' => true]);
} catch (ExchangeError | VerificationError $e) {
// A spent code or a token that did not verify: the login must be restarted.
error_log('ZOREAL login failed: ' . $e->getMessage());
http_response_code(401);
echo json_encode(['error' => 'sign_in_failed']);
} catch (UserinfoError $e) {
// Personal data was unreachable. Fine for a returning user matched on sub;
// fatal for a signup that needs the email.
http_response_code(401);
echo json_encode(['error' => 'sign_in_failed']);
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.