PHP SDK (auris/sdk)
auris/sdk v0.1.0auris/sdk is the official PHP client library for Auris IAM. It implements the OAuth2 Authorization Code flow with PKCE (S256) and provides a clean API for retrieving user information and managing tokens.
The library has no external dependencies — it uses only PHP built-ins (curl, session, hash, openssl) and works with PHP 7.4 and above.
Requirements
- PHP 7.4 or higher
curlextension enabledopensslextension enabled (for PKCE)sessionextension enabled (for the defaultSessionTokenStore)
Installation
composer require auris/sdkClasses
AurisConfig
Holds all configuration for the Auris client. Pass an instance to AurisClient.
use Auris\AurisConfig;
$config = new AurisConfig(
domain: 'auth.yourdomain.com', // Required — your Auris tenant domain
clientId: 'app_xxxxx', // Required — Application Client ID
redirectUri: 'https://app.com/callback.php', // Required — must be registered in the Console
clientSecret: null, // Optional — only for confidential clients
scope: 'openid profile email', // Optional — OAuth2 scopes (default shown)
tenant: 'my-tenant', // Optional — sent as x-tenant header
tokenStore: null, // Optional — custom TokenStore instance
);Constructor parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
domain | string | Yes | — | Auris tenant domain, without https:// |
clientId | string | Yes | — | Application Client ID from the Console |
redirectUri | string | Yes | — | Must exactly match a registered Callback URL |
clientSecret | ?string | No | null | Client secret for confidential server-side apps |
scope | string | No | 'openid profile email' | Space-separated OAuth2 scopes |
tenant | string | No | 'default' | Tenant identifier |
tokenStore | ?TokenStore | No | null | Custom storage backend. Defaults to SessionTokenStore. |
AurisClient
The main client class. Instantiate it with an AurisConfig object.
use Auris\AurisClient;
use Auris\AurisConfig;
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback.php'
);
$auris = new AurisClient($config);getLoginUrl(options?): string
Generates the Auris hosted login URL including PKCE parameters and a CSRF state token. The PKCE code verifier and state are stored in the session automatically.
// Redirect to the hosted login page
$loginUrl = $auris->getLoginUrl();
header('Location: ' . $loginUrl);
exit;
// With additional options
$loginUrl = $auris->getLoginUrl([
'login_hint' => '[email protected]',
'screen_hint' => 'signup',
'locale' => 'it',
'prompt' => 'login',
]);Available options:
| Option | Type | Description |
|---|---|---|
login_hint | string | Pre-fill the email field |
screen_hint | 'signup' | Open the registration screen |
prompt | 'login' | 'none' | Force re-auth or silent check |
locale | string | UI locale (en, it, de, fr, es) |
connection | string | Force a specific SSO connection |
handleCallback(code, state): TokenResult
Exchanges the authorization code received on the callback URL for tokens. Validates the state parameter against the stored value to prevent CSRF attacks.
Throws AurisException if the state is invalid, the code exchange fails, or the network request errors.
// callback.php
session_start();
try {
$result = $auris->handleCallback(
code: $_GET['code'] ?? '',
state: $_GET['state'] ?? ''
);
// Tokens are now stored in the session
echo 'Authenticated! Access token expires in ' . $result->expiresIn . ' seconds.';
} catch (Auris\AurisException $e) {
http_response_code(400);
echo 'Authentication failed: ' . htmlspecialchars($e->getMessage());
}isAuthenticated(): bool
Returns true if the user has a valid (non-expired) access token stored in the current session.
if (!$auris->isAuthenticated()) {
header('Location: /login.php');
exit;
}getUser(): ?AurisUser
Returns the currently authenticated user by decoding the stored ID token. Returns null if no session is active.
$user = $auris->getUser();
if ($user !== null) {
echo 'Hello, ' . htmlspecialchars($user->firstName);
echo ' (ID: ' . $user->id . ')';
echo ' Roles: ' . implode(', ', $user->roles);
}getAccessToken(): ?string
Returns the stored access token string, or null if not authenticated. Use this token in Authorization: Bearer headers when calling your own API.
$token = $auris->getAccessToken();
if ($token !== null) {
$ch = curl_init('https://api.yourapp.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $token,
'Accept: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
}refreshToken(): TokenResult
Exchanges the stored refresh token for a new access token and refresh token pair. Updates the stored tokens automatically.
Throws AurisException if no refresh token is available or the refresh fails.
try {
$result = $auris->refreshToken();
echo 'New access token expires in ' . $result->expiresIn . ' seconds.';
} catch (Auris\AurisException $e) {
// Refresh failed — redirect to login
header('Location: /login.php');
exit;
}logout(returnTo?): void
Clears the stored tokens from the session and optionally redirects the browser.
// Clear tokens and redirect to the home page
$auris->logout(returnTo: 'https://yourapp.com/');Pkce
Static helper class for generating PKCE parameters. You do not normally need to call these directly — AurisClient::getLoginUrl() handles PKCE automatically. These are exposed for custom integrations.
use Auris\Pkce;
// Generate a 128-byte code verifier (URL-safe base64, 43–128 chars)
$verifier = Pkce::generateVerifier();
// Derive the S256 code challenge from the verifier
$challenge = Pkce::generateChallenge($verifier);
// Generate a cryptographically random state string (CSRF protection)
$state = Pkce::generateState();TokenResult
Returned by handleCallback() and refreshToken(). Contains the raw token data from the Auris token endpoint.
class TokenResult
{
public string $accessToken;
public ?string $refreshToken;
public int $expiresIn; // Seconds until the access token expires
public string $tokenType; // Always 'Bearer'
public ?string $idToken; // JWT containing user claims
public function getUser(): AurisUser; // Decode user info from the ID token
}AurisUser
Represents the authenticated user, decoded from the ID token.
class AurisUser
{
public string $id; // Auris user ID
public string $sub; // JWT subject claim (same as $id)
public string $email;
public bool $emailVerified;
public string $name; // Full display name
public string $firstName;
public string $lastName;
public string $username;
public ?string $picture; // Profile picture URL
public array $roles; // string[] — assigned role names
public array $metadata; // Custom key-value metadata
public string $tenant;
public string $createdAt;
}TokenStore and SessionTokenStore
TokenStore is the interface for persisting tokens across requests. The default implementation SessionTokenStore stores tokens in PHP’s native $_SESSION.
SessionTokenStore is used automatically when no custom store is provided. It requires session_start() to have been called before instantiating AurisClient.
To use a custom backend, implement the TokenStore interface:
use Auris\TokenStore;
class DatabaseTokenStore implements TokenStore
{
public function __construct(
private \PDO $pdo,
private string $userId
) {}
public function get(string $key): ?string
{
$stmt = $this->pdo->prepare(
'SELECT value FROM auris_tokens WHERE user_id = :uid AND key = :key'
);
$stmt->execute([':uid' => $this->userId, ':key' => $key]);
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
return $row ? $row['value'] : null;
}
public function set(string $key, string $value): void
{
$stmt = $this->pdo->prepare(
'INSERT INTO auris_tokens (user_id, key, value)
VALUES (:uid, :key, :val)
ON DUPLICATE KEY UPDATE value = :val'
);
$stmt->execute([':uid' => $this->userId, ':key' => $key, ':val' => $value]);
}
public function remove(string $key): void
{
$stmt = $this->pdo->prepare(
'DELETE FROM auris_tokens WHERE user_id = :uid AND key = :key'
);
$stmt->execute([':uid' => $this->userId, ':key' => $key]);
}
}
// Pass the custom store via AurisConfig
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'https://yourapp.com/callback.php',
tokenStore: new DatabaseTokenStore($pdo, $currentUserId)
);AurisException
Thrown by AurisClient on error. Contains a machine-readable $code and human-readable $message.
class AurisException extends \RuntimeException
{
public string $code; // Machine-readable error code
public int $httpStatus; // HTTP status code (0 for network errors)
}Common error codes:
| Code | Description |
|---|---|
invalid_state | CSRF state mismatch — possible attack or stale session |
invalid_grant | Authorization code is invalid, expired, or already used |
invalid_client | Client ID or redirect URI does not match the registered application |
network_error | cURL request to the Auris API failed |
token_expired | The access token is expired — call refreshToken() |
no_refresh_token | No refresh token in session — user must log in again |
Vanilla PHP Example
A complete login flow across four files:
<?php
// login.php — redirect to Auris hosted login
require 'vendor/autoload.php';
use Auris\AurisClient;
use Auris\AurisConfig;
session_start();
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:8000/callback.php'
);
$auris = new AurisClient($config);
header('Location: ' . $auris->getLoginUrl());
exit;<?php
// callback.php — handle the redirect back from Auris
require 'vendor/autoload.php';
use Auris\AurisClient;
use Auris\AurisConfig;
use Auris\AurisException;
session_start();
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:8000/callback.php'
);
$auris = new AurisClient($config);
try {
$auris->handleCallback(
code: $_GET['code'] ?? '',
state: $_GET['state'] ?? ''
);
header('Location: /dashboard.php');
exit;
} catch (AurisException $e) {
http_response_code(400);
echo '<p>Login failed: ' . htmlspecialchars($e->getMessage()) . '</p>';
echo '<a href="/login.php">Try again</a>';
}<?php
// dashboard.php — protected page
require 'vendor/autoload.php';
use Auris\AurisClient;
use Auris\AurisConfig;
session_start();
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:8000/callback.php'
);
$auris = new AurisClient($config);
if (!$auris->isAuthenticated()) {
header('Location: /login.php');
exit;
}
$user = $auris->getUser();
?>
<!DOCTYPE html>
<html lang="en">
<head><title>Dashboard</title></head>
<body>
<h1>Welcome, <?= htmlspecialchars($user->firstName) ?></h1>
<p>Email: <?= htmlspecialchars($user->email) ?></p>
<p>Roles: <?= htmlspecialchars(implode(', ', $user->roles)) ?></p>
<a href="/logout.php">Sign out</a>
</body>
</html><?php
// logout.php — clear session and redirect
require 'vendor/autoload.php';
use Auris\AurisClient;
use Auris\AurisConfig;
session_start();
$config = new AurisConfig(
domain: 'auth.yourdomain.com',
clientId: 'your-client-id',
redirectUri: 'http://localhost:8000/callback.php'
);
$auris = new AurisClient($config);
$auris->logout(returnTo: 'http://localhost:8000/');Laravel Integration
Service Provider
Register AurisClient in the Laravel service container as a singleton:
// app/Providers/AurisServiceProvider.php
namespace App\Providers;
use Auris\AurisClient;
use Auris\AurisConfig;
use Illuminate\Support\ServiceProvider;
class AurisServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(AurisClient::class, function () {
$config = new AurisConfig(
domain: config('auris.domain'),
clientId: config('auris.client_id'),
redirectUri: config('auris.redirect_uri'),
clientSecret: config('auris.client_secret'),
tenant: config('auris.tenant', 'default'),
);
return new AurisClient($config);
});
}
}Configuration File
// config/auris.php
return [
'domain' => env('AURIS_DOMAIN'),
'client_id' => env('AURIS_CLIENT_ID'),
'client_secret' => env('AURIS_CLIENT_SECRET'),
'redirect_uri' => env('AURIS_REDIRECT_URI'),
'tenant' => env('AURIS_TENANT', 'default'),
];Controller
// app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;
use Auris\AurisClient;
use Auris\AurisException;
use Illuminate\Http\Request;
class AuthController extends Controller
{
public function __construct(private AurisClient $auris) {}
public function login()
{
return redirect($this->auris->getLoginUrl());
}
public function callback(Request $request)
{
try {
$this->auris->handleCallback(
$request->query('code', ''),
$request->query('state', '')
);
return redirect('/dashboard');
} catch (AurisException $e) {
return redirect('/login')->withErrors(['auth' => $e->getMessage()]);
}
}
public function logout()
{
$this->auris->logout(returnTo: config('app.url'));
return redirect('/');
}
}Middleware
// app/Http/Middleware/RequireAurisAuth.php
namespace App\Http\Middleware;
use Auris\AurisClient;
use Closure;
use Illuminate\Http\Request;
class RequireAurisAuth
{
public function __construct(private AurisClient $auris) {}
public function handle(Request $request, Closure $next)
{
if (!$this->auris->isAuthenticated()) {
return redirect('/login');
}
return $next($request);
}
}// routes/web.php
use App\Http\Controllers\AuthController;
use App\Http\Middleware\RequireAurisAuth;
Route::get('/auth/login', [AuthController::class, 'login']);
Route::get('/auth/callback', [AuthController::class, 'callback']);
Route::get('/auth/logout', [AuthController::class, 'logout']);
Route::middleware(RequireAurisAuth::class)->group(function () {
Route::get('/dashboard', fn() => view('dashboard'));
Route::get('/settings', fn() => view('settings'));
});Related Pages
- WordPress Plugin — SSO plugin built on top of the PHP SDK
- Hosted Login Guide — PKCE flow explained
- JavaScript SDK — For browser and Node.js integrations