-1

I have a project with Symfony 5.1 using Lexik JWT v2.8.0, gesdinet jwt refresh token v0.9.1 and my own entity user. I can log in with JWT and get the token, save it in a HttpOnly cookie and use it with the protected APIs successfully.

I have implemented CRUD API with the route /api/user/ and I don't want non logged in users to be able to update or delete users, so I need to grant access to non logged in and logged in users to create and read users.

I used a different route to create users /api/register and added it to the access_control with IS_AUTHENTICATED_ANONYMOUSLY, so it's working fine with non logged in users.

But to get a users list I use the /api/user/ route with GET method as the route is shared with PUT and DELETE methods, I only want the GET method to be accesible.

my access_control in security.yaml is:

access_control:
    - { path: ^/api/user, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET] }
    - { path: ^/api/linkpage, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET] }
    - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api, roles: IS_AUTHENTICATED_FULLY } 

But when I try to get the users without a token, I get a 401 unauthorised message, I can only have the list of users if I am logged in and have a token.

PD: I have the same problem with the /api/linkpage route with GET method if I need a list of linkpages and I don't have a token.

edit: this is the full security.yaml:

security:
    encoders:
        UserBundle\Domain\Entity\User:
            algorithm: auto

    providers:
        app_user_provider:
            entity:
                class: UserBundle\Domain\Entity\User
                property: email
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login:
            pattern: ^/api/login
            stateless: true
            anonymous: true
            json_login:
                provider: app_user_provider
                check_path: /api/login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
        refresh:
            pattern:  ^/api/token/refresh
            stateless: true
            anonymous: true
        register:
            pattern: ^/api/register
            stateless: true
            anonymous: true
        api:
            pattern: ^/api
            stateless: true
            provider: app_user_provider
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator
        main:
            anonymous: true
            lazy: true
            provider: app_user_provider

    access_control:
        - { path: ^/api/user, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET] }
        - { path: ^/api/linkpage, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET] }
        - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
Alex
  • 1,230
  • 2
  • 24
  • 46

1 Answers1

3

The issue is right here

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

You can add anonymous: true as you're protected by

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

And you're explicitly listing the other routes accessible by non authenticated users.

DonCallisto
  • 29,419
  • 9
  • 72
  • 100