Skip to Content
SDKsPHP

PHP SDK (auris/sdk)

auris/sdk v0.1.0

auris/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
  • curl extension enabled
  • openssl extension enabled (for PKCE)
  • session extension enabled (for the default SessionTokenStore)

Installation

composer require auris/sdk

Classes

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:

ParameterTypeRequiredDefaultDescription
domainstringYes—Auris tenant domain, without https://
clientIdstringYes—Application Client ID from the Console
redirectUristringYes—Must exactly match a registered Callback URL
clientSecret?stringNonullClient secret for confidential server-side apps
scopestringNo'openid profile email'Space-separated OAuth2 scopes
tenantstringNo'default'Tenant identifier
tokenStore?TokenStoreNonullCustom 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:

OptionTypeDescription
login_hintstringPre-fill the email field
screen_hint'signup'Open the registration screen
prompt'login' | 'none'Force re-auth or silent check
localestringUI locale (en, it, de, fr, es)
connectionstringForce 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:

CodeDescription
invalid_stateCSRF state mismatch — possible attack or stale session
invalid_grantAuthorization code is invalid, expired, or already used
invalid_clientClient ID or redirect URI does not match the registered application
network_errorcURL request to the Auris API failed
token_expiredThe access token is expired — call refreshToken()
no_refresh_tokenNo 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')); });