-1

I have deployed an API-Platform app using JWT token to ElasticBeanstalk which, as usual, works fine in my local server.

On EB though it is denying access to logged in users despite the correct BearerToken being provided.

This is the error thrown:

{
 "errors": [
    {
        "message": "Access Denied.",
        "extensions": {
            "category": "graphql"
        },
        "locations": [
            {
                "line": 6,
                "column": 9
            }
        ],
        "path": [
            "retrievedQueryUser"
        ]
    }
],
"data": {
    "retrievedQueryUser": null
}
}

The query in question attempts to retrieve user profile info through the below graphql config:

*          "retrievedQuery"={
*              "item_query"=UserProfileResolver::class,
*              "normalization_context"={"groups"={"get-owner"}},
*              "security"="is_granted('IS_AUTHENTICATED_FULLY') and object == user"
*          },

So, it should be a simple matter of checking if the users IS_AUTHENTICATED_FULLY and if it is the user him/herself trying to execute the query.

Far as I could tell, by dump below on /vendor/symfony/security-core/Authorization/AuthorizationChecker.php, it's failing to retrieve a token.

 var_dump($this->tokenStorage->getToken()->getUser()->getUsername());

I did a cursory comparison of phpinfo() between my local installation and the one at AWS-EB and could not find any obvious mismatch.

This is the config for JWT at /config/packages/lexik_jwt_authentication.yaml.

lexik_jwt_authentication:
   secret_key: '%env(resolve:JWT_SECRET_KEY)%'
   public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
   pass_phrase: '%env(JWT_PASSPHRASE)%'
   user_identity_field: email
   token_ttl: 1800

Just to confirm that the users are able to login. It's passing through the isGranted() check that fails.

Any ideas?

EDIT - add `/config/packages/security.yaml

security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
    App\Entity\User:
        algorithm: auto
        #algorithm: bcrypt
        #algorithm: argon2i
        cost: 12
providers:
    database:
        entity:
            class: App\Entity\User
            property: email
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    refresh:
        pattern:  ^/api/token/refresh
        stateless: true
        anonymous: true
    api:
        pattern:  ^/api
        stateless: true
        anonymous: true
        json_login:
            check_path:               /api/login_check
            success_handler:          lexik_jwt_authentication.handler.authentication_success
            failure_handler:          lexik_jwt_authentication.handler.authentication_failure
        guard: 
            authenticators: 
                - app.google_login_authenticator
                - App\Security\TokenAuthenticator
            entry_point: App\Security\TokenAuthenticator
        user_checker: App\Security\UserEnabledChecker
     access_control:
    - { path: ^/login,     roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin,     roles: ROLE_SUPERADMIN }
    - { path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api,       roles: IS_AUTHENTICATED_ANONYMOUSLY }
role_hierarchy:
    ROLE_PROVIDER: ROLE_USER
    ROLE_ADMIN: [ROLE_PROVIDER, ROLE_EDITOR]
    ROLE_SUPERADMIN: ROLE_ADMIN
BernardA
  • 1,391
  • 19
  • 48
  • What's the route and firewall configuration? Do other protected paths that require a JWT token work? – yivi Mar 14 '20 at 12:04
  • I added `security.yaml` to the body of the question. Concerning routes, this being `graphql`, they all look like: `https:mywebsite/api/graphql` – BernardA Mar 14 '20 at 12:23
  • According to your access control rules, `/api/graphql` does not require authentication. – yivi Mar 14 '20 at 12:25
  • Do other routes on `/api/graphql` and require authentication work? I would move the `IS_AUTHENTICATED` rule to your access control section, and just have `object == user` on the security annotation. – yivi Mar 14 '20 at 12:36
  • That's correct: `/api/graphql` does not require authentication. There are several queries that are open to anybody. But to get most of the user info the access control is in place at the query level and, as it;s the case with the query in question, both the user should be authenticated and should be the user him/herself to access the info. Overall I do not think it is anything to do with security config. As said, all works fine locally with the same config. – BernardA Mar 14 '20 at 12:51
  • care to explain why is this question voted down? What is wrong with it? Or did you just have a bad day? – BernardA Mar 14 '20 at 19:57
  • I didn’t vote on the question in any way. – yivi Mar 14 '20 at 20:00

1 Answers1

0

Upon further research I found out that Apache was stripping the authorization token from the request.

On the method supports of /lexik/jwt-authenticator-bundle/Security/Guard/JWTTokenAuthenticator, the dump as below will not include the token on AWS:

 var_dump($request->headers->all());
 var_dump($_SERVER);

As per this question, this is an issue of Apache configuration which is not accepting the authorization headers.

The indicated solution is to add the following to .htaccess:

 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

This resolves the issue, though one should note that the local Apache installation works fine without the above edit to .htaccess.

So, it should also be possible to change Apache config directly, but I could not find how to go about it.

EDIT: Later I found a specific instruction on 'JWT-Token' docs as follows, that confirm that solution on this link.

BernardA
  • 1,391
  • 19
  • 48