web-dev-qa-db-fra.com

Laravel Passport Password Grant - L'authentification du client a échoué

Après avoir beaucoup entendu parler du passeport laravel, j'ai envisagé de le mettre en œuvre dans mon nouveau projet, où mon objectif est de créer une API qui sera utilisée dans une application mobile.

Donc, mon application mobile est une client, qui aura plus loin ses utilisateurs.

J'ai suivi les étapes mentionnées par Taylor et également lu à ce sujet ici . En bref, j'ai suivi ces étapes:

  1. laravel/passport installé.
  2. Créé un utilisateur du site.
  3. Clés de passeport générées php artisan passport:install
  4. client_id et client_secret générés à l'aide de php artisan passport:client
  5. Ajout de routes redirection et callback dans web.php 
  6. Autorisé l'utilisateur et obtenu le jeton d'accès final.

Ensuite, j'ai essayé d'appeler api/user (avec en-tête Authorization contenant la valeur Bearer eyJ0eXAiOiJKV1...(token)

J'ai reçu les données. Assez simple et soigné.

Mais les utilisateurs de mon application n'auront pas ces détails. J'ai donc pensé à configurer Mot de passe Grant Tokens qui correspond parfaitement à mes besoins. 

Maintenant commence le vrai mal de tête. J'essaie de le configurer depuis 3 jours et je continue à me faire

{"error":"invalid_client","message":"Client authentication failed"}

J'ai essayé presque tous les guides que j'ai suivis en ligne: Problèmes de redirection , Ajoutez au moins une solution Scope , Problème P100Y etc.

Mais je reçois toujours l'erreur invalid client. Voici ce que je fais passer par POSTMAN à oauth/token:

{
    "grant_type": "password,"
    "client_id": "3,"
    "client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
    "username": "[email protected],"
    "password": "123456,"
    "scope": ""
}

Toute aide serait appréciée.

20
Kanav

Vérifiez d'abord vos informations d'identification si elles sont correctes. Ensuite, vérifiez votre table de modèle qui utilise le trait \Laravel\Passport\HasApiTokens pour savoir si elle contient ou non la colonne email, car elle sert par défaut à identifier l'utilisateur lors de la validation des informations d'identification. Si votre table a la colonne username ou toute autre colonne utilisée pour la validation des informations d'identification, vous devez définir une fonction findForPassport dans ce modèle. comme ça,

public function findForPassport($username) {
       return self::where('username', $username)->first(); // change column name whatever you use in credentials
    }

J'utilise la colonne nom d'utilisateur et mot de passe pour valider un utilisateur, In {project_directory}\vendor\laravel\passport\src\Bridge\UserRepository.php

cette fonction valide vos identifiants,

public function getUserEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity)
    {
        if (is_null($model = config('auth.providers.users.model'))) {
            throw new RuntimeException('Unable to determine user model from configuration.');
        }

        if (method_exists($model, 'findForPassport')) { // if you define the method in that model it will grab it from there other wise use email as key 
            $user = (new $model)->findForPassport($username);
        } else {
            $user = (new $model)->where('email', $username)->first();
        }

        if (! $user || ! $this->hasher->check($password, $user->password)) {
            return;
        }

        return new User($user->getAuthIdentifier());
    }

remarquez la deuxième déclaration if et vous saurez ce qui s'y passe.

espérons que cette aide :)

15
Shahzaib Sheikh

Cela pourrait vous aider à aller dans la bonne direction car nous appliquons nous-mêmes l’octroi de mot de passe.

1 - Sur votre étape 4 au lieu d’exécuter ceci:

php artisan passport:install

exécutez ce qui suit pour créer votre client de mot de passe:

php artisan passport:client --password

La commande ci-dessus donnera une question suivante pour définir le nom de votre client d'attribution de mot de passe. Assurez-vous d’obtenir l’identifiant et le secret de ce nouvel enregistrement dans votre base de données. 

2 - Votre objet de requête POSTMAN Post doit être placé dans un objet similaire à celui-ci:

'form_params' => [
    'grant_type' => 'password',
    'client_id' => 'my_client-id',
    'client_secret' => 'my_client-secret',
    'username' => 'username or email', <-pass through variables or something
    'password' => 'my-user-password', <- pass through variables or something
    'scope' => '',
],

Update 1 10/12/2016:

Après une enquête plus approfondie sur ce problème, je suis tombé sur le même endroit où vous vous trouvez et j'ai été forcé de plonger dans le trou du passeport pour lapin.

Actuellement, d'après ce que je vois, le système a défini l'identifiant du client comme "code_autorisation" lorsqu'il doit être "mot de passe". Je cherche des solutions pour résoudre le problème que vous rencontrez, car je l'ai également rencontré. Je publierai du code pour aider les gens à suivre où je suis allé et ce que je faisais, mais il est 2 h 40 maintenant, alors j'ai besoin de sommeil.

Update 2 10/12/2016

