Sanctum vs Passport: Most Teams Pick the Expensive One
Passport implements OAuth2, which is the right answer for third-party clients and an expensive mistake for your own frontend. The decision turns on one question about who the consumer is.
This is the most common avoidable decision in a Laravel API, and it goes the wrong way often enough to be worth a whole article.
The question is not which package is better. It is who is holding the token.
What OAuth2 is actually for
OAuth2 exists so that a third party can act on a user's behalf without the user handing over their password. That is the problem it solves: delegation across a trust boundary. The consent screen, the authorisation code, the client credentials, the scopes - all of it exists to make that specific exchange safe.
If the client is your own React application or your own mobile app, there is no trust boundary and no delegation. The user is authenticating with you, directly. OAuth2 solves nothing here and charges you for the machinery anyway.
What that costs when it is wrong
Passport brings an OAuth2 server into your application: client tables, authorisation codes, access and refresh tokens, key generation, token introspection, and an upgrade surface that has to be kept current.
Your team now maintains an OAuth2 server. They will debug refresh token rotation, explain client credentials to somebody, and handle key rotation in deployment. All of it to let your own mobile app log in.
It also gets built wrong in a recognisable way: password grant used because the redirect flow makes no sense for a first-party app, the client secret shipped inside that app where it is not a secret, and a token lifetime somebody set to a year so people stop complaining.
Sanctum, which is what most APIs want
Opaque tokens, stored hashed, with abilities and per-token revocation:
$token = $user->createToken('mobile', ['orders:read'])->plainTextToken;Nothing to stand up, nothing to rotate, and revocation is deleting a row. For a mobile app, a CLI, or a server-to-server key issued to a customer, this is the right shape.
The part people miss is that Sanctum has a second mode that is better still.
For a first-party SPA, use no token at all
If your single-page application is served from the same top-level domain as the API, Sanctum authenticates it with the ordinary session cookie:
GET /sanctum/csrf-cookie → sets the CSRF cookie
POST /login → normal session login
GET /api/orders → cookie-authenticated, CSRF protected
No token in localStorage, so nothing for a cross-site scripting bug to steal.
HttpOnly, SameSite, CSRF protection - the whole set of browser protections that
token-in-storage authentication gives up.
Teams skip this because "it is an API, so it needs tokens". It does not, and this is the most secure arrangement available to a first-party browser client.
When Passport is genuinely right
Other companies' applications integrate with you. They need to act for your users, you need consent screens and scoped access, and you need to revoke one integration without touching anything else.
You are the identity provider. Other systems authenticate against you.
A standards requirement. A partner or a procurement process specifies OAuth2 and that is not negotiable.
Notice what these have in common: somebody outside your organisation holds the credential. That is the whole test.
Migrating between them
From Passport to Sanctum, where Passport was chosen by mistake: issue Sanctum tokens on login, accept both during a transition window, then stop issuing Passport tokens and remove it. Bounded, and usually a week.
From Sanctum to Passport, when a real third-party integration appears: install Passport for the third-party flows and keep Sanctum for your own clients. They coexist, with different guards. This is another reason starting with Sanctum costs you nothing - you are not painted into a corner, you are simply not paying up front.
The rule, once more
Your client, your token: Sanctum. Somebody else's client acting for your user: Passport.
If you cannot name the third party, you do not need OAuth2 yet - and the versioning policy you write for that API will matter far more to its consumers than which package issued the token.
Bahrain is the one market where this choice is usually made for you. Open banking there is live, not planned, and the other side of the integration expects OAuth 2 with the scopes and consent flow that come with it.
