lexik/LexikJWTAuthenticationBundle

Postman Ok, Fetch Not Ok

helveden opened this issue · 4 comments

Hello my fetch not working

var datas = {email: "charrieralexis3@gmail.com", password: "Toto@0"}
fetch(url, {method: 'post', body = JSON.stringify(datas)})

Fetch result :
Unable to find the controller for path "/api/login_check". The route is wrongly configured. (404 Not Found)

I try with header Content-type application/json but fetch is failed and 2 call exec.

If you have a success with fetch.
I use expojs for join the Api.

Thank you

Postman result :
image

Ok now I have solved my initial problem. Now when I send the token I get a 401 status.

When i call my local website. /api/annonce

access_control:
         # - { path: ^/admin, roles: ROLE_ADMIN }
         # - { path: ^/profile, roles: ROLE_USER }
         - { path: ^/api/login, roles: PUBLIC_ACCESS }
         - { path: ^/api, roles: IS_AUTHENTICATED_FULLY }

when i change it's working :

     `- { path: ^/api, roles: PUBLIC_ACCESS }`

Make sure your fetch contain "application/json" header.

I resolve my problem with this a new Authenticator with the doc Symfony :

https://symfony.com/bundles/LexikJWTAuthenticationBundle/current/6-extending-jwt-authenticator.html#using-different-token-extractors-per-authenticator

<?php

namespace App\Security;

use Lexik\Bundle\JWTAuthenticationBundle\Security\Authenticator\JWTAuthenticator;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\TokenExtractorInterface;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\AuthorizationHeaderTokenExtractor;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\CookieTokenExtractor;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\QueryParameterTokenExtractor;

class TokenAuthenticator extends JWTAuthenticator
{
    /**
    * @return TokenExtractor\TokenExtractorInterface
    */
    protected function getTokenExtractor():TokenExtractorInterface
    {
        // Return a custom extractor, no matter of what are configured
        return new AuthorizationHeaderTokenExtractor('Bearer', 'Authentication');

        // Or retrieve the chain token extractor for mapping/unmapping extractors for this authenticator
        $chainExtractor = parent::getTokenExtractor();

        // Clear the token extractor map from all configured extractors
        $chainExtractor->clearMap();

        // Or only remove a specific extractor
        $chainTokenExtractor->removeExtractor(function (TokenExtractorInterface $extractor) {
            return $extractor instanceof CookieTokenExtractor;
        });

        // Add a new query parameter extractor to the configured ones
        $chainExtractor->addExtractor(new QueryParameterTokenExtractor('jwt'));

        // Return the chain token extractor with the new map
        return $chainTokenExtractor;
    }
}
security:
    enable_authenticator_manager: true
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email

    firewalls: 
        login:
            pattern: /api/login_check
            stateless: true
            json_login:
                username_path: email
                check_path: /api/login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure

        api:
            pattern:   /api
            stateless: true
            jwt: 
                authenticator: app.token_authenticator

        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        
        main: 
            pattern:    /.*
            lazy: true
            provider: app_user_provider
            custom_authenticator: App\Security\AppAuthenticator
            logout:
                path: app_logout

            # activate different ways to authenticate
            # https://symfony.com/doc/current/security.html#the-firewall

            # https://symfony.com/doc/current/security/impersonating_user.html
            # switch_user: true
nelmio_cors:
    paths:
        '/api/login_check':
            allow_origin: ['*']
            allow_headers: ['*']
            allow_methods: ['POST', 'PUT','OPTIONS', 'GET', 'DELETE']
            max_age: 3600
        '/api/.*':
            allow_origin: ['*']
            allow_headers: ['*']
            allow_methods: ['POST', 'PUT', 'OPTIONS', 'GET', 'DELETE']
            max_age: 3600
  async req() {
       var myHeaders = new Headers();
       myHeaders.append("Access-Control-Allow-Origin", "*");
       myHeaders.append("Content-Type", "application/json");
       // myHeaders.append("Cache-Control", "no-cache");

       if(localStorage.getItem('token')) {
           
           myHeaders.append("Authentication", "Bearer " + localStorage.getItem('token'));
       }
       
       var url = 'http://api.loc/api/' + this.entity

       var args = {
           method: this.action, 
           headers: myHeaders 
       }

       if(this.datas !== null) {
           args.body = JSON.stringify(this.datas)
       }

       return await fetch(url, args)
           .then(function(response) {
               
               if (!response.ok) {
                   return Promise.reject('some reason');
               }
           
               return response.json();
           })
           .then(response => response)
           .catch(error => console.log("Erreur : " + error));

Cool cool.