I just installed this bundle and installed the sandbox application. I can get a token just fine:
curl -X POST http://sandbox.localhost.com/login_check -d _username=test -d _password=test
This returns:
{"token":"eyJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE0OTczMDYwMTgsImlhdCI6MTQ5NzMwMjQxOH0.DJjYjQSRxTDKeikHUs1Dsih7WK_7BownP3SA_gVMKCVUjfn9OfaqCp3bXFErqgAPnWtYn6u-LdX5H40ytW9m6j2pHOAAk8sR_pf_8IoWl4WedMniBzHqXs4hPqPVxH9ZJkGhDYnpWZPwHgxq6iOxnHwV_bLO3ZpLtjekOkh-B2EbWFtFbAZN5wIb-GZGLmerkWXDRzr53F3pf9Zr4guY9jS5_4QAtU5y6oQmzHMKMcn1Bh45BRFjwbf9TzYUHyABUaqA9UxXwJYJkQEXFgh5lfgxZHkrhOhmA4tRnpdceV7gtF_vJpgOlXHIchDNA4SQr9oCdw0oxYubEoV_ce5gh1Jo9irfRWFRfth9T2NEGlZ6qPDcLWvt7BAXjnzLfl_jKkbPwKJid4uT3ROYxGKAnYJhkOGSp0tdgti3w5Yq1Zlqso2Aw2qQmfQtnOXNGzSwtW9mAPXhGiB8DQBKMSNgKCpoeM5BQpFJNuiFOe73LAnyUWNOJjW3YUOuT7jQt4sgq03YcSsVZSwtAhnm4nnHtFaFVgCm4DSACsAbutzFmHLDDp6coDN92mtkWNHvAJhQo1Z9aA497XbtZaFLFEbY21fxhuxBlIzNqfkzjy0lGwPHKcdxnWg29qQSBcoR7T7BVw_kT2z3ujoKlOpJioqobHq7iDA5KbJAMh_rRaEFP2M"}
But when I try to access the /api route:
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE0OTczMDYwMTgsImlhdCI6MTQ5NzMwMjQxOH0.DJjYjQSRxTDKeikHUs1Dsih7WK_7BownP3SA_gVMKCVUjfn9OfaqCp3bXFErqgAPnWtYn6u-LdX5H40ytW9m6j2pHOAAk8sR_pf_8IoWl4WedMniBzHqXs4hPqPVxH9ZJkGhDYnpWZPwHgxq6iOxnHwV_bLO3ZpLtjekOkh-B2EbWFtFbAZN5wIb-GZGLmerkWXDRzr53F3pf9Zr4guY9jS5_4QAtU5y6oQmzHMKMcn1Bh45BRFjwbf9TzYUHyABUaqA9UxXwJYJkQEXFgh5lfgxZHkrhOhmA4tRnpdceV7gtF_vJpgOlXHIchDNA4SQr9oCdw0oxYubEoV_ce5gh1Jo9irfRWFRfth9T2NEGlZ6qPDcLWvt7BAXjnzLfl_jKkbPwKJid4uT3ROYxGKAnYJhkOGSp0tdgti3w5Yq1Zlqso2Aw2qQmfQtnOXNGzSwtW9mAPXhGiB8DQBKMSNgKCpoeM5BQpFJNuiFOe73LAnyUWNOJjW3YUOuT7jQt4sgq03YcSsVZSwtAhnm4nnHtFaFVgCm4DSACsAbutzFmHLDDp6coDN92mtkWNHvAJhQo1Z9aA497XbtZaFLFEbY21fxhuxBlIzNqfkzjy0lGwPHKcdxnWg29qQSBcoR7T7BVw_kT2z3ujoKlOpJioqobHq7iDA5KbJAMh_rRaEFP2M" http://sandbox.localhost.com/api
I get:
{"code":401,"message":"JWT Token not found"}
I have the rewrite code enabled in my Apache vhost, and the token is coming through in the headers:
(Inside src/AppBundle/Security/Guard/JWTAuthenticator.php)
echo print_r(getallheaders(), true);
Array
(
[Host] => sandbox.localhost.com
[User-Agent] => curl/7.43.0
[Accept] => */*
[Authorization] => Bearer eyJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE0OTczMDYwMTgsImlhdCI6MTQ5NzMwMjQxOH0.DJjYjQSRxTDKeikHUs1Dsih7WK_7BownP3SA_gVMKCVUjfn9OfaqCp3bXFErqgAPnWtYn6u-LdX5H40ytW9m6j2pHOAAk8sR_pf_8IoWl4WedMniBzHqXs4hPqPVxH9ZJkGhDYnpWZPwHgxq6iOxnHwV_bLO3ZpLtjekOkh-B2EbWFtFbAZN5wIb-GZGLmerkWXDRzr53F3pf9Zr4guY9jS5_4QAtU5y6oQmzHMKMcn1Bh45BRFjwbf9TzYUHyABUaqA9UxXwJYJkQEXFgh5lfgxZHkrhOhmA4tRnpdceV7gtF_vJpgOlXHIchDNA4SQr9oCdw0oxYubEoV_ce5gh1Jo9irfRWFRfth9T2NEGlZ6qPDcLWvt7BAXjnzLfl_jKkbPwKJid4uT3ROYxGKAnYJhkOGSp0tdgti3w5Yq1Zlqso2Aw2qQmfQtnOXNGzSwtW9mAPXhGiB8DQBKMSNgKCpoeM5BQpFJNuiFOe73LAnyUWNOJjW3YUOuT7jQt4sgq03YcSsVZSwtAhnm4nnHtFaFVgCm4DSACsAbutzFmHLDDp6coDN92mtkWNHvAJhQo1Z9aA497XbtZaFLFEbY21fxhuxBlIzNqfkzjy0lGwPHKcdxnWg29qQSBcoR7T7BVw_kT2z3ujoKlOpJioqobHq7iDA5KbJAMh_rRaEFP2M
)
Using Symfony 3.3.2 and latest JWT bundle (2.02 I believe?) Also using the stock configs in the sandbox app.
Any ideas? Thank you!
Can you dump $request->headers from the authenticator to see if the Authorization header is present?
And if it is, past the content of your config.yml + security.yml here?
Here are the headers from the request object passed to the TokenExtractor:
Symfony\Component\HttpFoundation\HeaderBag Object
(
[headers:protected] => Array
(
[authorization] => Array
(
[0] => Bearer eyJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJleHAiOjE0OTczNjk5NjAsImlhdCI6MTQ5NzM2NjM2MH0.RMmrr3Mib9LD-kSDADSHz_I2S8OPEtN2VEE5kju3nnU1rvLynl3KEt0d_jIOByqMbP453fMKzJQp_ei1K5CM7HGXzJTqYHzLwVOI_CXO2mzhjFLmPb2uEtzbza4-B82Cfj6BBIxGCFZM7tgvK6hoaU0mP55gWwqLmS77HIeZc0ilJE5g_LwqEGyAoyEBUL7e2MB7g5zVOXarcOLXtf0s49IiewuwpBTTzU_VBYlvJR-kuDTe2AhKNYmkeJ89gSX_B8DJExKo_NNPsjkxUJBmVL4SsHV2RtLZCxroW1eQnAr-KqS-2Q41vJmDXCEG_zJw3MJnhqMhZdUqSCjbmavvoDgeTEJAtxt61DdntMov4Ihipxi-w8T4Ov7VitgV3xSORp5nZosCwLoQflhDAE_A_aflQU02_c8EovvZzWa986dsLJPUR95lFP3eeYz3FP8qpGTQUlS7wZvSeyXI9RuIBQRy-I94UMPIqdNQPpUkDpjhsjb5H-Gm15I4ecDZyqsjSUNgODecKBNITtC-fKpe7BNpCv7GJVLrrmAexRpSHSehxl-gnZcnMw_YKvaTlvnCC4YkPvtpasm76Iimwwnok6LljsRFoDoceNtp9hooq9xaCFi9IjcxaiMh4GehPh33KdhQvQdrQ1In9WIKHqtKSq5WbhbWCrnWNr6fhb1lG_M
)
[host] => Array
(
[0] => sandbox.localhost.com
)
[user-agent] => Array
(
[0] => curl/7.43.0
)
[accept] => Array
(
[0] => */*
)
[x-php-ob-level] => Array
(
[0] => 0
)
)
[cacheControl:protected] => Array
(
)
)
security.yml
security:
encoders:
AppBundle\Entity\User:
algorithm: bcrypt
providers:
entity_provider:
entity:
class: AppBundle:User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login
stateless: true
anonymous: true
form_login:
check_path: /login_check
require_previous_session: false
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
register:
pattern: ^/register
stateless: true
anonymous: true
api:
pattern: ^/api
stateless: true
anonymous: false
provider: entity_provider
guard:
authenticators:
- app.jwt_token_authenticator
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY }
role_hierarchy:
ROLE_API: [ROLE_USER]
config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
framework:
#esi: ~
#translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# http://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
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%'
parameters.yml
parameters:
database_host: 127.0.0.1
database_port: null
database_name: lexik_jwt_auth
database_user: root
database_password: null
mailer_transport: smtp
mailer_host: 127.0.0.1
mailer_user: null
mailer_password: null
secret: ThisTokenIsNotSoSecretChangeIt
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: 'foobar' # ssh key pass phrase
jwt_token_ttl: 3600
I have traced to this part of function extract(Request $request) in AuthorizationHeaderTokenExtractor.php:
if (!(count($headerParts) === 2 && $headerParts[0] === $this->prefix)) {
return false;
}
$headerParts[0] = 'Bearer', not 'JWT' as configured in the sandbox app. Changing this call in JWTAuthenticator.php in function getTokenExtractor fixed it:
not-working:
$chainExtractor->addExtractor(new AuthorizationHeaderTokenExtractor('JWT', 'Authorization'));
working:
$chainExtractor->addExtractor(new AuthorizationHeaderTokenExtractor('Bearer', 'Authorization'));
I will close this issue. Thank you!
Ah yea... This is made to demonstrate the ability to alter token extractors from the authenticator itself, but it seems more misleading than helpful, I may change this to reflect the bundle doc. Thanks for the feedback!
As this is the first search result for "JWT not found header lexik", I'll add some infos.
If you do the same thing as @becauseinterwebs and at the last step, you cant' find the authorization line in your headers, there is probably a problem with your apache vhost config.
See the documentation part which I totally missed:
As stated in this link and this one, Apache server will strip any Authorization header not in a valid HTTP BASIC AUTH format.
If you intend to use the authorization header mode of this bundle (and you should), please add those rules to your VirtualHost configuration :
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
NOTE: Don't put this in a Directory section, it belongs to the root of your config.
Hi @leogout , where is the virtualhost folder for the apache server of symfony ?
I got the same problem for few days now and i can't resolve it.
I still got "JWT Token not found" .
And how can you get the token in a controller for checking if the user is authenticated ?
Thanks for your reply guys.
Hi @leogout , where is the virtualhost folder for the apache server of symfony ?
Depends on your machine. On my Mac its in the direction /etc/private/apache2/
The exact file name you can find in the httpd.conf in the same directory. In my case it's a custom config file: virtualhosts-private.conf
You have then to put
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
inside
<VirtualHost *:443>
It would be great if some kind of "Notice" about this will appear in documentation for Lexik? :) I spent few hours digging what the hell is going on :)
Thanks to @leogout for this answer!
Something like this: https://github.com/lexik/LexikJWTAuthenticationBundle/blob/master/Resources/doc/index.md#important-note-for-apache-users
@Spomky excactly! :)
it confirms my belief that I should read the documentation more carefully
In addition to @leogout , if someone is using htaccess, can add this:
# Fix JWT Authentication problem
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
Most helpful comment
As this is the first search result for "JWT not found header lexik", I'll add some infos.
If you do the same thing as @becauseinterwebs and at the last step, you cant' find the authorization line in your headers, there is probably a problem with your apache vhost config.
See the documentation part which I totally missed:
Important note for Apache users
As stated in this link and this one, Apache server will strip any
Authorization headernot in a valid HTTP BASIC AUTH format.If you intend to use the authorization header mode of this bundle (and you should), please add those rules to your VirtualHost configuration :
NOTE: Don't put this in a Directory section, it belongs to the root of your config.