phplaraveljwt

Laravel not authenticating JWT token Tymon/jwt-auth


I am trying to implement jwt-auth 2.1 (https://jwt-auth.readthedocs.io/en/develop/quick-start/) in Laravel 9.

I am able to generate the token properly but when I send a request in Postman using the token, the protected route does not recognize the token and returns

"message": "Unauthenticated."

.

It seems that the "if" bellow is always false and not executed.

By the way, my primary key in my table is ID.

vendor/laravel/framework/src/illuminate/Auth/Middleware/Authenticate.php

if ($this->auth->guard($guard)->check()) {
      return $this->auth->shouldUse($guard);
}

How can I solve this? Bellow is my code.

routes/api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FunerariaController;
use App\Http\Controllers\CartorioController;
use App\Http\Controllers\CemiterioController;
use App\Http\Controllers\InumadoController;
use App\Http\Controllers\SepulturaController;
use App\Http\Controllers\TipoGuiaController;
use App\Http\Controllers\TipoSepulturaController;
use App\Http\Controllers\SolicitacaoController;
use App\Http\Controllers\TipoDivergenciaController;
use App\Http\Controllers\TipoVitimadoController;
use App\Http\Controllers\TipoSolicitacaoController;
use App\Http\Controllers\DampagofunerariaController;
use App\Http\Controllers\AprovadorController;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\GuiaSepultamentoController;
use App\Http\Controllers\UsuariofunerariaController;
use App\Http\Controllers\UsuariorecfController;
use App\Http\Controllers\FunerariaFuncionarioController;
use App\Http\Controllers\FunerariaVeiculoController;
use App\Http\Controllers\CategoriacausamorteController;
use App\Http\Controllers\UsuarioController;
use App\Http\Controllers\TipoDocController;
use App\Http\Controllers\PlanoController;
use App\Http\Controllers\PlanoItemController;
use App\Http\Controllers\GraficosCpntroller;


Route::post('login', [AuthController::class, 'login']);
Route::post('logout',[AuthController::class, 'logout']);
Route::post('refresh',[AuthController::class, 'refresh']);
Route::post('me',[AuthController::class, 'me']);
Route::get('verify-token', [AuthController::class, 'verifyToken']);
   
Route::get('/funerariaview/{id}',          [FunerariaController::class, 'index']);

FunerariaController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Session;
use Illuminate\Support\ServiceProvider;
use Illuminate\Routing\Controller;
use App\Models\Funeraria;
use App\Http\Requests;
use Carbon\Carbon;
use DB;
use Illuminate\Support\Facades\Http;

class FunerariaController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api');
    }

AuthController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
// use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
use Illuminate\Support\Facades\Cookie;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Tymon\JWTAuth\Facades\JWTAuth as FacadesJWTAuth;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;

class AuthController extends Controller
{
    /**
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login','verifyToken']]);
    }
public function login()
    {
        Log::info('Entrou em login');
        $received = request(['usuario', 'senha']);
        $credentials = [
            'usu_nome' => $received['usuario'],
            'password' => $received['senha'],
        ];

        Log::info('credentials:',$credentials);

       
        if (! $token = auth()->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        Log::info('Gerou token');
        Log::info('token:', ['token'=>$token]);

        return $this->respondWithToken($token);
    }

config/auth.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session"
    |
    */

    'guards' => [
        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that each reset token will be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the amount of seconds before a password confirmation
    | times out and the user is prompted to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => 10800,

];

Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array<int, class-string|string>
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\Cors::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            //\App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array<string, class-string|string>
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,
        'auth.api' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}

User.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

  /**
     * Especifica o nome da tabela associada a este modelo.
     *
     * @var string
     */
    protected $table = 'USUARIO';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'usu_nome',
        'usu_senha',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'usu_senha',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }

    /**
     * Sobrescreve o método para autenticação usando 'usu_nome' ao invés de 'email'.
     *
     * @return string
     */
    public function getAuthIdentifierName()
    {
        return 'usu_nome';
    }

    /**
     * Sobrescreve o método de senha para usar 'usu_0senha'.
     *
     * @return string
     */
    public function getAuthPassword()
    {
        return $this->usu_senha;
    }
}

Solution

  • I got it! It turns out the function bellow in my User.php was not supposed to be there. This function is only used when the primary key of my table is not ID, which is not my case. So I removed the function and it worked.

    // public function getAuthIdentifierName()
        // {
        //     return 'usu_nome';
        // }