Search by

atannex / laravel-flutter-bridge

Atanga1920

Enterprise-grade Laravel bridge for Flutter applications: Sanctum auth with rotating refresh tokens, Laravel Fortify account features over bearer tokens, connection sessions & remote sign-out, app keys with version policy, Reverb broadcasting, device registration, and Dart code generation.

Package info

github.com/atannex/laravel-flutter-bridge

pkg:composer/atannex/laravel-flutter-bridge

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v2.2.0 2026-11-10 23:51 UTC

This package is auto-updated.

Last update: 2026-11-11 00:48:12 UTC


README

Latest Version on Packagist License: MIT

An enterprise-grade Laravel package designed to seamlessly connect Laravel backends to Flutter applications. Provides standardized API response envelopes, device FCM registration, Sanctum token management, WebSocket broadcasting auth, and automated Dart model/route code generation.

๐ŸŒŸ Key Features

  • Standardized API Envelope: Unified JSON envelope across all endpoints (success, message, data, errors, meta).
  • Sanctum Device Auth: Issue and revoke personal access tokens per physical device with auto-refresh support.
  • Push Notification Registry: Multi-device management tracking FCM tokens, OS version, platform, and active status.
  • Bearer Broadcast Auth: Dedicated WebSocket authentication route for Laravel Reverb and Pusher without session cookies.
  • Dart Code Generator: Artisan commands to reflect Eloquent models into null-safe Dart classes and export typed API route registries.
  • Middleware Suite: Enforces JSON expectations, client telemetry logging, and response standardization.
  • Connection Management: Handshake discovery, heartbeated connection sessions, remote sign-out, server โ†’ client commands, app keys with version policy and rotating refresh tokens.

๐Ÿ“ฆ Installation

Add the package to your Laravel application:

composer require atannex/laravel-flutter-bridge

Publish configuration and migrations:

php artisan flutter:install
php artisan migrate

Verify your environment status:

php artisan flutter:status

๐Ÿš€ Quick Setup

1. Update User Model

Add Sanctum's HasApiTokens plus the HasFlutterTokens and HasFlutterDevices traits to your User model (HasApiTokens alone is enough for the bridge endpoints; the bridge traits add helpers such as createFlutterToken() and flutterConnections()):

use Atannex\LaravelFlutterBridge\Traits\HasFlutterDevices;
use Atannex\LaravelFlutterBridge\Traits\HasFlutterTokens;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFlutterTokens, HasFlutterDevices;
}

2. Using Response Macros

In your controllers, take advantage of built-in Flutter response macros:

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::latest()->paginate(15);
        return response()->flutterPaginated($posts, 'Posts fetched');
    }

    public function show(Post $post)
    {
        return response()->flutterSuccess($post);
    }

    public function destroy(Post $post)
    {
        $post->delete();
        return response()->flutterSuccess(null, 'Post deleted');
    }
}

๐Ÿ”Œ Connection Management (Bridge v2)

Bridge protocol 2.0.0 adds live connection sessions, registered client apps with a version policy, server โ†’ client commands, and real refresh-token rotation. The wire contract is documented in docs/CONNECTIONS.md.

Setup

php artisan flutter:install      # publishes config + migrations
php artisan migrate              # flutter_apps, flutter_connections, flutter_connection_commands, flutter_refresh_tokens
php artisan flutter:app:create "Acme Mobile" --platforms=android,ios --min-version=1.2.0 --update-url=https://example.com/app
php artisan flutter:export-config --base-url=https://api.example.com --app-key=fba_xxx

Push notifications (FCM HTTP v1)

FCM_CREDENTIALS=/path/to/service-account.json   # or the raw JSON / base64 JSON
FCM_PROJECT_ID=my-firebase-project               # optional, defaults to the credentials' project_id

Facade usage

use Atannex\LaravelFlutterBridge\Facades\FlutterBridge;

// Commands are delivered on the next heartbeat and pushed instantly as
// "BridgeCommand" on private-flutter.connections.{id} when broadcasting is enabled.
FlutterBridge::connections()->sendCommandToUser($user->id, 'message', ['title' => 'Hi', 'body' => 'Welcome back']);
FlutterBridge::connections()->sendCommand($connectionId, 'force_update', ['min_version' => '2.0.0']);

FlutterBridge::connections()->revoke($connectionId, 'lost_device');   // revokes its tokens too
FlutterBridge::connections()->revokeAllForUser($user->id, exceptId: $currentId);
FlutterBridge::connections()->isUserOnline($user->id);
FlutterBridge::connections()->stats();

$app = FlutterBridge::apps()->create('Acme Mobile', ['min_version' => '1.2.0']);
FlutterBridge::apps()->suspend($app);

$pair = FlutterBridge::tokens()->issue($user, 'Pixel 9', ['*'], null, $connectionId, $deviceId);

