PHPackages                             branpolo/laravel-test-login - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. branpolo/laravel-test-login

ActiveLibrary[Testing &amp; Quality](/categories/testing)

branpolo/laravel-test-login
===========================

Test authentication bypass for Laravel browser and API testing (Mink, Dusk, Behat)

00[1 PRs](https://github.com/Branpolo/laravel-test-login/pulls)PHPCI passing

Since Feb 22Pushed 1w agoCompare

[ Source](https://github.com/Branpolo/laravel-test-login)[ Packagist](https://packagist.org/packages/branpolo/laravel-test-login)[ RSS](/packages/branpolo-laravel-test-login/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (3)Used By (0)

Laravel Test Login
==================

[](#laravel-test-login)

Test authentication bypass for Laravel browser and API testing (Mink, Dusk, Behat, PHPUnit).

[![Tests](https://github.com/branpolo/laravel-test-login/actions/workflows/tests.yml/badge.svg)](https://github.com/branpolo/laravel-test-login/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/d5b038b313ede25492be26ae958560a795de15e9f30699729b4402431139074e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6272616e706f6c6f2f6c61726176656c2d746573742d6c6f67696e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/branpolo/laravel-test-login)[![Total Downloads](https://camo.githubusercontent.com/08f037b4b00bcc1dcf4c9408ef54ae51832aa9ea52cdbdb2ea53a47d18964605/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6272616e706f6c6f2f6c61726176656c2d746573742d6c6f67696e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/branpolo/laravel-test-login)[![PHP Version](https://camo.githubusercontent.com/bd659a1a874a458096c13dc03865202a3cdc8dd14e0ae1803bd82a31ef441fec/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6272616e706f6c6f2f6c61726176656c2d746573742d6c6f67696e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/branpolo/laravel-test-login)[![License](https://camo.githubusercontent.com/a2cf8677aebc8f7c61f1c942ce5b21e4ed961351c73084f98b54254bc1092e42/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6272616e706f6c6f2f6c61726176656c2d746573742d6c6f67696e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/branpolo/laravel-test-login)

Why This Package?
-----------------

[](#why-this-package)

When testing Laravel applications with external browser drivers (Behat/Mink, Panther, Chrome DevTools Protocol), you can't use Laravel's built-in `loginAs()` method because the test process and web server run in separate processes.

This package provides secure HTTP routes that allow external test frameworks to authenticate users, similar to how Laravel Dusk's `loginAs()` works internally.

Features
--------

[](#features)

- **Session-based login** - For browser tests (Mink, Dusk, Panther)
- **API token login** - For API tests (requires Laravel Sanctum)
- **Multi-guard support** - Works with custom authentication guards
- **Spatie Permissions integration** - Auto-clears permission cache
- **Environment-restricted** - Routes only load in local/testing environments

Security Warning
----------------

[](#security-warning)

**These routes bypass normal authentication!** They are designed ONLY for testing environments and should NEVER be available in production.

The package includes multiple safety measures:

1. Routes only register in configured environments (default: `local`, `testing`)
2. Environment check happens at boot time, not at request time
3. Configuration allows customizing allowed environments

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

[](#installation)

```bash composer require --dev branpolo/laravel-test-login ```

The package auto-registers via Laravel's package discovery.

### Publish Configuration (Optional)

[](#publish-configuration-optional)

```bash php artisan vendor:publish --tag=test-login-config ```

Configuration
-------------

[](#configuration)

```php // config/test-login.php return \[ // Environments where routes are active (SECURITY CRITICAL) 'environments' =&gt; \['local', 'testing'\],

```
// Route prefix (default: /_test)
'prefix' => '_test',

// Middleware (default: web for session support)
'middleware' => ['web'],

// User model (null = auto-detect from auth config)
'user_model' => null,

// Enable API token routes (requires Sanctum)
'api_tokens' => true,

// Clear Spatie permission cache on login
'clear_permissions_cache' => true,

```

\]; ```

Usage
-----

[](#usage)

### Browser Tests (Behat/Mink)

[](#browser-tests-behatmink)

```php // In your Behat context public function iAmLoggedInAsAdmin(): void { $user = User::factory()-&gt;create(); $user-&gt;assignRole('admin');

```
// Visit the login URL
\$this->visit('/_test/login/' . \$user->id);

// Verify login worked
\$response = json_decode(\$this->getSession()->getPage()->getText(), true);
if (\$response['message'] !== 'Logged in successfully') {
    throw new \RuntimeException('Login failed');
}

```

} ```

### Gherkin Example

[](#gherkin-example)

```gherkin Feature: Admin Dashboard Scenario: Admin can access dashboard Given I am logged in as "admin" When I visit "/admin/dashboard" Then I should see "Welcome, Admin" ```

```php /\*\*

- @Given I am logged in as :role \*/ public function iAmLoggedInAs(string $role): void { $user = User::factory()-&gt;create(); $user-&gt;assignRole($role);

    $this-&gt;visit('/\_test/login/' . $user-&gt;id); } ```

### API Tests

[](#api-tests)

```php // Get an API token $response = Http::get(env('APP\_URL') . '/\_test/api-login/' . $user-&gt;id); $token = $response-&gt;json('token');

// Use token in subsequent requests $this-&gt;withHeader('Authorization', 'Bearer ' . $token) -&gt;getJson('/api/users') -&gt;assertOk(); ```

### PHPUnit Browser Tests

[](#phpunit-browser-tests)

```php public function test\_admin\_can\_access\_dashboard(): void { $user = User::factory()-&gt;admin()-&gt;create();

```
// Login via test route
\$this->get('/_test/login/' . \$user->id)
    ->assertOk()
    ->assertJson(['message' => 'Logged in successfully']);

// Now authenticated
\$this->get('/admin/dashboard')
    ->assertOk();

```

} ```

Available Routes
----------------

[](#available-routes)

RouteMethodDescription`/\_test/login/{userId}/{guard?}`GETSession-based login`/\_test/api-login/{userId}`GETGet Sanctum API token`/\_test/user/{guard?}`GETGet current authenticated user`/\_test/logout/{guard?}`GETLogout current user`/\_test/clear-permissions-cache`POSTClear Spatie permission cache### User Lookup

[](#user-lookup)

The `{userId}` parameter accepts:

- **Numeric ID**: `/\_test/login/1`
- **Email address**: `/\_test/login/`

Multiple Guards
---------------

[](#multiple-guards)

Specify a custom guard as the second parameter:

```php // Login to 'admin' guard $this-&gt;get('/\_test/login/' . $user-&gt;id . '/admin');

// Check user on 'api' guard $this-&gt;get('/\_test/user/api'); ```

Laravel Sail with Local Chrome (Behat/Mink)
-------------------------------------------

[](#laravel-sail-with-local-chrome-behatmink)

When using Laravel Sail for your web server but running Chrome locally on the host (not inside the Docker container), you need a specific architecture:

### Architecture Overview

[](#architecture-overview)

``` ┌─────────────────────────────────────────────────────────────────┐ │ HOST MACHINE │ │ │ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │ │ Chrome (CDP) │ │ Behat Test Runner │ │ │ │ Port 9222 │◄───────►│ (with environment vars) │ │ │ └─────────────────┘ └──────────────┬──────────────┘ │ │ │ │ │ ┌───────────────────────────────────┘ │ │ │ DB: 127.0.0.1:5432 │ │ │ APP: localhost:8080 │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Docker (Sail) │ │ │ │ ┌─────────────────┐ ┌─────────────────────────┐ │ │ │ │ │ Laravel App │ │ PostgreSQL │ │ │ │ │ │ Port 8080 │ │ Port 5432 │ │ │ │ │ └─────────────────┘ └─────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ```

### Why This Setup?

[](#why-this-setup)

1. **Chrome is NOT installed** in the standard Laravel Sail container
2. **Behat needs direct database access** to create test users before browser navigation
3. **Session cookies** must be shared between the test login route and subsequent page visits

### Step 1: Start Sail

[](#step-1-start-sail)

```bash ./vendor/bin/sail up -d ```

### Step 2: Start Chrome on Host

[](#step-2-start-chrome-on-host)

```bash

Linux
=====

[](#linux)

chromium-browser --headless --disable-gpu --no-sandbox \\ --remote-debugging-port=9222 --disable-dev-shm-usage &amp;

macOS
=====

[](#macos)

/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome \\ --headless --disable-gpu --remote-debugging-port=9222 &amp;

Verify Chrome is running
========================

[](#verify-chrome-is-running)

curl -s  | head -2 ```

### Step 3: Run Behat on Host (NOT via Sail)

[](#step-3-run-behat-on-host-not-via-sail)

```bash

Set environment variables to connect to Sail's services
=======================================================

[](#set-environment-variables-to-connect-to-sails-services)

APP\_ENV=testing \\ APP\_URL= \\ DB\_CONNECTION=pgsql \\ DB\_HOST=127.0.0.1 \\ DB\_PORT=5432 \\ DB\_DATABASE=laravel \\ DB\_USERNAME=sail \\ DB\_PASSWORD=password \\ CACHE\_STORE=array \\ SESSION\_DRIVER=array \\ ./vendor/bin/behat --suite=mink-chrome ```

### Helper Script

[](#helper-script)

Create a helper script (`scripts/run-mink-tests.sh`):

```bash #!/bin/bash set -e

Check Sail is running
=====================

[](#check-sail-is-running)

if ! ./vendor/bin/sail ps 2&gt;/dev/null | grep -q "laravel.test"; then echo "Starting Sail..." ./vendor/bin/sail up -d sleep 5 fi

Start Chrome if not running
===========================

[](#start-chrome-if-not-running)

if ! curl -s  &gt; /dev/null 2&gt;&amp;1; then echo "Starting Chrome..." chromium-browser --headless --disable-gpu --no-sandbox \\ --remote-debugging-port=9222 --disable-dev-shm-usage &amp; sleep 3 fi

Run Behat with environment variables
====================================

[](#run-behat-with-environment-variables)

APP\_ENV=testing \\ APP\_URL= \\ DB\_CONNECTION=pgsql \\ DB\_HOST=127.0.0.1 \\ DB\_PORT=5432 \\ DB\_DATABASE=laravel \\ DB\_USERNAME=sail \\ DB\_PASSWORD=password \\ CACHE\_STORE=array \\ SESSION\_DRIVER=array \\ ./vendor/bin/behat --suite=mink-chrome "$@" ```

### Behat Context Example

[](#behat-context-example)

```php

session = new Session(\\$driver); \\$this-&gt;session-&gt;start(); } /\*\* \* @Given I am logged in as :role \*/ public function iAmLoggedInAs(string \\$role): void { // Create user in database (Behat has direct DB access) \\$this-&gt;currentUser = User::factory()-&gt;create(); \\$this-&gt;currentUser-&gt;assignRole(\\$role); // Login via test route (browser visits the Sail container) \\$baseUrl = getenv('APP\_URL') ?: 'http://localhost:8080'; \\$this-&gt;session-&gt;visit(\\$baseUrl . '/\_test/login/' . \\$this-&gt;currentUser-&gt;id); } /\*\* \* @When I visit :path \*/ public function iVisit(string \\$path): void { \\$baseUrl = getenv('APP\_URL') ?: 'http://localhost:8080'; \\$this-&gt;session-&gt;visit(\\$baseUrl . \\$path); } } \\`\\`\\` ### behat.yml Configuration \\`\\`\\`yaml default: suites: mink-chrome: paths: - '%paths.base%/features/mink' contexts: - Tests\\\\Behat\\\\Contexts\\\\ChromeBrowserContext \\`\\`\\` ### Common Issues | Issue | Cause | Solution | |-------|-------|----------| | "Chrome not found" | Chrome isn't installed in Sail | Run Chrome on the \*\*host\*\*, not in Docker | | "relation does not exist" | Database not migrated | Run \\`./vendor/bin/sail artisan migrate\\` | | 401 on API calls | Sanctum not configured for SPA | Enable \\`EnsureFrontendRequestsAreStateful\\` middleware | | Session not persisting | Wrong middleware | Ensure \\`/\_test/login\\` route uses \\`web\\` middleware | | Empty page content | Session mismatch | Don't run Behat via Sail - run on host with env vars | ### Key Points 1. \*\*Behat runs on HOST\*\* - Not via \\`./vendor/bin/sail exec\\` 2. \*\*Chrome runs on HOST\*\* - With \\`--remote-debugging-port=9222\\` 3. \*\*Sail provides web server\*\* - Laravel app accessible at \\`localhost:8080\\` 4. \*\*Database shared\*\* - Both Behat and Laravel use same PostgreSQL via different ports 5. \*\*Session cookies work\*\* - Because browser visits the same domain for login and navigation ## Spatie Permissions If you have \\`spatie/laravel-permission\\` installed, the package automatically clears the permission cache when logging in. This prevents stale permissions during tests. Disable this behavior in config: \\`\\`\\`php 'clear\_permissions\_cache' =&gt; false, \\`\\`\\` ## Testing \\`\\`\\`bash composer test \\`\\`\\` ## Changelog Please see \[CHANGELOG\](CHANGELOG.md) for more information on what has changed recently. ## Contributing Please see \[CONTRIBUTING\](CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email natan@diagnostics.ai instead of using the issue tracker. ## Credits - \[Branpolo\]() - Inspired by Laravel Dusk's \\`loginAs()\\` implementation ## License The MIT License (MIT). Please see \[License File\](LICENSE.md) for more information.

###  Health Score

21

—

LowBetter than 20% of packages

Maintenance64

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity14

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/b33ea035209154328f943126bb93017cf47ea3385b81fcf0fb9b965ba8eaad79?d=identicon)[Branpolo](/maintainers/Branpolo)

---

Top Contributors

[![Branpolo](https://avatars.githubusercontent.com/u/57213950?v=4)](https://github.com/Branpolo "Branpolo (1 commits)")

---

Tags

authenticationbehatbrowser-testingdusklaravelminkphptesting

### Embed Badge

![Health badge](/badges/branpolo-laravel-test-login/health.svg)

```
[![Health](https://phpackages.com/badges/branpolo-laravel-test-login/health.svg)](https://phpackages.com/packages/branpolo-laravel-test-login)
```

###  Alternatives

[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k488.3M21.5k](/packages/mockery-mockery)[phpspec/prophecy

Highly opinionated mocking framework for PHP 5.3+

8.5k548.7M629](/packages/phpspec-prophecy)[sebastian/global-state

Snapshotting of global state

6.6k848.0M40](/packages/sebastian-global-state)[hamcrest/hamcrest-php

This is the PHP port of Hamcrest Matchers

7.1k475.4M100](/packages/hamcrest-hamcrest-php)[vimeo/psalm

A static analysis tool for finding errors in PHP applications

5.8k76.1M6.1k](/packages/vimeo-psalm)[brianium/paratest

Parallel testing for PHP

2.5k113.9M660](/packages/brianium-paratest)

PHPackages © 2026

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