PHPackages                             rainwaves/lara-auth-suite - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. rainwaves/lara-auth-suite

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

rainwaves/lara-auth-suite
=========================

Laravel API auth suite: Sanctum tokens &amp; session modes, password reset, and 2FA.

v2.0.0(2mo ago)0290↑86.7%MITPHPPHP ^8.2|^8.3|^8.4

Since Nov 10Pushed 2mo agoCompare

[ Source](https://github.com/Magnificent-Big-J/lara-auth-suite)[ Packagist](https://packagist.org/packages/rainwaves/lara-auth-suite)[ RSS](/packages/rainwaves-lara-auth-suite/feed)WikiDiscussions main Synced today

READMEChangelog (5)Dependencies (15)Versions (11)Used By (0)

Rainwaves Lara Auth Suite
=========================

[](#rainwaves-lara-auth-suite)

Modern, flexible authentication for Laravel APIs &amp; SPAs.

Plug-and-play authentication for Laravel 10/11/12/13, supporting both API token auth (Sanctum) and session-based auth for SPAs — with password resets, backend-enforced Two-Factor Authentication (Email OTP + TOTP), recovery codes, and full role/permission support.

---

Overview
--------

[](#overview)

Rainwaves/Lara Auth Suite gives you full authentication without writing boilerplate:

- Token authentication for mobile apps or external APIs
- Session authentication for SPAs (Vue / React / Inertia / Livewire)
- Unified password reset flow
- Two-Factor Authentication (Email OTP, Authenticator App)
- TOTP replay-attack protection
- Recovery codes for locked-out users
- Automatic role &amp; permission assignment (Spatie Permissions)
- Feature-flag gating — enable only what you need

### Ideal for:

[](#ideal-for)

- SaaS platforms
- Admin dashboards
- Multi-tenant SPAs
- Hybrid apps needing both tokens + sessions

---

Demo Applications
-----------------

[](#demo-applications)

### Backend (Laravel)

[](#backend-laravel)

Reference backend implementation using the package:

### Frontend (Nuxt SPA)

[](#frontend-nuxt-spa)

Full SPA login + 2FA flow:

---

Features
--------

[](#features)

FeatureStatusDescriptionSanctum PAT loginDoneToken-based API authenticationSession authenticationDoneLaravel guard + CSRF protectionPassword reset (email)DoneFull reset flow with throttle2FA: Email OTPDoneSecure email verification codes2FA: TOTP (Authenticator App)DoneGoogle Authenticator / Authy / 1Password2FA enforcementDoneEnforced on protected routes (backend-driven)TOTP replay protectionDone`last_used_counter` prevents counter reuseRecovery codesDone8-code offline fallback for locked-out TOTP usersSecurity throttlesDoneLogin/reset/2FA rate limitingPending auth managerDoneSession-less state bridge during 2FA challengeFeature flag gatingDoneDisable unused auth features at the route levelTrusted devicesPlannedDevice rememberingToken/session/device mgmtPlannedRevoke, audit---

Requirements
------------

[](#requirements)

LaravelPHPSanctum10 / 11 / 12 / 138.2 / 8.3 / 8.44.x / 5.x---

Breaking Changes in v2.0.0
--------------------------

[](#breaking-changes-in-v200)

Read this section carefully before upgrading from v1.x.

**Registration is disabled by default.**`registration.enabled` now defaults to `false`. If you have not published `authx.php`, registration will be silently disabled after upgrading. Publish (or re-publish) the config and set `enabled: true` explicitly.

**`issue_token_on_register` defaults to `false`.**Token issuance on registration is now opt-in. Existing apps that relied on the `true` default must set this explicitly in their published config.

**`sendEmailOtp()` no longer returns the OTP.**The return type changed from `string` to `void`. The plaintext code must never escape the service layer. Any code that called `sendEmailOtp()` and used the return value must be updated.

**`ITokenAuthService` interface type hint corrected.**The interface previously imported `Illuminate\Auth\Authenticatable` (a trait). It now imports `Illuminate\Contracts\Auth\Authenticatable` (an interface). Custom implementations that bound to the old type hint must update their use statement.

**Session is not started until 2FA passes.**When 2FA is required, the session is now invalidated and the CSRF token regenerated before the challenge is issued. The session is only created after successful verification. Frontends that assumed a valid session existed during the challenge step must be updated.

**`SessionLoginResult::$channel` is now a `TwoFactorChannel` enum.**The field was previously a plain `string`. Code that compares the value using string literals must use the enum instead, e.g. `TwoFactorChannel::Email`.

**New migration required.**Run `php artisan migrate` after upgrading. The new migration adds `last_used_counter` to the `two_factor_secrets` table for TOTP replay protection.

---

Installation
------------

[](#installation)

```
composer require rainwaves/lara-auth-suite
```

Publish configuration:

```
php artisan vendor:publish \
  --provider="Rainwaves\\LaraAuthSuite\\LaraAuthSuiteServiceProvider" \
  --tag=authx-config
```

Run migrations:

```
php artisan migrate
```

---

Authentication Flow
-------------------

[](#authentication-flow)

Authentication decisions are enforced **on the backend**. Frontend clients **do not decide** authentication state.

- Credentials are validated
- If 2FA is required: the session is **invalidated**, a pending auth state is created, and an OTP/TOTP challenge is issued — the user is not logged in yet
- After successful 2FA: the session is created, CSRF token is issued, and the user is fully authenticated
- If 2FA is not required: the session is created and the user is fully authenticated immediately

This prevents:

- Logged-in-but-unverified states
- Session persistence before verification
- Frontend-controlled security decisions
- Password reset user enumeration
- TOTP replay attacks

---

Usage
-----

[](#usage)

### 1. Login (Session Mode – SPA)

[](#1-login-session-mode--spa)

**POST /auth/session/login**

```
{
  "email": "admin@example.com",
  "password": "secret",
  "remember": true
}
```

Response (2FA required — session not yet active):

```
{
  "user": {},
  "requires_two_factor": true,
  "channel": "email"
}
```

Response (2FA not required):

```
{
  "user": {},
  "requires_two_factor": false
}
```

---

### 2. Login (Token Mode / API Clients)

[](#2-login-token-mode--api-clients)

**POST /auth/login**

```
{
  "email": "admin@example.com",
  "password": "secret"
}
```

Response (no 2FA):

```
{
  "token": "plain-text-token",
  "token_type": "Bearer",
  "abilities": ["*"]
}
```

Response (2FA required — token is `null` until verified):

```
{
  "token": null,
  "requires_two_factor": true,
  "channel": "totp",
  "pending_auth_id": "uuid"
}
```

---

### 3. Get Current User

[](#3-get-current-user)

**GET /auth/me** — requires session cookie or `Authorization: Bearer `

---

### 4. Logout

[](#4-logout)

Session: `POST /auth/session/logout`

Token: `POST /auth/logout`

---

### 5. Forgot Password

[](#5-forgot-password)

**POST /auth/password/forgot**

```
{ "email": "admin@example.com" }
```

---

### 6. Reset Password

[](#6-reset-password)

**POST /auth/password/reset**

```
{
  "email": "admin@example.com",
  "token": "reset-token",
  "password": "newpassword",
  "password_confirmation": "newpassword"
}
```

> Passwords are capped at 128 characters to prevent bcrypt/argon2 resource exhaustion.

---

Two-Factor Authentication
-------------------------

[](#two-factor-authentication)

Two-Factor Authentication is:

- Evaluated during login (backend only)
- Enforced before session/token is issued
- Protected against replay attacks (TOTP counter tracking)

### Email OTP endpoints

[](#email-otp-endpoints)

```
POST /auth/session/2fa/email
POST /auth/session/2fa/verify-otp
POST /auth/session/2fa/disable

POST /auth/2fa/email
POST /auth/2fa/verify-otp
POST /auth/2fa/disable

```

### Authenticator App (TOTP)

[](#authenticator-app-totp)

```
POST /auth/session/2fa/totp/enable
POST /auth/session/2fa/totp/verify

POST /auth/2fa/totp/enable
POST /auth/2fa/totp/verify

```

### Recovery Codes

[](#recovery-codes)

Used when a TOTP user has lost access to their authenticator app:

```
POST /auth/session/2fa/recovery
POST /auth/2fa/recovery

```

> SMS-based OTP is intentionally excluded due to SIM-swap risk. 2FA management endpoints require the current password by default.

---

Configuration (`config/authx.php`)
----------------------------------

[](#configuration-configauthxphp)

```
use Rainwaves\LaraAuthSuite\Support\Enums\AuthMode;
use Rainwaves\LaraAuthSuite\Support\Enums\AuthFeature;
use Rainwaves\LaraAuthSuite\Support\Enums\TwoFactorChannel;

return [
    'route_prefix' => 'auth',
    'mode'         => AuthMode::Session->value, // session | token | both
    'user_model'   => null,
    'user_resource' => null,
    'debug_ping'   => false, // enable GET /auth/ping (disable in production)

    'frontend' => [
        'password_reset_url' => env('AUTHX_FRONTEND_RESET_URL', '/auth/reset-password'),
    ],

    'features' => [
        AuthFeature::PasswordReset->value,
        AuthFeature::TwoFactor->value,
        AuthFeature::Tokens->value,
        AuthFeature::Devices->value,
    ],

    '2fa' => [
        'channels'    => [TwoFactorChannel::Email->value, TwoFactorChannel::Totp->value],
        'enforcement' => 'optional', // off | optional | required
        'remember_device_days' => 30,
        'otp' => [
            'length'              => 6,
            'expiry_seconds'      => 180,
            'throttle_per_minute' => 5,
        ],
        'totp_digits'             => 6,
        'totp_period'             => 30,   // RFC 6238 default (seconds)
        'totp_window'             => 1,    // steps either side accepted (covers ±30s clock drift)
        'verification_ttl_seconds' => 600, // how long verified 2FA state is trusted for token users
        'recovery_codes_count'    => 8,
        'require_password_on_manage' => true,
    ],

    'tokens' => [
        'abilities' => ['*'],
    ],

    'throttle' => [
        'login'        => 5,
        'two_factor'   => 5,
        'reset'        => 5,
        'decay_seconds' => 60,
    ],

    'registration' => [
        'enabled'               => false,  // opt-in — disabled by default
        'issue_token_on_register' => false, // opt-in
        'default_roles'         => [],
        'default_permissions'   => [],
        'allow_self_assign_roles' => false,
        'allow_self_assign_permissions' => false,
        'rules' => [
            'name'       => ['required', 'string', 'max:255'],
            'email'      => ['required', 'string', 'email', 'max:255', 'unique:users,email'],
            'password'   => ['required', 'string', 'min:8', 'max:128', 'confirmed'],
            'roles'      => ['sometimes', 'array'],
            'roles.*'    => ['string'],
            'permissions' => ['sometimes', 'array'],
            'permissions.*' => ['string'],
        ],
    ],

    'permissions' => [
        'enabled' => true,
        'fail_open_when_tables_missing' => false,
    ],
];
```

---

Frontend Integration (SPA)
--------------------------

[](#frontend-integration-spa)

Frontend clients consume backend decisions. They do **not** determine authentication state.

The backend returns:

- Whether 2FA is required
- Which channel must be used
- A `pending_auth_id` (token mode) to complete the flow
- Whether the session/token is fully verified

Reference implementation:

---

Roadmap
-------

[](#roadmap)

VersionFeaturev1.0Token + session auth, password resetv1.1Email OTP, TOTP, 2FA enforcementv2.0Security hardening, TOTP replay protection, recovery codes, Laravel 13v2.xTrusted devices, session/token audit---

Security
--------

[](#security)

Report security issues privately to:

Do **not** open a public GitHub issue for security vulnerabilities.

---

License
-------

[](#license)

MIT © Rainwaves

---

Credits
-------

[](#credits)

Built by **Rainwaves**Security-first authentication for serious Laravel applications.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance86

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 73.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~37 days

Total

5

Last Release

70d ago

Major Versions

v1.1.2 → v2.0.02026-04-24

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/30896750?v=4)[Joel Mnisi](/maintainers/Magnificent-Big-J)[@Magnificent-Big-J](https://github.com/Magnificent-Big-J)

---

Top Contributors

[![mnisij](https://avatars.githubusercontent.com/u/14214514?v=4)](https://github.com/mnisij "mnisij (31 commits)")[![Magnificent-Big-J](https://avatars.githubusercontent.com/u/30896750?v=4)](https://github.com/Magnificent-Big-J "Magnificent-Big-J (11 commits)")

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/rainwaves-lara-auth-suite/health.svg)

```
[![Health](https://phpackages.com/badges/rainwaves-lara-auth-suite/health.svg)](https://phpackages.com/packages/rainwaves-lara-auth-suite)
```

###  Alternatives

[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

135224.7k7](/packages/statamic-rad-pack-runway)[jeremy379/laravel-openid-connect

OpenID Connect support to the PHP League's OAuth2 Server. Compatible with Laravel Passport.

59437.0k9](/packages/jeremy379-laravel-openid-connect)[ecotone/laravel

Ecotone for Laravel — CQRS, Event Sourcing, Sagas, Durable Workflows, and Outbox on top of Laravel Queue, via PHP attributes.

21318.6k3](/packages/ecotone-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
