TausiDocs

PHP and Laravel

PHP 8.1+ with ext-curl and ext-json, no other dependencies. TausiBackend (secret key) protects your API and manages users; TausiClient (publishable key) signs users in from server-rendered pages and keeps the token in $_SESSION.

Install

tausi/tausi-php on PackagistRequires PHP 8.1+ with ext-curl and ext-json; no other dependencies
Shell
composer require tausi/tausi-php
.env.env
TAUSI_URL=https://tausi-auth.onrender.com
TAUSI_PUBLISHABLE_KEY=pk_…
TAUSI_SECRET_KEY=sk_…

Protect your API

api.phpPHP
<?php
use Tausi\TausiBackend;

$tausi = new TausiBackend(getenv('TAUSI_URL'), getenv('TAUSI_SECRET_KEY'));

$auth = $tausi->authenticateRequest();   // reads Authorization: Bearer <token> from $_SERVER
if ($auth === null) {
    http_response_code(401);
    exit(json_encode(['error' => 'Unauthorized']));
}
echo json_encode(['id' => $auth->user->id, 'email' => $auth->user->email]);

authenticateRequest() and verifySession($token) return null for invalid, expired, revoked or banned sessions, and throw TausiException only for problems on your side (wrong key, network, 5xx).

Apache with PHP-FPM or CGI
The Authorization header may never reach PHP. Add CGIPassAuth On, or pass the header in yourself: $tausi->authenticateRequest($request->header('Authorization')).

Laravel

app/Providers/AppServiceProvider.phpPHP
public function register(): void
{
    $this->app->singleton(\Tausi\TausiBackend::class, fn () => new \Tausi\TausiBackend(
        config('services.tausi.url'),
        config('services.tausi.secret'),
    ));
}

// config/services.php
'tausi' => ['url' => env('TAUSI_URL'), 'secret' => env('TAUSI_SECRET_KEY')],
app/Http/Middleware/TausiAuth.phpPHP
<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Tausi\TausiBackend;
use Tausi\TausiException;

final class TausiAuth
{
    public function __construct(private readonly TausiBackend $tausi) {}

    public function handle(Request $request, Closure $next)
    {
        try {
            $auth = $this->tausi->authenticateRequest($request->header('Authorization'));
        } catch (TausiException) {
            return response()->json(['error' => 'Authentication unavailable'], 503);
        }
        if ($auth === null) {
            return response()->json(['error' => ['code' => 'UNAUTHENTICATED']], 401);
        }
        $request->attributes->set('tausi', $auth);
        return $next($request);
    }
}
bootstrap/app.php and routes/api.phpPHP
->withMiddleware(fn ($m) => $m->alias(['tausi' => \App\Http\Middleware\TausiAuth::class]))

Route::middleware('tausi')->get('/me', fn (Request $r) => $r->attributes->get('tausi')->user->toArray());

Server-rendered sign-in

When PHP renders the forms itself, use TausiClient. The token stays in $_SESSION on the server and never reaches the browser:

sign-in.phpPHP
<?php
use Tausi\TausiClient;
use Tausi\TausiException;
use Tausi\TokenStore\PhpSessionTokenStore;

session_start();
$tausi = new TausiClient(getenv('TAUSI_URL'), getenv('TAUSI_PUBLISHABLE_KEY'), new PhpSessionTokenStore());

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        $tausi->signIn($_POST['email'], $_POST['password']);   // also regenerates the PHP session id
        header('Location: /dashboard');
        exit;
    } catch (TausiException $e) {
        $error = match ($e->errorCode) {
            'INVALID_CREDENTIALS' => 'Wrong email or password.',
            'EMAIL_NOT_VERIFIED' => 'Check your inbox to verify your email first.',
            default => $e->getMessage(),   // ACCOUNT_BANNED, ACCOUNT_SUSPENDED, RATE_LIMITED, ...
        };
    }
}

// On protected pages:
$auth = $tausi->getSession();   // AuthResult or null (no request without a token)
if ($auth === null) { header('Location: /sign-in'); exit; }
sign-up and profilePHP
$tausi->signUp($email, $password, $name, [
    'username' => 'asha', 'phoneNumber' => '+255712345678', 'timezone' => 'Africa/Dar_es_Salaam',
]);   // EMAIL_ALREADY_REGISTERED (409) if the email has an account; its owner gets an email

$tausi->updateUser(['firstName' => 'Asha', 'timezone' => null]);   // null clears a field
$tausi->changePassword($current, $new);                            // signs out other devices
$tausi->listSessions();  $tausi->revokeOtherSessions();
$tausi->signOut();
Rate limits
When PHP calls Tausi on behalf of users, Tausi sees your server's IP, so per-IP sign-in limits apply to all your users together. For busy sign-in pages, let the browser sign in with @tausi-auth/js and only verify the token in PHP.

Social sign-in

oauth.phpPHP
// /login/google
$start = $tausi->startOAuth('google', 'https://app.example.com/auth/callback');   // must be on an allowed origin
$_SESSION['tausi_verifier'] = $start->codeVerifier;
header('Location: ' . $start->url);

// /auth/callback
try {
    $tausi->handleOAuthRedirect($_GET, $_SESSION['tausi_verifier'] ?? '');
} catch (TausiException $e) {
    // e.g. access_denied (cancelled), account_banned
} finally {
    unset($_SESSION['tausi_verifier']);
}

Manage users

admin.phpPHP
$page = $tausi->listUsers(['q' => 'asha', 'access' => 'banned', 'pageSize' => 50]);
foreach ($page->items as $u) {
    echo $u->email, ' ', $u->status, ' ', $u->activeSessions, ' ', $u->lastSignInAt, ' ', $u->access;
}
$detail = $tausi->getUser($userId);   // user, sessions (devices), signInHistory, recentAudit

$tausi->updateUser($userId, ['emailVerified' => true, 'privateMetadata' => ['stripeId' => 'cus_123']]);
$tausi->suspendUser($userId, new DateTimeImmutable('+7 days'), 'Chargeback');
$tausi->banUser($userId, 'Spam');   $tausi->unbanUser($userId);
$tausi->bulkUsers('revoke_sessions', [$idA, $idB]);
$tausi->revokeUserSessions($userId);
$tausi->deleteUser($userId);

See Managing users for what each action does.

Errors

Every API error is a Tausi\TausiException with status, errorCode, getMessage(), details, requestId and retryAfter. Network failures have status 0 and code NETWORK_ERROR or TIMEOUT. All codes.

To use Guzzle or Symfony HttpClient, implement Tausi\Http\HttpClient and pass it as the third argument of TausiBackend or the fourth of TausiClient.