lexik / LexikJWTAuthenticationBundle

JWT authentication for your Symfony API
MIT License
2.52k stars 611 forks source link

API Full authentication is required to access this resource. #489

Open Ogek opened 6 years ago

Ogek commented 6 years ago

Hi guys, I've just started using this bundle. I'm using Symfony 4. My problem is that once I authenticate and save the token in cookies when I make a request to my api routes, I get a 500 error caused by a double exception in Symfony. I based this skeleton to build the application: https://github.com/Limenius/symfony-react-sandbox/tree/symfony4. The errors I receive are these:

Full authentication is required to access this resource.

InsufficientAuthenticationException

AccessDeniedException
Access Denied.

I think my problems are that I'm logged in as anonymous even if the login request returns me the token. Below my security configuration:

security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
    # https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
    providers:
        in_memory:
            memory:
                users:
                    "USERNAME":
                        password: "PASSWORD"
                        roles: 'ROLE_ADMIN'
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        api_login:
            pattern:  ^/api/login
            stateless: true
            anonymous: true
            form_login:
                check_path:               /api/login_check
                success_handler:          lexik_jwt_authentication.handler.authentication_success
                failure_handler:          lexik_jwt_authentication.handler.authentication_failure
                require_previous_session: false

        admin:
            pattern:   ^/admin/api
            stateless: true
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator

        admin_api:
            pattern:   ^/admin/api
            stateless: true
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator

        main:
            anonymous: ~

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

Thank you.

chalasr commented 6 years ago

Doesn't your security miss a role hierarchy? Your ROLE_ADMIN does't fulfil the IS_AUTHENTICATED_FULLY requirement I guess.

Try adding:

role_hierarchy:
    ROLE_ADMIN: [ROLE_USER]
ollo-ride-nico commented 6 years ago

Hello, I have the same problem.

Would you have a solution please?

Thanks you

security:
    role_hierarchy:
        ROLE_ADMIN: [ROLE_USER]

    encoders:
        App\Entity\Client:
            algorithm: bcrypt

    providers:
        our_db_provider:
            entity:
                class: App\Entity\Client
                property: username

    firewalls:

        main:
            #pattern: ^/login
            stateless: true
            anonymous: true
            provider: our_db_provider
            json_login:
                check_path: login
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure

        api:
            pattern: ^/api
            stateless: true
            anonymous: true
            provider: our_db_provider
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator

        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/clients, roles: IS_AUTHENTICATED_FULLY }
chalasr commented 6 years ago

Sorry guys, I need a full reproducer in order to help. Please share us a sample app with enough code to reproduce the bug + the steps needed to reproduce it

castorinop commented 6 years ago

Same problem here using api platfrom

src/Entity/Customer.php:

/** @ORM\Entity
 * @ApiResource(attributes={
 *        "access_control"="is_granted('ROLE_ADMIN')"
 *    })
 *
 */
class Customer

I can see that "Guard autentication suceful", but later "Guard authenticator set no success response"

Steps: Watching the logs appears this

[2018-07-15 13:26:21] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"api","authenticators":1} []
[2018-07-15 13:26:21] security.DEBUG: Calling getCredentials() on guard configurator. {"firewall_key":"api","authenticator":"Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Guard\\JWTTokenAuthenticator"} []
[2018-07-15 13:26:21] security.DEBUG: Passing guard token information to the GuardAuthenticationProvider {"firewall_key":"api","authenticator":"Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Guard\\JWTTokenAuthenticator"} []
[2018-07-15 13:26:21] security.INFO: Guard authentication successful! {"token":"[object] (Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Authentication\\Token\\JWTUserToken: JWTUserToken(user=\"admin\", authenticated=true, roles=\"USER_ADMIN\"))","authenticator":"Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Guard\\JWTTokenAuthenticator"} []
[2018-07-15 13:30:46] security.DEBUG: Guard authenticator set no success response: request continues. {"authenticator":"Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Guard\\JWTTokenAuthenticator"} []
[2018-07-15 13:30:46] security.DEBUG: Remember me skipped: it is not configured for the firewall. {"authenticator":"Lexik\\Bundle\\JWTAuthenticationBundle\\Security\\Guard\\JWTTokenAuthenticator"} []
[2018-07-15 13:30:47] security.DEBUG: Access denied, the user is neither anonymous, nor remember-me. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /srv/api/vendor/api-platform/core/src/Security/EventListener/DenyAccessListener.php:79)"} []
[2018-07-15 13:30:47] request.ERROR: Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: "Access Denied." at /srv/api/vendor/symfony/security/Http/Firewall/ExceptionListener.php line 117 {"exception":"[object] (Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException(code: 0): Access Denied. at /srv/api/vendor/symfony/security/Http/Firewall/ExceptionListener.php:117, Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /srv/api/vendor/api-platform/core/src/Security/EventListener/DenyAccessListener.php:79)"} []

And debuging see onAuthenticationSuccess return null when Guard expects a Response.

vendor/lexik/jwt-authentication-bundle/Security/Guard/JWTTokenAuthenticator.php:

185  public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
186  {
187       return;
 188  }
mu4ddi3 commented 5 years ago

@ogek i can see "admin/api" here, "api/admin" there. Are you sure this config is ok?

@castorinop, return null from that means request will continue, just no redirect etc.

If it is still actuall, bring some code & config or reproducer as chalasr said before

chalasr commented 5 years ago

Closing due to the lack of feedback. Feel free to reopen (providing enough code to reproduce). Thanks

RobinTHOREL commented 5 years ago

I have the same issue on my api platform project.

You can find way to reproduce the error on this link : https://github.com/ButterCorp/Backr-api/issues/6

NCS-Thomas commented 5 years ago

I can reproduce this issue, but am not in a position to explain why.

  1. The value for security > firewalls > login > pattern is not equals to the value for security > firewalls > login > json_log > check_path (besides a starting ^ character in the pattern)

  2. When is security > firewalls > login > pattern omitted / commented out

wuestkamp commented 5 years ago

I can confirm @NCS-Thomas , it's necessary to have security.firewalls.login.pattern defined. For me this works:

        login:
            pattern: ^/auth
            stateless: true
            anonymous: true
            json_login:
                check_path: /auth
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure