Looking to hire Laravel developers? Try LaraJobs
This package is not available.

authos-client-laravel maintained by rishadblack

Description
Authos client for Laravel applications: the button block, the code exchange, the management API and signed webhooks.
Author
Last update
2026/10/30 13:10 (dev-main)
License
Downloads
31

Comments
comments powered by Disqus

Authos Client for Laravel

The official Laravel client for Authos. Add hosted social login to an existing Laravel application without moving its users, passwords, sessions, or authorization rules into Authos.

The package provides:

  • a Blade button block for the providers enabled for your application;
  • signed, short-lived state for login, sign-up, and account-connection flows;
  • a callback route that exchanges one-time codes server to server;
  • a signed webhook endpoint and Laravel event;
  • methods for links, identities, users, tenants, and event recovery;
  • an in-memory fake for application tests.

Your application decides what every accepted or rejected result means. It keeps its own registration, authentication, sessions, two-step verification, permissions, and user records.

Contents

Requirements

Dependency Version
PHP 8.3 or newer
Laravel 12 or 13

Installation

composer require rishadblack/authos-client-laravel
php artisan vendor:publish --tag=authos-config

Laravel discovers Authos\Laravel\AuthosServiceProvider automatically. Publishing the configuration is optional; environment variables are enough for the standard setup.

Authos application setup

Create an application in the Authos dashboard, then add the exact callback and webhook addresses used by your Laravel application.

Default addresses:

https://your-app.example/auth/authos/callback
https://your-app.example/api/webhooks/authos

Copy the application id, application secret, and webhook secret into .env:

AUTHOS_URL=https://auth.sylloo.com
AUTHOS_CLIENT_ID=app_your_public_id
AUTHOS_SECRET=sk_your_key_id.your_secret
AUTHOS_WEBHOOK_SECRET=whsec_your_webhook_secret

Never expose AUTHOS_SECRET or AUTHOS_WEBHOOK_SECRET to a browser, mobile application, log, or public repository.

Configuration

The published config/authos.php supports these settings:

Environment variable Default Purpose
AUTHOS_URL https://auth.sylloo.com Authos service address
AUTHOS_CLIENT_ID none public application id
AUTHOS_SECRET none server-side application secret
AUTHOS_WEBHOOK_SECRET none verifies incoming webhook signatures
AUTHOS_ROUTES true registers the package callback and webhook routes
AUTHOS_CALLBACK_PATH auth/authos/callback callback route path
AUTHOS_WEBHOOK_PATH api/webhooks/authos webhook route path
AUTHOS_DOMAIN none optional host used by both package routes
AUTHOS_REDIRECT_URI generated callback URL exact callback registered in Authos
AUTHOS_BIND_STATE_TO_SESSION true binds signed state to the browser session
AUTHOS_REMEMBER_DOMAIN current host cookie domain for the last successful provider

Use AUTHOS_DOMAIN when callbacks and webhooks must exist only on one central host. Set an explicit AUTHOS_REDIRECT_URI when Laravel cannot generate the public callback address correctly.

Keep session binding enabled for a normal application. A multi-host application may disable it when the button and callback are necessarily on different hosts, but should carry its own nonce in state and verify it on the original host with Authos::pullNonce().

Inspect the registered routes with:

php artisan route:list --name=authos

Handle callback results

The callback route is registered only after the application binds Authos\Laravel\Contracts\HandlesAuthosResult. Create a class that translates Authos results into your application's own sign-in, registration, refusal, or account-linking flow:

<?php

namespace App\Authos;

use Authos\Laravel\Contracts\HandlesAuthosResult;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class AuthosResultHandler implements HandlesAuthosResult
{
    public function handle(array $result, array $state, Request $request): Response
    {
        if (($result['result'] ?? null) === 'rejected') {
            return redirect()->route('login')->withErrors([
                'authos' => 'This social login could not be used.',
            ]);
        }

        // Call your application Action here. Match or create the local user according
        // to your own rules, run any required two-step check, then start your session.

        return redirect()->intended($state['return'] ?? route('dashboard'));
    }

    public function failed(string $reason, Request $request): Response
    {
        return redirect()->route('login')->withErrors([
            'authos' => 'The social login expired. Please try again.',
        ]);
    }
}

Bind it in a service provider:

use App\Authos\AuthosResultHandler;
use Authos\Laravel\Contracts\HandlesAuthosResult;

public function register(): void
{
    $this->app->bind(HandlesAuthosResult::class, AuthosResultHandler::class);
}

The handler receives:

  • $result: the verified exchange response, including result, reason, attempt, user, identity, and link when applicable;
  • $state: values signed when the button URL was built, such as intent, tenant, kind, return, and your custom state values;
  • $request: the Laravel callback request.

Do not trust a browser-supplied user id or email. Use only the verified exchange result and enforce your normal local authorization and account-matching rules.

Render provider buttons

Place the component under the application's existing sign-in or registration form:

<x-authos-buttons intent="login" return="/dashboard" />

For a tenant-aware application:

<x-authos-buttons
    intent="signup"
    :tenant="$business->getKey()"
    kind="customer"
    :state="['host' => request()->getHost()]"
    return="/account"
/>

Available component properties:

