Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/references/authentication/auth_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,55 @@ the condition cannot be determined. It is not a replacement for authorization.

Once an action is already pending in the session, Shield continues that pending
action instead of rechecking the condition.

## Gateway Actions

Shield allows one configured action for each authentication event, such as
`login` or `register`. If your application needs to choose between multiple
ways to complete that action, register one custom action as a gateway.
Use this when users may have different verification methods enabled, but Shield
should still treat them as one login action.

A gateway action is a normal custom action. It can also be conditional, so it
only runs for users who have at least one supported method available. For
example, a login action can check whether the user has any two-factor methods
enabled:

```php
public function appliesTo(User $user): bool
{
return $user->getIdentity('mfa_email') !== null
|| $user->getIdentity('mfa_sms') !== null;
}
```

Then register the gateway action as the login action:

```php
public array $actions = [
'register' => null,
'login' => \App\Authentication\Actions\TwoFactorGateway::class,
];
```

The gateway action owns the choice between methods:

1. `show()` displays the available methods for the pending user.
2. `handle()` validates the selected method, sends the challenge, and remembers
the selected method.
3. `verify()` verifies the challenge and completes the action.

Use one action identity type for the gateway, returned by `getType()`. For
example, the gateway might return `mfa_gateway`. Do not create separate action
identities for each method, such as `email_2fa` and `sms_2fa`, because Shield
discovers the pending action through the configured action's type.

Keep the action identity's `extra` value as the pending action message. If the
gateway needs to remember internal state, such as the selected method, store it
somewhere else, like `secret2` or an application-owned table. If the stored
value is sensitive, prefer application-owned protected storage.

This pattern is useful for application-owned flows, especially when the choices
are code-delivery methods such as email or SMS. It does not make Shield provide
built-in MFA. Your application is still responsible for enrollment, delivery,
recovery, and method-specific security rules.