Lexikjwtauthenticationbundle: FOSUser + LexikJWT still returning 401 "Bad Credentials"

Created on 5 May 2015  Â·  44Comments  Â·  Source: lexik/LexikJWTAuthenticationBundle

Hello,
After reading and trying all fixes found in here trying to get LexikJWT and FOSUser working together, I finally create my own new issue because I could really not find a way, it's still returning 401 "Bad Credentials"...

I need a "backend admin" login (which is working) independent from my API login which will be used in an hybrid app.

Here is my security.yml :

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_API:         ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

    firewalls:
        admin:
            pattern: ^/admin
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:
                path:        /admin/logout
                target:      /admin
            anonymous:    true

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

        login:
            pattern:  ^/api/login
            stateless: true
            anonymous: true
            provider: fos_userbundle
            form_login:
                check_path:     /api/login_check
                username_parameter: username
                password_parameter: password
                require_previous_session: false
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure

        api:
            pattern:   ^/api
            stateless: true
            provider: fos_userbundle
            lexik_jwt:
                authorization_header:
                    enabled: true
                    prefix:  Bearer
                throw_exceptions:        false
                create_entry_point:      true

    access_control:
        - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN }
        - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api, roles: [IS_AUTHENTICATED_FULLY, ROLE_API, ROLE_ADMIN] }

If someone has any idea why I cannot manage to get this working, I thank you in advance.

I'm trying using Sandbox's AngularJS implementation and Curl CLI, they both return 401 Bad Credentials..

Most helpful comment

Well... I've just faced the same problem now and I fixed it by creating an empty file src/Repository/UserRepository.php because I'm using src/Entity/User.php . As simple as it sounds...
I hope it might help somebody...

All 44 comments

Hi,

I see you are using the fos_user.user_provider.username_email user provider. Are the email and username values equal in your user entities ? If they are different, check the configuration reference and try to change the user_identity_field to email in the bundle configuration.

Let me know if it helps.

Thank you for answering me so quickly.
I've overriden the FOSUser's setEmail function in my entity class to make them the same. As described here :

public function setEmail($email){
    parent::setEmail($email);
    $this->setUsername($email);
}

I checked in database, they are the same. And I tried both email and username in user_identity_field parameter.
My FOSUser's backend login works with both fos_user.user_provider.username_email and fos_user.user_provider.username, so I tried all combination of - listed before - providers, username_parameter, password_parameter, and user_identity_field.

Hi ! I am having the exact same issue.
I am also using FOSUserBundle.
After getting the token, any call to the api returns a 401 Bad Credentials.

I am using an Angular App and I have the exact same code as in the Sandbox Bundle.

And I precise that I have added the RewriteEngine in my vhost (I'm using wamp for dev).

Here is the debug from Symfony :

security.INFO: Authentication exception occurred; redirecting to authentication entry point (A Token was not found in the SecurityContext.) 
security.DEBUG: Calling Authentication entry point

Here is my security.yml:

# app/config/security.yml
security:

    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email


    firewalls:
        dev:
            pattern: ^/{_{profiler|wdt}}/
            security: false
            switch_user: true
        api_login:
            pattern:    ^/api/login
            stateless:  true
            anonymous:  true
            logout:     false
            provider:   fos_userbundle
            form_login:
                check_path:               api_login_check
                require_previous_session: false
                username_parameter:       username
                password_parameter:       password
                success_handler:          lexik_jwt_authentication.handler.authentication_success
                failure_handler:          lexik_jwt_authentication.handler.authentication_failure
        api:
            pattern:    ^/api
            stateless:  true
            provider:   fos_userbundle
            lexik_jwt:
                authorization_header:
                    enabled: true
                    prefix:  Bearer
                query_parameter:
                    enabled: true
                    name:    bearer
        main:
            pattern: .*
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:       true
            anonymous:    true
            switch_user:  true

    role_hierarchy:
        ROLE_DELEGATION:        [ROLE_USER]
        ROLE_EXPORT:            [ROLE_USER]
        ROLE_USER_ADMIN:        [ROLE_USER]
        ROLE_LIST_ADMIN:        [ROLE_USER]
        ROLE_IMPORT:            [ROLE_USER]
        ROLE_MOBILE:            [ROLE_USER]
        ROLE_ADMIN:             [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
        ROLE_SUPER_ADMIN:       [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]

    access_control:
        - { path: ^/$, role: ROLE_USER}
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/contacts, role: ROLE_USER }
        - { path: ^/profile, roles: ROLE_USER }
        - { path: ^/entites, role: ROLE_USER }
        - { path: ^/export, role: ROLE_EXPORT }
        - { path: ^/titres, roles: ROLE_ADMIN }
        - { path: ^/categories, roles: ROLE_ADMIN }
        - { path: ^/services, roles: ROLE_ADMIN }
        - { path: ^/groupes, roles: ROLE_ADMIN }
        - { path: ^/admin, roles: ROLE_ADMIN }
        - { path: ^/imports, roles: ROLE_IMPORT }
        - { path: ^/utilisateurs, roles: ROLE_USER_ADMIN }
        - { path: ^/register, role: ROLE_SUPER_ADMIN }
        - { path: ^/group, roles: ROLE_USER_ADMIN }
#        JWT SETUP
        - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api,       roles: ROLE_MOBILE }

@Yonn-Trimoreau have you been able to solve the issue on your side?
No progress on mine... :(

not sure if this will make a difference, but worth a try:

        api:
            pattern:    ^/api/.* # instead of ^/api

No progress on mine neither, I've disabled it since someone helps finding an answer.. I tried debugging but with no success.
@carlcraig Sadly, your solution is not working, but thanks for trying ;)

Hi @Yonn-Trimoreau @vialcollet

I just pushed a new branch on the sandbox repository showing how to make a basic integration of the bundle with fosuserbundle. You can find it here. Use the make install or make test command to test it (you'll need a database).

Based on this simple tests it works fine, so I don't really know how to help without having more info about your code.

By the way, could you show your FOSUserBundle configuration ?

Hi @Yonn-Trimoreau .
That's great news to see that you have spent some of your time configuring this bundle. I am sure I'll be able to understand what's wrong from there.

One thing to mention is that I have two firewalls. One for the standard Symfony web access and another one for the mobile API using AngularJS (Ionic framework).
In the fos_user fonciguration, I specify firewall_name: main only. Maybe that's the reason...

Here is my FOSUserBundle here:

fos_user:
    db_driver: orm
    firewall_name: main
    user_class: Curuba\contactsBundle\Entity\users
    group:
        group_class: Curuba\contactsBundle\Entity\Group
    from_email:
            address:        [email protected]
            sender_name:    Bastien Vial-Collet

I'll keep you posted.

Hmm. No success so far. Your Sandbox is obviously working perfectly on my Windows PC.
I see five differences between your sandbox and my app.

  • I am running my Symfony app from wamp
  • Because of the above and because Angular App is served from a node server I am using CORS.
  • I don't have any specific listeners related to your bundle.
  • I have two logins: one traditional form provided by FOS for Web access and a stateless one used by the application.
  • I have to firewalls : one for the api: api and one for the web access: main

Excepts from the above, configuration and security have the exact same code.

I can confirm that the header of the GET request includes the token (BEARER + token).

What do you suggests as the next step to understand where it is failing. How can I go beyond the exception `You are not authenticated, A Token was not found in the SecurityContext.)?

Have you looked at:
https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#important-note-for-apache-users
Might be this issue that is preventing token from being there for firewall to authenticate.

Hi @carlcraig . Thanks for your help.

I just tried to run the server using app.console server:run and now it works!!
So it confirms that the issue is coming from the apache configuration.

As indicated in my first post, I had activated vhosts in wamp and added the RewriteEngine instructions. But this was not helping.

For information here is what I have:

#httpd.conf
# Virtual hosts
Include conf/extra/httpd-vhosts.conf

And :

#httpd-vhosts.conf
<VirtualHost *:8080>

    DocumentRoot "c:/wamp/www"
    ServerName localhost
    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.)
    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

</VirtualHost>

No idea why this is not working!

My next step will be to deploy on a test server to check everything is fine.

Thank you all for your help and if you have any clue why the above wamp config doesn't work let me know!

@Yonn-Trimoreau Have you made any progress ? Can we close the issue ?

Sorry about the week without answers from me, I was in vacation.
In fact, @vialcollet only invited himself in my issue. Our issues are totally different.
I'm not getting the token at all, while he is.
So, my issue is exacty at the same point as @vialcollet stopped it. When I send my credentials to /api/login_check, it responds 401 Bad Credentials..

I really cannot help you without seeing the code. Have you looked at the fosuser branch of the sandbox ?

Yes, I looked at it and tried your way, still no way of making it work.. Here is my code :

config.yml :

fos_user:
    db_driver: orm
    firewall_name: admin
    user_class: Ork\VtcBundle\Entity\User

lexik_jwt_authentication:
    private_key_path: %kernel.root_dir%/var/jwt/private.pem   # ssh private key path
    public_key_path:  %kernel.root_dir%/var/jwt/public.pem    # ssh public key path
    pass_phrase:      'test'                                 # ssh key pass phrase
    token_ttl:        86400
    encoder_service:     lexik_jwt_authentication.jwt_encoder

security.yml

    firewalls:
        dev:
            pattern:  ^/{_{profiler|wdt}}/
            security: false
            switch_user: true

        api_login:
            pattern:  ^/api/login
            stateless: true
            anonymous: true
            provider: fos_userbundle
            form_login:
                check_path:     api_login_check
                username_parameter: username
                password_parameter: password
                require_previous_session: false
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure

        api:
            pattern:   ^/api
            stateless: true
            lexik_jwt:
                authorization_header:
                    enabled: true
                    prefix:  Bearer
                query_parameter:
                    enabled: true
                    prefix: Bearer
                throw_exceptions:        true

        admin:
            pattern: ^/admin
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:
                path:        /admin/logout
                target:      /admin
            anonymous:    true

routing.yml

fos_user_security:
    resource: "@FOSUserBundle/Resources/config/routing/security.xml"
    prefix: /admin

api_login_check:
    path: /api/login_check

parameters.yml

    jwt_private_key_path: %kernel.root_dir%/var/jwt/private.pem   # ssh private key path
    jwt_public_key_path:  %kernel.root_dir%/var/jwt/public.pem    # ssh public key path
    jwt_key_pass_phrase:  'test'                                      # ssh key pass phrase
    jwt_token_ttl:        86400

I'm sure it's a little thing, thank you for helping me and sorry for bothering you about my issue

No idea ? :(

Sorry no. Have you tried debugging step by step ? Is the success_handler or the failure handler of your form_login even called ?

I don't have any handler set, how do I do this ?

They are present in your security.yml

api_login:
    pattern:  ^/api/login
    stateless: true
    anonymous: true
    provider: fos_userbundle
    form_login:
        check_path:     api_login_check
        username_parameter: username
        password_parameter: password
        require_previous_session: false
        success_handler: lexik_jwt_authentication.handler.authentication_success # here
        failure_handler: lexik_jwt_authentication.handler.authentication_failure # here

But what are they associated to and how do I use it ?

One question @Yonn-Trimoreau, what is your environment?

Linux Mint / Apache 2.4.7 / PHP 5.5.9 / PostgreSQL 9.3.6

I found the problem by debugging the exception returned in the construct

Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationFailureEvent

In my case the exception was coming from FOSuserbundle and telling me no username!

and @trousers did you corrected this pointed problem ?

Facing no username given too in dev.log when using

curl -X POST -d '{"username": "johndoe", "password": "test"}' -H "Content-Type:application/json" http://courtier-web-api-platform/app_dev.php/login_check

Works when using

curl -X POST -d username="johndoe" -d password="test" http://courtier-web-api-platform/app_dev.php/login_check

But I need to post my request in json.

Hello,
Any updates for this issue? I use JWTAuthenticationBundle with FOSUser and it is impossible for me to authenticate an user with username/email, this is either username or email.

@kent99 Are you able to achieve this with FOSUser only (without this bundle)?
Otherwise, your issue come from FOSUser; or worst, Symfony.

It's not common to have two "username" combined for an authentication. Maybe you should look for only one (either username or email)?

@kent99,

Could you show your security.yml file?

@chalasr yes it worked with FOSUser Bundle Logging by Username or Email

JWTAuthenticationBundle provides only one authentification field?

Maybe I have to open an issue for this but this issue is related to my problem, I allow the user to change his email but as the email does not change in the token payload I have a 401 Bad credentials when the user does another request after that user updated his email.

@skrajewski yes please find my security.yml below

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: ...
        Symfony\Component\Security\Core\User\User:
            algorithm: ...
            cost: ...

...

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email
        in_memory:
            memory:
                users:
                   ...

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        default:
            pattern: ^/api/doc
            provider: ...
            anonymous: ~
            ...

        authenticate:
            pattern:  ^/v1/authenticate
            stateless: true
            anonymous: true
            form_login:
                check_path:               /v1/authenticate
                success_handler:          lexik_jwt_authentication.handler.authentication_success
                failure_handler:          lexik_jwt_authentication.handler.authentication_failure
                require_previous_session: false

        refresh:
            pattern:  ^/v1/token/refresh
            stateless: true
            anonymous: true
            provider: fos_userbundle

        api:
            pattern:   ^/v1
            provider: fos_userbundle
            stateless: true
            anonymous: true
            lexik_jwt: ~

    access_control:
        ...

and my config.yml

fos_user:
    db_driver: orm
    firewall_name: api
    user_class: AppBundle\Entity\User
    ...

lexik_jwt_authentication:
    private_key_path: '%jwt_private_key_path%'
    public_key_path:  '%jwt_public_key_path%'
    pass_phrase:      '%jwt_key_pass_phrase%'
    token_ttl:        '%jwt_token_ttl%'
    user_identity_field: email

Oh, sorry I totally misunderstood your problem. I believed you want mix username + email + password.
I have a working Symfony 2.8 project with FOSUser + LexikJWT. It uses the email as username without problem (with small tricks as you can find here).

I'm pretty sure I can give you all you need to make it works. I be back before the end of this day with code.

@chalasr I want to keep username and email different but my main problem is how to change username/email without to have a 401 from LexikJWT

how to change username/email without to have a 401

@kent99 What do you mean by "change username/email"?
If I correctly understood, you want to authenticate your users through email instead of the (default) username? Otherwise, please give me the exact issue

@chalasr yes I want to authenticate my users through email but also when an user updates his email to not have a 401 Bad credential returned by LexikJWT
Please let me know if I am not clear.

Ok @qdequippe, now I see your problem.
When the user change his email, do you renew the token (using the new email+password)?
Or are you just trying to use the same token as before the email changed?

@chalasr no I don't renew the token currently, I would like to do it automatically without to have to ask password. Yes I try to use the same token.

This is the expected behavior since the JWT is a JSON representation of your user, including identifier.
Depending on the context, you can simply automatically renew the token in the method that updates the user email. Then, you have to find a way to use this new token in front (maybe pass it to the response of the update email action, then use it).

To automatically re-create the token, use the lexik_jwt_authentication.jwt_manager like this:

<?php

use Symfony\Component\HttpFoundation\JsonResponse;

$user = $this->getUser();
$token =  $this->get('lexik_jwt_authentication.jwt_manager')->create($user);

return new JsonResponse(['token' => $token, 'email' => $user->getEmail()]);

@chalasr thank you for your response. I understand that it's an expected behaviour. I will do this.

Install FOSRestBundle and force json

fos_rest: param_fetcher_listener: true view: mime_types: json: ['application/json', 'application/json;version=1.0', 'application/json;version=1.1', 'application/json;version=1.2'] view_response_listener: 'force' formats: xml: true json: true templating_formats: html: true format_listener: rules: - { path: ^/, priorities: [ html, json, xml ], fallback_format: ~, prefer_extension: true } versioning: enabled: true resolvers: media_type: enabled: true exception: codes: 'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404 'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT messages: 'Symfony\Component\Routing\Exception\ResourceNotFoundException': true allowed_methods_listener: true access_denied_listener: json: true body_listener: true body_converter: enabled: true

hello guys,
i have a question i trying to understand how to implement symfony with LexikJWTAuthenticationBundle
i have a 401 bad credential
i followed steps described here and on the project github
Should i write some logic on controllers for generating the token? i didn't see that step on doc?
thx for help?

@kenyramses I suggest you to ask this on stackoverflow, comments on closed issues aren't tracked.

Should i write some logic on controllers for generating the token? i didn't see that step on doc?thx for help?

No, generating the token only requires configuration.
By default, an _username and _password request parameters are expected by the login endpoint (the one that returns a token).

Thank you Robin

2017-07-31 13:45 GMT+02:00 Robin Chalas notifications@github.com:

@kenyramses https://github.com/kenyramses I suggest you to ask this on
stackoverflow, comments on closed issues aren't tracked.

Should i write some logic on controllers for generating the token? i
didn't see that step on doc?thx for help?

No, generating the token only requires configuration.
By default, an _username and _password request parameters are expected.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/lexik/LexikJWTAuthenticationBundle/issues/66#issuecomment-319044485,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKwFe470EmJVD1bwHvXBiyUv7V7wqFabks5sTb5bgaJpZM4EQPU9
.

Please if you've allready use the bundle with symfony, i would like to have
an example if possible

Any github link or source

thx :)

2017-07-31 14:12 GMT+02:00 Ramesses Bonhof KENY kenyramses@gmail.com:

Thank you Robin

2017-07-31 13:45 GMT+02:00 Robin Chalas notifications@github.com:

@kenyramses https://github.com/kenyramses I suggest you to ask this on
stackoverflow, comments on closed issues aren't tracked.

Should i write some logic on controllers for generating the token? i
didn't see that step on doc?thx for help?

No, generating the token only requires configuration.
By default, an _username and _password request parameters are expected.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/lexik/LexikJWTAuthenticationBundle/issues/66#issuecomment-319044485,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKwFe470EmJVD1bwHvXBiyUv7V7wqFabks5sTb5bgaJpZM4EQPU9
.

See https://github.com/chalasr/lexik-jwt-authentication-sandbox

Robin CHALAS
Développeur PHP/Symfony - @chalasr https://github.com/chalasr
E-mail : robin.[email protected] - Site internet : http://www.elao.com
Paris / Lyon / Montpellier - Tel : +33 (0)4 82 53 37 19

Le 31 juillet 2017 à 14:24:07, KENY RAMESSES BONHOF (
[email protected]) a écrit:

Please if you've allready use the bundle with symfony, i would like to have
an example if possible

Any github link or source

thx :)

2017-07-31 14:12 GMT+02:00 Ramesses Bonhof KENY kenyramses@gmail.com:

Thank you Robin

2017-07-31 13:45 GMT+02:00 Robin Chalas notifications@github.com:

@kenyramses https://github.com/kenyramses I suggest you to ask this
on
stackoverflow, comments on closed issues aren't tracked.

Should i write some logic on controllers for generating the token? i
didn't see that step on doc?thx for help?

No, generating the token only requires configuration.
By default, an _username and _password request parameters are expected.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<
https://github.com/lexik/LexikJWTAuthenticationBundle/issues/66#issuecomment-319044485
,
or mute the thread
<
https://github.com/notifications/unsubscribe-auth/AKwFe470EmJVD1bwHvXBiyUv7V7wqFabks5sTb5bgaJpZM4EQPU9

.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/lexik/LexikJWTAuthenticationBundle/issues/66#issuecomment-319052139,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHJ4756R5HKGjYIXL5bh26l_ZejxZOJlks5sTcdngaJpZM4EQPU9
.

Well... I've just faced the same problem now and I fixed it by creating an empty file src/Repository/UserRepository.php because I'm using src/Entity/User.php . As simple as it sounds...
I hope it might help somebody...

@MiguelSMendoza thank you! That solved the problem on my side!

Was this page helpful?
0 / 5 - 0 ratings