LexikJWTAuthenticationBundle: "code": 401, "message": "Invalid credentials." while passing the jwt
Hey, I’m currently trying to implement the JWT Authentication Bundle in my API Platform Project. Everything has worked well so far, except that I’m unable to access my resources with a generated JWT Token.
I’m able to generate a JWT Token, when passing a username and a password to the backend. But as soon as I’m trying to use this token I receive this 401 error.
The request is passed with http to the backend on my localhost, I also tried https. I manually validated the jwt on jwt.io and everything seems to be fine with the token.
The API Platform project runs in a docker container.
If you need some further information, just let me know
Operating System: Mac OS
My security.yml
security:
password_hashers:
# use your user class name here
App\Entity\User:
# Use native password hasher, which auto-selects the best
# possible hashing algorithm (starting from Symfony 5.3 this is "bcrypt")
algorithm: auto
encoders:
App\Entity\User:
algorithm: auto
# https://symfony.com/doc/current/security/experimental_authenticators.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
public:
methods: [POST]
pattern: ^/user/create
security: false
login:
methods: [POST]
pattern: ^/authentication_token
json_login:
check_path: /authentication_token
username_path: email
password_path: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
main:
stateless: true
# anonymous: true
provider: app_user_provider
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# 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: ^/users, roles: PUBLIC, methods: [POST] }
- { path: ^/docs, roles: IS_AUTHENTICATED_ANONYMOUSLY } # Allows accessing the Swagger UI
- { path: ^/authentication_token, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_FULLY }
api-platform.yml
api_platform:
title: Hello API Platform
version: 1.0.0
mapping:
paths: ['%kernel.project_dir%/src/Entity']
patch_formats:
json: ['application/merge-patch+json']
swagger:
versions: [3]
api_keys:
apiKey:
name: Authorization
type: header
# Mercure integration, remove if unwanted
mercure: ~
# Good cache defaults for REST APIs
defaults:
stateless: true
cache_headers:
vary: ['Content-Type', 'Authorization', 'Origin']
Lexikon_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)%'
JwtDecorator.php
<?php
// api/src/OpenApi/JwtDecorator.php
declare(strict_types=1);
namespace App\OpenApi;
use ApiPlatform\Core\OpenApi\Factory\OpenApiFactoryInterface;
use ApiPlatform\Core\OpenApi\OpenApi;
use ApiPlatform\Core\OpenApi\Model;
final class JwtDecorator implements OpenApiFactoryInterface
{
public function __construct(
private OpenApiFactoryInterface $decorated
) {}
public function __invoke(array $context = []): OpenApi
{
$openApi = ($this->decorated)($context);
$schemas = $openApi->getComponents()->getSchemas();
$schemas['Token'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'token' => [
'type' => 'string',
'readOnly' => true,
],
],
]);
$schemas['Credentials'] = new \ArrayObject([
'type' => 'object',
'properties' => [
'email' => [
'type' => 'string',
'example' => 'johndoe@example.com',
],
'password' => [
'type' => 'string',
'example' => 'apassword',
],
],
]);
$pathItem = new Model\PathItem(
ref: 'JWT Token',
post: new Model\Operation(
operationId: 'postCredentialsItem',
tags: ['Token'],
responses: [
'200' => [
'description' => 'Get JWT token',
'content' => [
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Token',
],
],
],
],
],
summary: 'Get JWT token to login.',
requestBody: new Model\RequestBody(
description: 'Generate new JWT Token',
content: new \ArrayObject([
'application/json' => [
'schema' => [
'$ref' => '#/components/schemas/Credentials',
],
],
]),
),
),
);
$openApi->getPaths()->addPath('/authentication_token', $pathItem);
return $openApi;
}
}

About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 15
Having absolutely the same issue. Used docker-compose config from api platform. Followed all their instructions from here. After passing correct creds i get token, but when I try make request with it i get 401 error. Checked token on jwt.io. It says everything is correct and signature is valid.
UPD. I think I faced the reason. Symfony\Bridge\Doctrine\Security\User\EntityUserProvider::loadUserByIdentifier For some reason I receive here my username in $identifier var. But in my security settings i have
So user not found. To confirm this. If i set property: username everything works fine. I think this happens because you always put username in token. But not always this is unique property. Correct me if I’m wrong. Also mb there’s a workaround how we can store another value in token (email e.g.). Thanks beforehand!
UPD2. I guess I’ve solved the problem
solved the issue
Hey, sorry for the close/reopen, that’s a misclick. Are you using the apache webserver? If yes, check https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/Resources/doc/index.md#important-note-for-apache-users. Otherwise, please create and share an application with just enough code to reproduce the issue.