Search code examples
phpsymfonyjwtswaggerapi-platform.com

Symfony, API Platform, JWT: JWT Token not found (401)


I am trying to protect my API with JWT. But the problem is, that I am not able to access Swagger UI, because I get 401: JWT Token not found.

packages/api_platform.yml

api_platform:
    swagger:
        api_keys:
            JWT:
                name: Authorization
                type: header

packages/security.yml

security:
    enable_authenticator_manager: true
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        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:
        login:
            pattern: ^/api/login
            stateless: true
            json_login:
                check_path: /api/login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure

        api:
            pattern:   ^/api
            stateless: true
            jwt: ~

    access_control:
        - { path: ^/api/login, roles: PUBLIC_ACCESS }
        - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }


when@test:
    security:
        password_hashers:
            # By default, password hashers are resource intensive and take time. This is
            # important to generate secure password hashes. In tests however, secure hashes
            # are not important, waste resources and increase test times. The following
            # reduces the work factor to the lowest possible values.
            Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                algorithm: auto
                cost: 4 # Lowest possible value for bcrypt
                time_cost: 3 # Lowest possible value for argon
                memory_cost: 10 # Lowest possible value for argon

lexik_jwt_authentication.yml

lexik_jwt_authentication:
    secret_key: '%env(resolve:JWT_SECRET_KEY)%'
    public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
    pass_phrase: '%env(JWT_PASSPHRASE)%'

    api_platform:
        check_path: /api/login_check
        username_path: email
        password_path: security.credentials.password

As well I generated JWT with lexik:jwt:generate-keypair. As soon as I create CURL Request from terminal, I get the Token back

curl -X POST -H "Content-Type: application/json" https://project-symfony.ddev.site/index.php/api/login_check -d '{"username":"[email protected]","password":"admin"}'

I'm trying to use Swagger UI and add a bearer token there. But when I go to https://project-symfony.ddev.site/api, it says 'JWT is not found.' Any ideas? I've checked tutorials from API Platform, Lexik Documentation, Symfony, but nothing's working. I am Using Symfony 6.4.4, with security-bundle


Solution

  • I have modified API's Pattern in the security.yml by adding a slash at pattern: ^/api/

    Complete security.yml

    security:
        # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
        password_hashers:
            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:
            login:
                pattern: ^/api/login
                stateless: true
                json_login:
                    check_path: /api/login_check
                    success_handler: lexik_jwt_authentication.handler.authentication_success
                    failure_handler: lexik_jwt_authentication.handler.authentication_failure
    
            api:
                pattern:   ^/api/  #Slash added 
                stateless: true
                jwt: ~
    
        access_control:
            - { path: ^/api/login, roles: PUBLIC_ACCESS }
            - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }
    
    when@test:
        security:
            password_hashers:
                # By default, password hashers are resource intensive and take time. This is
                # important to generate secure password hashes. In tests however, secure hashes
                # are not important, waste resources and increase test times. The following
                # reduces the work factor to the lowest possible values.
                Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                    algorithm: auto
                    cost: 4 # Lowest possible value for bcrypt
                    time_cost: 3 # Lowest possible value for argon
                    memory_cost: 10 # Lowest possible value for argon
    
    

    With this change, API Platform/Swagger UI works seamlessly, allowing authorizations to be processed by entering the bearer token.