Skip to content

feat: add conditional auth actions#1328

Open
memleakd wants to merge 1 commit into
codeigniter4:developfrom
memleakd:feat/conditional-auth-actions
Open

feat: add conditional auth actions#1328
memleakd wants to merge 1 commit into
codeigniter4:developfrom
memleakd:feat/conditional-auth-actions

Conversation

@memleakd
Copy link
Copy Markdown

Description

This PR adds a small opt-in way for auth actions to decide whether they apply to a specific user.

The idea came from the earlier MFA/2FA discussions and stalled work around Shield.

This is the first small piece: actions can implement ConditionalActionInterface and return true or false from appliesTo(User $user). That makes cases like "require an action only for admins" possible without changing existing actions or forcing every app into the same policy.

final class AdminEmail2FA extends Email2FA implements ConditionalActionInterface
{
    public function appliesTo(User $user): bool
    {
        return $user->inGroup('admin', 'superadmin');
    }
}

Existing actions keep working as before. If an action does not implement the new interface, Shield treats it as always applicable.

A couple of edge cases are handled intentionally:

  • If a conditional action does not apply, Shield skips starting it and ignores stored identities for that action.
  • If a user is already inactive and has a stored activation identity, Shield still requires activation. This avoids turning conditional activation into a way around activation.
  • If an action is already pending in the session, Shield continues that pending action instead of rechecking the condition mid-flow.

This should give Shield a safer foundation for future MFA work, while keeping this PR focused on the existing auth action system.

Tests cover login actions, registration activation, stored action identities, magic-link activation, and session filter behavior.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

- add ConditionalActionInterface for opt-in per-user action checks
- skip conditional login/register actions when they do not apply
- keep stored activation identities enforced for inactive users
- document conditional action behavior and activation edge cases
- add login, registration, magic-link, and filter coverage

Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@datamweb datamweb added the new feature PRs for new features label May 29, 2026
@datamweb
Copy link
Copy Markdown
Collaborator

Hi @memleakd! This feature looks absolutely fantastic, and I really want to thank you for the clean and solid implementation. The simple and straightforward example you provided in the description is great and makes the concept very easy to understand.

However, what is hidden inside this PR is another fascinating and powerful capability that could be even more practical. As we know, Shield currently has an architectural limitation where only one class (a linear action) can be defined for each event in the config ($actions array). It seems your PR is exactly the key to bypassing this limitation!

With this new ConditionalActionInterface, it becomes entirely possible to build a class like a TwoFactorGatewayAction. Consider a scenario where a user(end user) has configured both SMS 2FA and Email 2FA methods:

We could register this Gateway as the single action for the login event. Using the appliesTo() method, we check if the user has any active methods. If they do, this Gateway can act as a Router. Instead of forcing a static method, it can render a View during login, giving the user the choice of how to receive their code (SMS or Email). This practically resolves Shield’s single-action limitation.

I haven’t had the time to fully implement and test this specific Gateway scenario myself, but architecturally, it makes perfect sense.

I wanted to ask you to look into this aspect of your feature as well. If you can verify that it works for such combined scenarios to bypass Shield’s limitations, I highly recommend documenting this advanced pattern thoroughly in a new section of the docs (perhaps under the Guides or Customization sections). This would be a massive added value for developers who need to handle more complex scenarios.

Thanks again for this clean architecture and valuable PR. Excellent work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature PRs for new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants