Skip to main content
Laravel Authentication supports two adoption modes that describe how your domain maps onto the Identity–Principal–Device model. Choosing the right mode is less about the package and more about whether your app needs to distinguish “who logged in” from “who this request is acting as.” Both modes use the same guards, the same facade, and the same middleware — the difference is entirely in how you implement your Eloquent models.

2D mode: identity is the principal

In 2D mode, one model implements both Identity and Principal. The logged-in user is the actor on whose behalf every request runs. There is no separate membership, role model, or tenant record — the user themselves is the scope of each action. Auth::identity() and Auth::principal() return the same object in this mode. Auth::tenant() returns null because the principal’s getTenant() returns null. Auth::type() likewise returns null. When to use 2D mode:
  • Simple single-tenant applications where every user has the same scope
  • Machine-to-machine APIs where the authenticating service account is also the actor
  • Internal tools without multi-tenant isolation requirements
  • Early-stage products where you want to get auth working now and grow the model later

3D mode: identity, principal, and tenant are separate

In 3D mode, three separate models carry the three concerns:
  • An Identity model represents the human (or service account) — it implements Identity and HasPrincipals
  • A Principal model represents the tenant-scoped actor — typically a membership or role row — and implements Principal
  • A Tenant model represents the isolation boundary and implements Tenant
Auth::identity() returns the human. Auth::principal() returns the membership they are currently acting as (pinned by the pid claim in the access token). Auth::tenant() returns the tenant that membership belongs to. When to use 3D mode:
  • Multi-tenant SaaS where users belong to one or more workspaces, organizations, or teams
  • Apps where a single login should be able to switch between different tenant contexts
  • Platforms with per-tenant roles or permissions that differ from the user’s global account
  • Any domain where “acting on behalf of” is a first-class concept

Side-by-side comparison

One model handles everything. Point auth.providers.users.model at it and you’re done.
use Illuminate\Foundation\Auth\User;
use SineMacula\Laravel\Authentication\Contracts\Identity;
use SineMacula\Laravel\Authentication\Contracts\Principal;
use SineMacula\Laravel\Authentication\Traits\ActsAsPrincipal;
use SineMacula\Laravel\Authentication\Traits\Authenticatable;

class AppUser extends User implements Identity, Principal
{
    use Authenticatable, ActsAsPrincipal;
}
At runtime:
Auth::identity();   // AppUser instance
Auth::principal();  // same AppUser instance
Auth::tenant();     // null
Auth::type();       // null

Starting with 2D and growing into 3D

The two modes are additive — you do not need to re-platform to move from 2D to 3D. The guards change nothing; only your model implementations change. Here is a safe migration path:
1

Start with 2D

Implement Identity and Principal on your existing user model. Issue tokens, wire middleware, ship.
2

Add a membership model

When you need per-tenant roles, create an AppMembership model that implements Principal. Keep your user model implementing Identity but add HasPrincipals to it. The guards pick up the new contract automatically.
3

Add a tenant model

Create an AppTenant model that implements Tenant. Wire AppMembership::tenant() to return it. Auth::tenant() now works without any change to your guards or middleware.
4

Optionally add HasType

If you need to branch on tenant category (e.g. 'staff' vs 'customer'), add HasType to AppTenant and implement getType(). Auth::type() starts returning the value immediately.
Existing access tokens issued in 2D mode continue to work during and after migration. The pid claim in a 2D token contains the identity’s own identifier. When you switch to 3D, new tokens carry a membership identifier as pid. Old tokens will fail to resolve a Principal if the old pid no longer matches a membership row — issue a fresh token to users after migration.

2D setup guide

Step-by-step walkthrough for wiring up a single-model identity that acts as its own principal.

3D setup guide

Step-by-step walkthrough for separating identity, membership, and tenant into three models.