Debugging le problème depuis 7 heures maintenant. Il existe une méthode dans le passeport qui valide le client. Cette méthode utilise les entrées que vous avez ajoutées à l'objet (mentionné ci-dessus) et tente d'obtenir l'entité cliente via une classe de référentiel client en fonction de ce que vous avez transmis. Si un client est trouvé, il sera ensuite vérifié si une instance de l'entité client existe réellement dans l'interface de l'entité client, ce qui lui permet de récupérer les informations d'identification du client à partir de la base de données. Cependant, il existe un bloc de code qui renvoie la valeur NULL. TOUS les champs ont été introduits correctement jusqu'à présent, mais il semble y avoir une confusion entre le référentiel et l'interface. Ce qui provoque l'erreur à être jeté.

En fin de compte, je sens que je suis sur le point de résoudre ce problème. Votre patience est grandement appréciée. =)

Mise à jour 3 10/12/2016

Après une longue période de débogage, j'ai trouvé le problème initial. Il y avait des champs qui ne correspondaient pas. En bref, c'est un problème d'installation.

SO

La solution dans ce cas est:

DOUBLE VÉRIFIER TOUS LES ZONES Dans la base de données avecTOUSinformations d'identification transmises. Jusqu'à des points, des tirets, des mots de passe d'espaces, un identifiant client, un secret client, des URI/URLs de redirection VALID, des types de subvention et des portées (si vous les utilisez): 

Assurez-vous que le client dans la base de données a un ENUM de 1 dans la colonne "password_client", sinon vous devez en créer un en utilisant la commande php artisan mentionnée ci-dessus, à laquelle je ferai référence ici:

php artisan passport:client --password

Assurez-vous que le secret que vous transmettez correspond à ce qui est répertorié pour ce client dans votre base de données, caractère pour caractère

Assurez-vous que l'identifiant que vous transmettez correspond et qu'il s'agit d'un type de données entier.

Assurez-vous qu'il y a un nom quelconque pour le client

Ne vous inquiétez pas de la colonne user_id lorsque vous utilisez les attributions de mot de passe

assurez-vous que la route est correcte

Assurez-vous que l'email dans lequel vous entrez (nom d'utilisateur) est un utilisateur réel dans votre tableau d'utilisateurs dans votre base de données (ou quel que soit le tableau que vous avez personnalisé pour que le système laravel 5.3 soit accepté comme tableau d'utilisateurs, je vais ajouter un lien sur la façon de personnaliser laravel 5.3. système à accepter une table d'utilisateurs par défaut si nécessaire).

Assurez-vous que le grant_type est orthographié correctement

