bherila/auth-laravel
A Laravel authentication package that helps add secure user login, registration, and password reset flows to your application with minimal setup, offering customizable auth scaffolding and guard integration for faster development.
This release makes credential revocation durable and transactional, but it is strictly opt-in. Nothing changes until you flip the switch.
Minimal adoption path:
config/oauth_server.php:
'revocation' => [
'enabled' => true,
],
CredentialLineages::revokingOwner() or CredentialLineages::revokingConnection().duringIssue() so the persistence path consults the revocation sequence in the same transaction.Where to look first:
docs/oauth-credential-revocation.md — the canonical adoption guide.CredentialLineages — the revocation barrier API.OAuthCredentialOwners — existing revocation methods that now adopt the owner barrier automatically.oauth_server.revocation.enabled config key — this is the master switch.First real-world use case: a user clicks "Log out of all devices". Instead of iterating tokens and hoping nothing refreshes in between, you call revokingOwner() around your connection/row revocation. The revocation sequence advances atomically with the write, so any in-flight refresh or authorization code cannot sneak through afterwards.
Transaction-scoped revocation (primary pattern). The guards are designed to live inside your own DB transaction. The line below is illustrative of the shape, not a literal signature:
use Illuminate\Support\Facades\DB;
use Your\Package\CredentialLineages;
DB::transaction(function () use ($user) {
CredentialLineages::revokingOwner($user, function () use ($user) {
// Your application-side revocation / audit selection
$user->oauthConnections()->update(['revoked_at' => now()]);
});
});
Because the revocation sequence increments in the same transaction as the write, a refresh token validated before the commit cannot be persisted after it. No cache TTL and no token decryption required.
Per-connection revocation. Use revokingConnection() for device/session-level logout. It follows every tracked rotation of that connection while preserving same-client sibling connections—so logging out one phone does not log out a second phone that happens to share a client.
Custom issuance decisions. Any place you branch on business rules during token issuance (plan checks, tenant state, risk gates) should be wrapped in duringIssue(). Without this wrapper, custom issuance paths bypass the repository guards and can write unregistered grants, which the new model treats as fail-closed.
Existing owner revocation. If you already revoke via OAuthCredentialOwners, you get the owner barrier automatically. Audit your codebase for places that revoke credentials by deleting rows directly—those are the call sites that need to be moved behind the guards.
Fresh authorization remains possible. Broad owner-wide revocation intentionally does not lock the user out permanently; a new authorization code flow can mint a fresh lineage after the revocation. Preserve that behavior—do not add application-level checks that permanently block re-authorization.
Rollout pattern. Coordinate rollout with issuance paused. Run the migration, enable the config flag, deploy the new code, then resume issuance. This prevents an old process from writing credentials that the new repository guards would otherwise reject as unregistered.
oauth_server.revocation.enabled is not optional if you want the durability guarantees. Forgetting to clear a cached config is a common silent failure—verify with php artisan config:show oauth_server.revocation inside the running environment.OAuthCredentialOwners methods are the safe path. Prefer them over hand-rolled deletes. They adopt the owner barrier automatically, which keeps your revocation call sites consistent with the new model.duringIssue() for custom issuance decisions, OAuthCredentialOwners for owner-scoped revocation, and CredentialLineages for connection-scoped revocation and audit selection.revokingOwner()/revokingConnection(); confirm custom issuance is inside duringIssue(); inspect the lineage tables to see whether the failing grant was ever registered.How can I help you explore Laravel packages today?