Events: FlutterConnectionEstablished, FlutterConnectionDisconnected, FlutterConnectionRevoked (broadcast as ConnectionRevoked) and FlutterCommandQueued (broadcast as BridgeCommand). Broadcasting only happens when flutter-bridge.broadcasting.enabled is true and the default driver is not null/log. The provider authorizes the flutter.connections.{connection} and users.{id} private channels.

Scheduling cleanup

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('flutter:connections:prune')->daily();

๐Ÿ” Use your own sign-in (Fortify)

By default auth/login checks email + password and auth/register creates a user from name / email / password. If your app has its own sign-in rules, plug them in so the mobile endpoints cannot bypass them. Every option is optional and takes an invokable class name (works with php artisan config:cache) or a callable.

// config/flutter-bridge.php
'auth' => [
    // ...

    // (Request $request): ?Authenticatable  โ€” null = wrong credentials (422)
    'authenticate_using'   => App\Actions\Fortify\AuthenticateUser::class,

    // (array $input, Request $request): Authenticatable  โ€” gets every request field
    'register_using'       => App\Actions\Fortify\CreateNewUser::class,

    // (Authenticatable $user): array  โ€” shapes `user` in auth responses and auth/me
    'user_presenter'       => App\Http\Presenters\UserPresenter::class,

    // 'auto' | true | false โ€” authenticator-app two-step sign-in
    'two_factor_challenge' => 'auto',
],

When Laravel Fortify is installed you usually need none of the above:

Step Order used
Sign-in (auth/login) authenticate_using โ†’ Fortify::authenticateUsing() callback โ†’ built-in email/password
Sign-up (auth/register) register_using โ†’ Fortify's bound CreatesNewUsers action (e.g. App\Actions\Fortify\CreateNewUser, with your password rules, roles and extra fields) โ†’ built-in
Two-step sign-in users with a Fortify two-factor secret (confirmed, when Fortify's confirm option is on) must send code or recovery_code
user in responses user_presenter โ†’ the model

A class registered as register_using may be invokable or expose Fortify's create(array $input). Sign-up fires Illuminate\Auth\Events\Registered, and validation errors from your action come back as the usual 422 validation_failed envelope.

Two-step flow for accounts with an authenticator app:

POST auth/login {email, password}                 โ†’ 422 meta.error_code "two_factor_required", data {"two_factor": true}
POST auth/login {email, password, code: "123456"} โ†’ 200 tokens   (or recovery_code: "xxxxxxxxxx-xxxxxxxxxx", usable once)
wrong code                                        โ†’ 422 "two_factor_invalid"

auth/social applies the same check after the provider token is verified. The email one-time-code endpoints (auth/2fa/send-otp, auth/2fa/verify) are a separate feature; set features.two_factor to false if your app should only allow authenticator-app sign-in.

๐Ÿ”‘ Laravel Fortify over the bridge (2.2)

With Laravel Fortify installed, the app gets every Fortify account feature with bearer tokens, through Fortify's own actions, password rules, events and config/fortify.php features. Nothing to register: the routes are under the bridge prefix, and a feature that is off in Fortify answers 404 feature_disabled. The full contract is docs/FORTIFY.md.

Flow Endpoints
Forgot / reset password with an emailed code auth/forgot-password โ†’ auth/reset-password/verify-code โ†’ auth/reset-password (also accepts the token of Fortify's emailed link); revokes all the user's bridge sessions
Email verification with a code auth/email/verification-notification, auth/email/verify (a code is also emailed after auth/register)
Profile and password PUT auth/user/profile-information, PUT auth/user/password (revoke_other_sessions)
Password confirmation (per token, auth.password_timeout) auth/user/confirm-password, auth/user/confirmed-password-status; sensitive endpoints answer 423 password_confirmation_required
Authenticator app enable, QR code (svg, otpauth:// url), secret key, confirm, recovery codes, regenerate, disable under auth/user/two-factor-*
Passkeys (laravel/passkeys) list, rename, delete under auth/user/passkeys

Codes are 6 digits, stored hashed in the cache, valid 10 minutes, locked after 5 wrong attempts and usable once (flutter-bridge.fortify.codes). The handshake publishes what works under features.fortify; auth/me and every auth response add email_verified, two_factor_enabled, two_factor_pending_confirmation and passkeys_count to the default user payload (a custom user_presenter can merge FortifyUserState::for($user), or set fortify.user_state to true). Set FLUTTER_FORTIFY=false to keep the 2.1 behaviour.

๐Ÿ› ๏ธ Artisan Commands

Generate Dart Model from Eloquent

php artisan flutter:generate-model User

Generates a null-safe Dart model with fromJson(), toJson(), and constructor.

Export Routes to Dart

php artisan flutter:export-routes --prefix=api

Generates a Dart route file with all endpoints typed as static constants.

๐Ÿงช Testing

composer test