scheb / 2fa

Two-factor authentication for Symfony applications 🔐
MIT License
495 stars 72 forks source link

Possibly unclear sentence about "your API has to be stateful" in the API integration docs #175

Closed danielrhodeswarp closed 1 year ago

danielrhodeswarp commented 1 year ago

Description

OK, this is obviously not a bug, but there's something that troubles the pedantic side of me in the doc page for API integration:

https://symfony.com/bundles/SchebTwoFactorBundle/5.x/api.html

It says "your API has to be stateful (stateless: false) in the firewall configuration".

This is correct, but - for me with my configuration - slightly unclear. I have both a 'login' firewall and the actual 'api' firewall. And my first factor way to sign in is using JWTs with Lexik bundle.

I only have to use stateless: false on my login firewall (see below) for Scheb 2FA to work.

When I first read "your API has to be stateful (stateless: false) in the firewall configuration" I imagined I had to put stateless: false on both firewalls.

Maybe I am being dopey! But I just wanted to point out something that confused me.

(I can indeed set stateless: false on the api firewall too, and it still works but it sends an unwanted cookie that I'd rather not send.)

Additional Context

SECURITY.YAML

    login:
            pattern:  ^/authenticate
            #MUST have stateless: false here
            stateless: false
            anonymous: lazy
            #means Lexik JWT
            json_login:
                username_path: email
                check_path: api_login_check
                success_handler: App\Security\JWTAuthenticationSuccessHandler
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
            #Scheb 2FA
            two_factor:
                prepare_on_login: true
                prepare_on_access_denied: true
                auth_form_path: 2fa_login
                check_path: 2fa_login_check
                post_only: true 
                authentication_required_handler: App\Security\TwoFactorAuthenticationRequiredHandler
                success_handler: App\Security\TwoFactorAuthenticationSuccessHandler
                failure_handler: App\Security\TwoFactorAuthenticationFailureHandler
                auth_code_parameter_name: oneTimeCode

        api:
            pattern: ^/
            #DO NOT NEED stateless: false here (false works here but sends out an unwanted cookie with every api call response)
            stateless: true
            provider: app_user_provider
            guard:
                authenticators:
                    - app.jwt_token_authenticator
scheb commented 1 year ago

It actually should say "your firewall has to be stateful". Thanks for pointing that out.

zeromodule commented 1 year ago

@danielrhodeswarp Hi, Daniel. Does your attached security config work well with LexikJWT ?

danielrhodeswarp commented 1 year ago

Hello @zeromodule Yes, the security config in this issue thread is working well with LexikJWT. And, as Mr. Scheb points out - it's only the login firewall that needs stateless: false

zeromodule commented 1 year ago

@danielrhodeswarp do you use API Platform? I do, and I can't force it to send session cookie on login. stateless: false in the firewall and defaults -> stateless:false in the config/packages/api_platform.yaml don't help. I can't find any working example of combination of API platform and these two bundles (LexikJWT and Scheb2FA)...

zeromodule commented 1 year ago

So, I finally managed to solve it. The problem was that, in the API Platform distribution sessions are explicitly disabled in the framework.yaml (the whole section is commented).

    #    session:
    #        handler_id: null
    #        cookie_secure: auto
    #        cookie_samesite: lax
    #        storage_factory_id: session.storage.factory.native