Estoy configurando una ruta de autenticación con mi API. Estoy usando laravel 5.5 con tymondesigns / jwt-auth 1.0.0-rc.1 y Postman para interactuar con la API.

La ruta / método de autenticación parece funcionar:

/**
 * Authenticates a json request, generating a token.
 *
 * @param Request $request
 * @return JsonResponse
 */
public function authenticate(Request $request)
{
    // grab credentials from the request
    $credentials = $request->only('email', 'password');

    try {
        // attempt to verify the credentials and create a token for the user
        if (! $token = JWTAuth::attempt($credentials)) {
            return response()->json(
                [
                    'error' => 'Invalid credentials.',
                    'detail' => 'Please use your email and password to generate a token.'
                ],
                401);
        }
    } catch (JWTException $e) {
        // something went wrong whilst attempting to encode the token
        return response()->json(
            [
                'error' => 'Could not create token',
                'detail' => 'There was an internal problem and your token could not be created.'
            ], 500
        );
    }

    // all good so return the token
    return response()->json(compact('token'));
}

Una solicitud de publicación API de Postman devuelve (lo que parece ser) una respuesta válida, por ejemplo:

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4"
}

Para comenzar, para propósitos de prueba básicos, estoy alimentando esto a una acción usando GET, con el siguiente sufijo:

?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4

Para probar esto, si hago lo siguiente:

public function globalObjects(Request $request): JsonResponse {
    var_dump(JWTAuth::parseToken()->authenticate(), JWTAuth::getToken()); exit;

   // ... later code that never gets reached
}

Me sale lo siguiente:

bool(false) object(Tymon\JWTAuth\Token)#809 (1) { ["value":"Tymon\JWTAuth\Token":private]=> string(384) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4" }

.. como en:

  • Recibo el token
  • No encuentra a la usuaria

Artículos de nota:

  • mi clave principal es id, pero es un UUID, entonces un binario (16) ... y por lo tanto:
  • Configuré el identificador para que sea: 'identificador' => 'correo electrónico'

Siguiente solicitud: aquí \config\jwt.php

return [
    'secret' => env('JWT_SECRET', 'AqAWUTYISA56lrl2vcRtZQn4M4zk9onl'),
    'ttl' => 60,
    'refresh_ttl' => 20160,
    'algo' => 'HS256',
    'user' => 'App\User',
    'identifier' => 'email',
    'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'],
    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
    'providers' => [
        'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',
        'jwt' => 'Tymon\JWTAuth\Providers\JWT\Namshi',
        'auth' => 'Tymon\JWTAuth\Providers\Auth\Illuminate',
        'storage' => 'Tymon\JWTAuth\Providers\Storage\Illuminate',

    ],

];

Gracias

0
elb98rm 18 oct. 2017 a las 14:23

3 respuestas

La mejor respuesta

La respuesta es: "esto no es compatible con esta función en su estado actual sin extenderla usted mismo".

Espero que esto ayude a cualquier otra persona que use UUID como clave principal. No puede hacerlo sin editar los artículos del proveedor o extender ... Pero, esta es una solución fácil.

Voy a plantear esto con el autor del paquete y espero encontrar una solución más permanente. Sin embargo, aquí hay una solución alternativa:

Fondo:

  • Los UUID se almacenan como columnas binarias (16) id en la base de datos.
  • Esto no es legible para humanos / texto amigable.
  • Para evitar esto, existen campos id_text como campos mysql generados automáticamente
  • nota: nunca deberías buscar usando estos (enfatiza mucho el db)
  • Estos son legibles por texto y, por lo tanto, se pueden usar fácilmente en formularios, etc.
  • Creé un UuidHelper para permitir una traducción fácil

Problema en JWT:

  • La función de autenticación intenta decodificar un id_text como id
  • obviamente, esto siempre falla

En el archivo \vendor\tymon\jwt-auth\src\JWTAuth.php

/**
 * Authenticate a user via a token.
 *
 * @return \Tymon\JWTAuth\Contracts\JWTSubject|false
 */
public function authenticate()
{
    $id_text = $this->getPayload()->get('sub');

    $uuid_helper = new UuidHelper();
    $id = $uuid_helper->textIdToId($id_text);

    if (! $this->auth->byId($id)) {
        return false;
    }

    return $this->user();
}