Property Default Purpose
intent login login, signup, or connect
tenant none application-defined tenant identifier
kind none application-defined local user kind
return none signed local destination for the handler
login-hint none email hint sent to the provider
connect-token none proof used by a signed-in user connecting a provider
choose-account false asks the provider to show its account chooser
state [] additional values included in signed state

Enabled providers are cached for ten minutes. If Authos is unavailable, the component renders nothing after a short timeout, leaving the application's normal form usable.

Build an individual URL through dependency injection or the facade when you need custom markup:

use Authos\Laravel\Facades\Authos;

$url = Authos::connectUrl('login', 'google', [
    'tenant' => (string) $business->getKey(),
    'kind' => 'member',
    'return' => '/dashboard',
    'prompt' => 'select_account',
    'state' => ['host' => request()->getHost()],
]);

Connect another provider

A connect flow starts from an already authenticated local account. First request a short-lived connect token on the server, then give it to the button component:

use Authos\Laravel\Facades\Authos;

$proof = Authos::connectToken(
    externalId: (string) $user->getKey(),
    tenant: $business->getKey(),
    kind: 'member',
    sub: $user->authos_sub,
);
<x-authos-buttons
    intent="connect"
    :tenant="$business->getKey()"
    kind="member"
    :connect-token="$proof['connect_token']"
    return="/profile/security"
/>

Only issue connect tokens after authenticating and authorizing the local user.

Handle webhooks

The package verifies Authos-Id, Authos-Timestamp, and Authos-Signature before dispatching AuthosWebhookReceived. Invalid or stale signatures receive HTTP 401.

Register a listener in your application:

<?php

namespace App\Listeners;

use Authos\Laravel\Events\AuthosWebhookReceived;
use Illuminate\Contracts\Queue\ShouldQueue;

final class ApplyAuthosEvent implements ShouldQueue
{
    public function handle(AuthosWebhookReceived $event): void
    {
        // Make this idempotent: store $event->id before applying the change.
        // Handle the event type through your application's own Actions.
    }
}

Important event types include user.updated, user.merged, user.deleted, link.removed, and attempt.flagged. Events can be delivered more than once or out of order. Queue processing, keep every processed event id, and ignore duplicates.

If delivery was interrupted, recover events from the API:

$page = Authos::events(after: $lastEventId, types: ['user.merged', 'user.deleted']);

Client methods

Use Authos\Laravel\Facades\Authos or inject Authos\Laravel\Authos.

Method Purpose
connectUrl($intent, $provider, $options) build a hosted-flow URL with signed state
exchange($code, $externalId, $metadata, $kind) exchange a one-time callback code
connectToken($externalId, $tenant, $kind, $sub) authorize a connect flow for a local user
link($sub, $tenant, $kind, $externalId, $metadata) connect an Authos account to a local record
removeLink($sub, $tenant) remove one application or tenant link
removeTenant($tenant) request removal of every link for a deleted tenant
disconnect($sub, $provider) remove one provider identity
user($sub) read the application's view of an Authos account
block($sub, $tenant, $blocked) block or unblock social login
providers() get enabled providers, cached for ten minutes
events($after, $types) recover application events
readState($state) verify and consume signed callback state
pullNonce($nonce) consume a session nonce in a multi-host flow

Every write automatically receives a unique Idempotency-Key. Authos returns machine-readable error codes when it refuses a request.

Errors

API and connection failures throw Authos\Laravel\AuthosException:

use Authos\Laravel\AuthosException;
use Authos\Laravel\Facades\Authos;

try {
    $user = Authos::user($sub);
} catch (AuthosException $exception) {
    report($exception);

    $code = $exception->errorCode; // e.g. unauthorized, link_not_found, unreachable
    $status = $exception->status;  // 0 when the service could not be reached
}

Show plain application-owned messages to users. Do not expose secrets, raw upstream responses, or stack traces.

Testing

Replace the client with its fake in a Pest or PHPUnit test:

use Authos\Laravel\Facades\Authos;

$authos = Authos::fake()->respond('/api/v1/attempts/exchange', [
    'result' => 'signed_in',
    'user' => ['sub' => 'usr_example', 'email' => 'person@example.com'],
    'attempt' => ['provider' => 'google'],
]);

// Exercise your callback or Action.

$authos->assertSent('/api/v1/attempts/exchange', function (array $call): bool {
    return $call['method'] === 'post'
        && $call['data']['code'] === 'one_time_code';
});

Other helpers:

$authos->respond('/api/v1/users/usr_example', ['data' => ['sub' => 'usr_example']]);
$authos->assertSent('/api/v1/users/usr_example');
$authos->assertNothingSent();

The fake signs and verifies state with the same implementation as the real client. By default, its provider list contains Google and GitHub; queue a provider response when a test needs another list.

Security notes

  • Keep application and webhook secrets on the server.
  • Register exact callback addresses in Authos and use HTTPS in production.
  • Keep signed state bound to the session unless the application has a deliberate multi-host design.
  • Treat callback codes and connect tokens as short-lived, one-time values.
  • Authorize local writes before calling link, disconnect, removeLink, removeTenant, or block.
  • Process webhooks idempotently and in a queue.
  • Continue enforcing the application's own two-step verification and session rules after social login.
  • Do not use an unverified provider email as proof of account ownership.

License

Authos Client for Laravel is open-source software licensed under the MIT License.