Frederik Hulleman
Frederik Hulleman

Reputation: 11

How to set-up google authenticator as a second factor authentication in Api Platform?

I'm currently using the default JWT authentication in my API platform project. But I want to try adding 2 factor authentication (with google authenticator) to my projects.

I followed the following instructions:

If I login with an existing and valid email + pwd, I nicely get the response: {"login": "success", "two_factor_complete": false}

However, no I don't know to continue: which endpoint should I use post my 2fa code?

I copy and pasted the 4 handlers from here (and didn't change a thing)

My config/routes/scheb_2fa.yaml:

2fa_login:
    path: /2fa
    defaults:
        _controller: "scheb_two_factor.form_controller::form"

2fa_login_check:
    path: /2fa_check

My config/packages/scheb_2fa.yaml:

scheb_two_factor:
    security_tokens:
        - Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken
        - Symfony\Component\Security\Http\Authenticator\Token\PostAuthenticationToken
    google:
        enabled: true                  # If Google Authenticator should be enabled, default false
        server_name: Server Name       # Server name used in QR code
        issuer: Issuer Name            # Issuer name used in QR code
        digits: 6                      # Number of digits in authentication code
        window: 1                      # Depends on the version of Spomky-Labs/otphp used:
        # Until v10: How many codes before/after the current one would be accepted
        # From v11: Acceptable time drift in seconds
        # template: security/2fa_form.html.twig   # Template used to render the authentication form

My config/packages/security.yaml:

security:
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        App\Entity\User: 'auto'

    enable_authenticator_manager: true

    # Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            stateless: false
            lazy: true
            provider: app_user_provider

            json_login:
                check_path: /authentication_token
                username_path: email
                password_path: password
                success_handler: App\Security\AuthenticationSuccessHandler
                #success_handler: lexik_jwt_authentication.handler.authentication_success
                #failure_handler: lexik_jwt_authentication.handler.authentication_failure
            
            jwt: ~

            two_factor:
                prepare_on_login: true
                prepare_on_access_denied: true
                authentication_required_handler: App\Security\TwoFactorAuthenticationRequiredHandler
                success_handler: App\Security\TwoFactorAuthenticationSuccessHandler
                failure_handler: App\Security\TwoFactorAuthenticationFailureHandler
                auth_code_parameter_name: authCode

            logout:
                path: app_logout

            # activate different ways to authenticate
            # https://symfony.com/doc/current/security.html#the-firewall

            # https://symfony.com/doc/current/security/impersonating_user.html
            # switch_user: true

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        # This makes the logout route accessible during two-factor authentication. Allows the user to
        # cancel two-factor authentication, if they need to.
        - { path: ^/logout, role: PUBLIC_ACCESS }
        # This ensures that the form can only be accessed when two-factor authentication is in progress.
        - { path: ^/2fa, role: IS_AUTHENTICATED_2FA_IN_PROGRESS }
        - { path: ^/api/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI
        - { route: api_entrypoint, roles: PUBLIC_ACCESS }
        - { route: api_doc, roles: PUBLIC_ACCESS }
        - { route: api_jsonld_context, roles: PUBLIC_ACCESS }
        - { path: ^/authentication_token, roles: PUBLIC_ACCESS }
        - { path: ^/request_password, roles: PUBLIC_ACCESS }
        - { path: ^/set_password, roles: PUBLIC_ACCESS }
        - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
        - { path: ^/, roles: PUBLIC_ACCESS }

And I added the $googleAuthenticatorSecret property to my User Entity, incl. the following functions:

    public function isGoogleAuthenticatorEnabled(): bool
    {
        return null !== $this->googleAuthenticatorSecret;
    }

    public function getGoogleAuthenticatorUsername(): string
    {
        return $this->email;
    }

    public function getGoogleAuthenticatorSecret(): ?string
    {
        return $this->googleAuthenticatorSecret;
    }

    public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void
    {
        $this->googleAuthenticatorSecret = $googleAuthenticatorSecret;
    }

All my existing users have a secret. And I added a secret to my Google Authenticator app. So that should work just fine.

But I have no clue how to set up/configure the endpoint to post the 2fa code to!

Thanks in advance!

Upvotes: 1

Views: 754

Answers (0)

Related Questions