Assurez-vous que vous êtes configuré pour accepter le jeton porteur de réponse (c'est-à-dire access_token et refresh_token).

En dehors de cela, les étapes initiales que j'ai décrites dans la partie ci-dessus de cette réponse devraient vous remettre sur la bonne voie. Il y en a d'autres ici qui ont mentionné certaines étapes similaires qui sont utiles mais qui corrigent la même erreur qui est liée à un problème séparé (qui, j'en suis sûr, est le résultat d'un problème d'installation lié à la configuration de leur système spécifique). 

J'espère que cela aide cependant.

9
Andre F.

Essayez de lancer php artisan config:cache après toutes les commandes de passeport.

2
Emiliano Díaz

utilisez le code ci-dessous pour générer un jeton d'accès, cela a déjà fonctionné pour moi auparavant:

$request->request->add([
      'client_id' => '2',
      'client_secret' => 'm3KtgNAKxq6Cm1WC6cDAXwR0nj3uPMxoRn3Ifr8L',
      'grant_type' => 'password',
      'username' => '[email protected]',
      'password' => 'pass22'
    ]);
    $tokenRequest = $request->create('/oauth/token', 'POST', $request->all());

    $token =  \Route::dispatch($tokenRequest);
1
Muzafar Ali

J'ai eu le même problème et j'ai été corrigé en définissant les en-têtes basic.auth, avec client_id comme nom d'utilisateur et secret comme mot de passe.

Ensuite, cela a bien fonctionné.

1
André

J'ai réussi à obtenir le passeport Laravel - Password_Grant_Token via RESTED (service semblable à POSTMAN) sans aucun contrôleur ou middleware supplémentaire. Voici comment j'ai réussi à le faire!

Installez l'auth-Scaffolding par défaut dans laravel doc's here
Installez le passeport doc est ici
Enregistrer un utilisateur via auth-échafaudage
Goto RESTED ou POSTMAN, ou tout autre service similaire
Vérifiez les données dans la table oauth_clients pour vos form_params
Avec RESTED via Request_body_form_data, les en-têtes n'écrivent pas vos formulaires_params et envoient une demande POST à */oauth/token (url complète requise).

(les paramètres de formulaire requis sont grant_type, client_id, client_secret, nom d'utilisateur et mot de passe)

Vous devriez obtenir en retour un objet avec 4 clés (token_type, expires_in, access_token & refresh_token) et un statut 200 OK.

Si tout était réussi jusqu'à présent ...

Ouvrez une autre fenêtre RESTED:

Envoyez une requête GET à/api/user (à nouveau, une URL complète est requise) Dans les en-têtes, écrivez 2 paires nom-valeur (Accept => application/json, Authorization => Bearer ACCESS_TOKEN_GOTTEN_IN_PREVIOUS_REQUEST (to/oauth/token)

Et ça devrait être ça. Vous devriez obtenir un objet utilisateur en réponse de/api/user.

0
fj.agmedia

Vérifiez soigneusement le type de subvention.

{
    "grant_type": "password",
    "client_id": 2,
    "client_secret": 
    "username": ,
    "password": 
    "scope": ""
}

Dans l'exemple ci-dessus, il est dit mot de passe. Maintenant, vérifiez la table: oauth_clients Et assurez-vous que la valeur de la colonne password_client = 1

ou cherchez l'entrée avec le password_client = 1

0
Andy Parinas
{"error":"invalid_client","message":"Client authentication failed"}

signifie que les informations client_id et client_secret que vous envoyez actuellement sont l'une des suivantes:

  1. client_id et client_secret envoyé est non enregistré sur votre serveur oauth
  2. client_id et client_secret envoyés sont pas du type de subvention que vous spécifiez dans le corps de publication

Pour moi, la valeur de la colonne password_client pour ce client particulier était 0. je l'ai changé manuellement à 1 mais cela n'a pas aidé. - Kanav 4 octobre à 3:25

Lorsque je lis votre commentaire, certaines des réponses font que celui-ci est évident que vous utilisez les types client_id et client_secret incorrects pour votre flux d’octroi de mot de passe; votre cas est donc le dernier. Vous pouvez le vérifier en recherchant l'entrée dans la table oauth_clients pour votre client_id et client_secret fournis.

"grant_type": "password,"    
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"

SELECT * FROM oauth_clients WHERE id = 3 AND secret = '8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g' AND password_client=1;

dans votre table oauth_clients pour vérifier si les identificateurs client_s et client_secret fournis pour le flux d'octroi de mot de passe sur votre serveur oauth. Et aussi vous ne changez pas manuellement le type de client en changeant simplement la valeur de cette colonne, vous devez créer un nouveau client pour le type d'octroi de mot de passe.

php artisan migrate

Cette commande migrera le fichier de migration laravel/passport pour générer deux clients par défaut pour chaque type pris en charge par laravel/passport. Vous pouvez également créer un client pour le flux d’octroi de mot de passe avec

php artisan passport:client --password

Lorsque vous avez un nouveau client pour le type d’octroi de mot de passe, essayez à nouveau de POST à ​​/ oauth/token pour générer un jeton avec vos nouveaux client_id et client_secret générés.

0
Raymond Lagonda

Je faisais également face au même problème, j'ai eu la solution de ce lien. Veuillez vérifier que . https://github.com/laravel/passport/issues/71

Il dit ce qui suit: Vous appelez/oauth/token comme vous le feriez toujours pour récupérer votre jeton. Mais faites-le avec un grant_type de custom_request. Vous devez ajouter une méthode byPassportCustomRequest ($ request) à votre modèle User (ou à tout modèle que vous avez configuré pour fonctionner avec Passport). Cette méthode acceptera une requête Illuminate\Http\Request et renverra le modèle utilisateur si vous êtes en mesure d'authentifier l'utilisateur via la requête, ou la valeur null.

0
Krutika Modi

Essayez de créer un nouveau mot de passe client en utilisant un passeport artisan php: client --password Alors très probablement, un utilisateur ne sera pas attribué à ce mot de passe client. Editez la ligne de la base de données et ajoutez-y un ID utilisateur existant.

{
    "grant_type": "password,"
    "client_id": "" <- edited and added user id
    "client_secret": "8BU......," <- new secret
    "username": "[email protected]," <- email of above added user id
    "password": "123456,"<- password 
    "scope": ""
}

J'espère que vous pourrez obtenir un jeton maintenant

0
cody 007

Vérifiez l'URL de redirection/rappel lorsque le client est configuré sur le serveur de passeports. Vérifiez l'entrée où vous obtenez l'ID client et le secret à partir duquel l'URL de redirection est correcte. 

J'avais la même erreur et j'ai trouvé que l'URL de redirection n'était pas correcte. 

Il doit être pointé sur la route/callback (dans les exemples donnés par Taylor)

0
Dan at TYT

si vous avez tout essayé et que cela ne fonctionne toujours pas, essayez cette solution !!.

$query = http_build_query([
    'client_id' => 1,
    'redirect_uri' => 'http://localhost:3000/callback',
    'response_type' => 'code',
    'scope' => '*'
]);

dans mon cas c'est la solution. j'ai vérifié

0
Cheran