La documentación no es la más clara, por lo que supuse que 'identifier' => 'email' evitaría este problema ... resulta que no lo hace. Voy a retroalimentar esto a los autores.

Modificar el núcleo fue solo un ejercicio ... Estoy bastante seguro de que esta clase puede ampliarse, y lo intentaré en breve. Editar fuentes es, por supuesto, subóptimo en la mayoría de los casos.

Sin embargo, espero que esta excavación ayude a las personas a comprender el problema.

0
elb98rm 18 oct. 2017 a las 21:29

Su token se recibió pero no se analizó correctamente, debe verificar el éxito del análisis de token.

if (! $auth = JWTAuth::parseToken();) {
    throw Exception('JWTAuth unable to parse token from request');
}
dd(\Auth::id());

Le sugiero que vaya a su kernel.php y agregue las siguientes líneas en la matriz protegida $ route Middleware

'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',

Luego vaya a sus rutas y úsela como middleware para autenticarse así

 Route::group(['middleware' => 'jwt.auth'], function () {
  // Your routes here that you want to protect
        Route::get('foo', function () {
        return 'Hello World';
             });
     ]):

enter image description here

0
Zulfiqar Tariq 18 oct. 2017 a las 15:56

Aquí está la solución que uso en mi API funciona perfectamente bien.

Primero reescribe la clase Tymon\JWTAuth\Providers\Auth\Illuminate::class

<?php


namespace Scryba\Code\Laravel\Providers\Auth\Jwt;

use Tymon\JWTAuth\Contracts\Providers\Auth;
use Illuminate\Contracts\Auth\Guard as GuardContract;

class Illuminate implements Auth
{
/**
 * The authentication guard.
 *
 * @var \Illuminate\Contracts\Auth\Guard
 */
protected $auth;

/**
 * Constructor.
 *
 * @param  \Illuminate\Contracts\Auth\Guard  $auth
 *
 * @return void
 */
public function __construct(GuardContract $auth)
{
    $this->auth = $auth;
}

/**
 * Check a user's credentials.
 *
 * @param  array  $credentials
 *
 * @return bool
 */
public function byCredentials(array $credentials)
{
    return $this->auth->once($credentials);
}

/**
 * Authenticate a user via the id.
 *
 * @param  mixed  $id
 *
 * @return bool
 */
public function byId($id)
{
    //you can see i added hex2bin($id)because i save my UUID primary key as 
    //binary(16)
    return $this->auth->onceUsingId(hex2bin($id));
}

/**
 * Get the currently authenticated user.
 *
 * @return mixed
 */
public function user()
{
    return $this->auth->user();
}
}

Luego actualice el archivo \config\jwt.php a

 'providers' => [

    /*
    |--------------------------------------------------------------------------
    | JWT Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to create and decode the tokens.
    |
    */

    'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class,

    /*
    |--------------------------------------------------------------------------
    | Authentication Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to authenticate users.
    |
    */

    //'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
    'auth' => Scryba\Code\Laravel\Providers\Auth\Jwt\Illuminate::class,

    /*
    |--------------------------------------------------------------------------
    | Storage Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to store tokens in the blacklist.
    |
    */

    'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,

],

En mi archivo de rutas

////// Protected methods (requires Authenticatication)
        $api->group(
            [
                'middleware' => ['api.auth'],
                'providers' => ['jwt'],

            ],function($api){

        $api->resource('cars', 'CarController', ['only' => [
            'index' ,'show'
        ]]);

        });

Entonces, en su caso, deje el archivo fuente \ vendor \ tymon \ jwt-auth \ src \ JWTAuth.php como está y escriba su código como se muestra a continuación en su clase personalizada, si corresponde.

/**
* Authenticate a user via the id.
*
* @param  mixed  $id
*
* @return bool
*/
public function byId($id)
{
   $id_text = $this->getPayload()->get('sub');

   $uuid_helper = new UuidHelper();
   $id = $uuid_helper->textIdToId($id_text);

  return $this->auth->onceUsingId($id);
}
2
scryba 3 nov. 2017 a las 20:29