Sign in to the help center through your application

An owner or administrator with settings.manage configures Settings → Branding → Help-center sign-in. This lets your application authenticate a reader of customer-only content and, with a stable identity, their ticket portal. It uses the help-center JWT signing secret, which is distinct from the widget identity secret.

Configure the handshake

Generate the help-center secret and store it on your server. Configure a sign-in URL on your application that authenticates the reader before signing a token. Copy the portal's displayed return URL as a fixed configuration value; the actual Cairn callback is <your-help-center-origin>/auth. /portal is a possible destination after authentication, not the authentication callback.

When a protected page offers sign-in, Cairn sends the application a return query parameter containing a local destination path. Your endpoint should remember that path through login and return to the fixed help-center callback with token and return query parameters. Do not accept an arbitrary callback origin from the request.

PHP example

Use firebase/php-jwt as a direct dependency. All identity fields come from the authenticated server account:

use Firebase\JWT\JWT;

$destination = $request->query('return', '/');
// Keep a local help-center path only. The help center validates this again.
if (!is_string($destination) || !str_starts_with($destination, '/')
    || str_starts_with($destination, '//') || str_contains($destination, '\\')
    || preg_match('/[\x00-\x20\x7f]/', $destination)) {
    $destination = '/';
}
$secret = config('cairn.helpcenter_jwt_secret');
$callback = config('cairn.helpcenter_auth_return_url'); // Exact portal-issued /auth URL.
abort_unless(is_string($secret) && $secret !== '' && is_string($callback) && $callback !== '', 503);
$token = JWT::encode([
    'sub' => 'platform-account:'.$account->id,
    'email' => strtolower(trim($account->email)),
    'name' => $account->name,
    'exp' => time() + 3600,
], $secret, 'HS256');
return redirect()->away($callback.'?'.http_build_query(['token' => $token, 'return' => $destination]))
    ->header('Cache-Control', 'no-store')->header('Referrer-Policy', 'no-referrer');

Preserve the validated destination through your application's normal session-based sign-in. Do not trust a return value as an external URL; absolute URLs, protocol-relative paths, backslashes and control characters must never become redirect targets. The help center independently canonicalizes the local path and falls back to / for unsafe input.

Session duration and ticket identity

JWT expiry determines the help-center session duration. The one-hour example intentionally requires sign-in again after one hour. Do not use a long expiry to simulate a permanent session. Cairn verifies HS256 and requires a future exp; do not invent extra audience claims as a way to access internal knowledge.

An expiry-only JWT can authenticate content, but include a stable sub and the user's server-derived email/name for a useful ticket identity. The reader's ticket access is scoped to the resolved contact in this workspace. A widget JWT is not interchangeable with this token.

The callback receives a token in its URL. Redact that query parameter from application, proxy and analytics logs, avoid third-party scripts on the handshake page, and never include a token in a support screenshot. The callback immediately redirects to the local destination after accepting it.

Verify

As an anonymous reader, a public article remains readable and customer-only content offers sign-in. Sign in through your application and confirm the requested local article opens. Repeat with /portal; the authenticated reader sees only their own tickets. Test invalid signatures, expired tokens, a token signed with the widget secret, and malicious return values such as //other.example and /\\other.example.

Repeat on the actual custom help-center hostname over valid HTTPS, without a Cairn platform administrator. Verify an internal article cannot be accessed by a customer token. When rotating the help-center secret, replace the server configuration and repeat these checks; the portal displays whether a secret is configured.