php Laravel Passport 密码授予 - 客户端身份验证失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39572957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Passport Password Grant - Client authentication failed
提问by Kanav
After hearing a lot about laravel passport, i thought of implementing it into my new project where my requirement is to create an API that'll be used in a mobile app.
在听说了很多关于 laravel 护照的信息后,我想将它实施到我的新项目中,我的要求是创建一个将在移动应用程序中使用的 API。
So my mobile app is a client
, which will further have its users.
所以我的移动应用程序是一个client
,它将进一步拥有它的用户。
I followed the steps mentioned by Taylorand also read about it here. In a nutshell I followed these steps:
我遵循了Taylor 提到的步骤,并在此处阅读了相关内容。简而言之,我遵循了以下步骤:
- Installed
laravel/passport
. - Created a website user.
- Generated passport keys
php artisan passport:install
- Generated
client_id
andclient_secret
usingphp artisan passport:client
- Added
redirection
andcallback
routes inweb.php
- Authorized the user and got the final access token.
- 已安装
laravel/passport
。 - 创建了一个网站用户。
- 生成的护照密钥
php artisan passport:install
- 生成
client_id
和client_secret
使用php artisan passport:client
- 添加
redirection
和callback
路由web.php
- 授权用户并获得最终访问令牌。
Then I tried calling api/user
( with Header Authorization
containing value Bearer eyJ0eXAiOiJKV1...(token)
然后我尝试调用api/user
( with Header Authorization
contains valueBearer eyJ0eXAiOiJKV1...(token)
I received the data. Pretty simple and neat.
我收到了数据。非常简单和整洁。
But my app users won't have these details. So I thought of configuring Password Grant Tokenswhich fits perfectly in my requirement.
但是我的应用程序用户不会有这些详细信息。所以我想到了配置完全符合我的要求的密码授予令牌。
Now starts the real headache. I've been trying to set this up for the last 3 days and continuously getting
现在开始真正的头痛。过去 3 天我一直在尝试设置它并不断获得
{"error":"invalid_client","message":"Client authentication failed"}
I've tried almost every guide I followed online: Redirection Issues, Add Atleast One Scope Solution, P100Y Issueetc.
我已经尝试了几乎所有我在网上遵循的指南:重定向问题、添加至少一个范围解决方案、P100Y 问题等。
But I'm still getting invalid client
error. Here's what I'm passing through POSTMAN to oauth/token
:
但我仍然收到invalid client
错误。这是我通过邮递员传递给oauth/token
:
{
"grant_type": "password,"
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
"username": "[email protected],"
"password": "123456,"
"scope": ""
}
Any help would be appreciated.
任何帮助,将不胜感激。
采纳答案by Shahzaib Sheikh
Check your credentials first if they are correct, Secondly check your model table which uses \Laravel\Passport\HasApiTokens
trait that whether it contains email
column, because by default it is used to identify user when validating credentials. if your table has username
column or any other column which is used in validating credentials you must define a function findForPassport
in that model. like this,
首先检查您的凭据是否正确,然后检查您的模型表,该表使用\Laravel\Passport\HasApiTokens
它是否包含email
列的特征,因为默认情况下它用于在验证凭据时识别用户。如果您的表具有username
用于验证凭据的列或任何其他列,您必须findForPassport
在该模型中定义一个函数。像这样,
public function findForPassport($username) {
return self::where('username', $username)->first(); // change column name whatever you use in credentials
}
I use username and password column to validate a user,
in {project_directory}\vendor\laravel\passport\src\Bridge\UserRepository.php
我使用用户名和密码列来验证用户,在 {project_directory}\vendor\laravel\passport\src\Bridge\UserRepository.php
this function validates your credentials,
此功能验证您的凭据,
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());
}
notice the second if statement and you will get to know what is happening there.
注意第二个 if 语句,你会知道那里发生了什么。
hope this help :)
希望这有帮助:)
回答by Andre F.
This might help point you in the right direction because we're implementing the password grant ourselves.
这可能有助于为您指明正确的方向,因为我们正在自己实施密码授予。
1 - On your step 4 instead of running this:
1 - 在你的第 4 步而不是运行这个:
php artisan passport:install
run the following to create your password grant Client:
运行以下命令来创建您的密码授权客户端:
php artisan passport:client --password
The above command will give a followup question to set the name of your Password Grant Client. Be sure to get the id and secret of this new record in your database.
上面的命令将给出一个后续问题来设置您的密码授予客户端的名称。请务必在您的数据库中获取此新记录的 ID 和密码。
2 - Your POSTMAN Post request object should be wrapped inside an object similar to the following:
2 - 您的 POSTMAN Post 请求对象应包含在类似于以下内容的对象中:
'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:
2016 年 10 月 12 日更新 1:
On further investigation of this issue I ran into the exact same spot you're at and was forced to dive into the rabbit hole of passport.
在进一步调查这个问题时,我遇到了你所在的完全相同的地方,并被迫潜入护照的兔子洞。
Currently from what I'm seeing the system has set the client identifier as 'authorization_code' when it needs to be 'password'. I'm researching how to resolve this issue you're having as I've ran into it too. I will post code to help people follow along where I've been and what I've been doing but it's 2:40 am right now so I need some sleep.
目前,从我所看到的系统已将客户端标识符设置为“authorization_code”,当它需要“密码”时。我正在研究如何解决您遇到的这个问题,因为我也遇到过。我将发布代码以帮助人们了解我去过的地方和我一直在做的事情,但现在是凌晨 2:40,所以我需要休息一下。
Update 2 10/12/2016
更新 2 10/12/2016
Been debugging the issue for 7 hours now. There is a method within passport that validates the client. This method takes the inputs you've added in the object (mentioned above) and attempts to get the Client Entity through a client repository class based on what you've passed in. If a Client is found it will then be checked to see if an instance of the Client Entity truly exists within the Client Entity Interface which LOOKS like it pulls in the Client's credentials from the database. However, there is a block of code which returns NULL From what I'm getting in my testing. ALL fields are being introduced properly so far but there seems to be a mix-up between the repository and the interface. Which is causing the error to be thrown.
现在已经调试了 7 个小时的问题。护照中有一种方法可以验证客户端。此方法采用您在对象中添加的输入(如上所述)并尝试根据您传入的内容通过客户端存储库类获取客户端实体。如果找到客户端,则将检查它是否客户端实体的实例确实存在于客户端实体接口中,它看起来像是从数据库中提取客户端的凭据。但是,有一段代码会根据我在测试中得到的结果返回 NULL。到目前为止,所有字段都被正确引入,但存储库和界面之间似乎存在混淆。这导致错误被抛出。
In the end I feel I'm getting close to solving this issue. Your patience is greatly appreciated. =)
最后,我觉得我离解决这个问题越来越近了。非常感谢您的耐心等待。=)
Update 3 10/12/2016
更新 3 10/12/2016
After a long period of debugging I've found the initial problem. There were fields that weren't matching up. In short, it's a setup issue.
经过长时间的调试,我发现了最初的问题。有些字段不匹配。简而言之,这是一个设置问题。
SO
所以
The solution in this case is:
这种情况下的解决办法是:
DOUBLE CHECK ALL FIELDS In the databasewith ALLcredentials being passed in. Right down to periods, dashes, spaces passwords, client id, client secret, VALID redirect URIs/URLs, grant_types, and scopes (if you're using them):
仔细检查各个领域在数据库与所有的凭据传递一直到句点,破折号,空格口令,客户端ID,客户端密钥,有效的重定向的URI /网址,grant_types和范围(如果你使用它们):
Make sure the client in the database has an ENUM of 1 under the "password_client" column, if not you need to create one using the mentioned php artisan command above, which I'll reference here:
确保数据库中的客户端在“password_client”列下的 ENUM 为 1,如果不是,则需要使用上面提到的 php artisan 命令创建一个,我将在此处引用:
php artisan passport:client --password
Make sure the secret you're passing in matches what is listed for that client in your database character for character
确保您传入的机密与您的数据库中为该客户端列出的内容相匹配
Make sure the id you're passing matches and is of an integer data type.
确保您传递的 id 匹配并且是整数数据类型。
Make sure there is a name of some sort for the client
确保客户端有某种名称
Do not worry about the user_id column when using password grants
使用密码授权时不要担心 user_id 列
make sure the route is correct
确保路线正确
Make sure the email your entering in (username) is an actual user inside of your users table within your database (or whatever table you customized the laravel 5.3 system to accept as your users table, I will add a link on how to customize laravel 5.3 system to accept a different users table as default if any need it).
确保您输入的电子邮件(用户名)是您数据库中用户表中的实际用户(或您自定义 laravel 5.3 系统接受为用户表的任何表,我将添加有关如何自定义 laravel 5.3 的链接系统在需要时接受不同的用户表作为默认值)。
Make sure the grant_type is spelled correctly
确保 grant_type 拼写正确
Make sure you're set up to accept the response bearer token (meaning the access_token and refresh_token).
确保您已设置为接受响应承载令牌(即 access_token 和 refresh_token)。
Other than that, the initial steps I've outlined in the above part of this Answer should put you back on the right track. There are others here who did mention some similar steps that are helpful but address the same error that is related to a seperate issue as well (which I'm sure is a result of a setup issue related to their specific system setup).
除此之外,我在本答案的上述部分中概述的初始步骤应该会让您回到正确的轨道上。这里还有其他人确实提到了一些有用的类似步骤,但也解决了与单独问题相关的相同错误(我确定这是与其特定系统设置相关的设置问题的结果)。
I hope this helps though.
我希望这会有所帮助。
回答by Emiliano Díaz
Have yo try running php artisan config:cache
after all the passport commands.
您是否尝试php artisan config:cache
在所有通行证命令之后运行。
回答by Muzafar Ali
use the below code to generate an access token, it has worked for me before:
使用以下代码生成访问令牌,它以前对我有用:
$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);
回答by André
I had the same issue, and got fixed by setting basic.auth headers, with client_id as username and secret as password.
我遇到了同样的问题,并通过设置 basic.auth 标头来解决,其中 client_id 作为用户名,secret 作为密码。
Then it worked fine.
然后它工作得很好。
回答by Andy Parinas
Check thoroughly the Grant Type.
彻底检查授予类型。
{
"grant_type": "password",
"client_id": 2,
"client_secret":
"username": ,
"password":
"scope": ""
}
In the above example, it says password. Now check the table: oauth_clientsand make sure that the value of column password_client = 1
在上面的例子中,它说密码。现在检查表:oauth_clients并确保列的值password_client = 1
or look for the entry with the password_client = 1
或查找带有 password_client = 1
回答by Raymond Lagonda
{"error":"invalid_client","message":"Client authentication failed"}
means that the client_id and client_secret you're currently sending is one of the following:
意味着您当前发送的 client_id 和 client_secret 是以下之一:
- client_id and client_secret being sent is not registeredin your oauth server
- client_id and client_secret being sent is not of the grant typethat you specify in the post body
- 正在发送的 client_id 和 client_secret未在您的 oauth 服务器中注册
- 发送的 client_id 和 client_secret不是您在帖子正文中指定的授权类型
For me, the password_client column value for that particular client was 0. i manually changed it to 1 but it didn't help. – Kanav Oct 4 at 3:25
对我来说,该特定客户端的 password_client 列值为 0。我手动将其更改为 1,但没有帮助。– Kanav 10 月 4 日 3:25
As I read your comment to some of the answer makes this one is obvious that you use the wrong type of client_id and client_secret for your password grant flow, so your case was the latter. You can verify that by finding the entry in oauth_clients table for your supplied client_id and client_secret
当我阅读您对某些答案的评论时,很明显您对密码授予流程使用了错误类型的 client_id 和 client_secret,因此您的情况是后者。您可以通过在 oauth_clients 表中为您提供的 client_id 和 client_secret 查找条目来验证这一点
"grant_type": "password,"
"client_id": "3,"
"client_secret": "8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g,"
SELECT * FROM oauth_clients WHERE id = 3 AND secret = '8BUPCSyYEdsgtZFnD6bFG6eg7MKuuKJHLsdW0k6g' AND password_client=1;
in your oauth_clients table to check that whether your supplied client_id and client_secret exists for password grant flowin your oauth server. And also you don't manually change the type of client by simply switching the value of that column, you have to create a new clientfor password grant type.
在您的 oauth_clients 表中检查您提供的 client_id 和 client_secret 是否存在用于oauth 服务器中的密码授予流程。而且您不需要通过简单地切换该列的值来手动更改客户端的类型,您必须为密码授予类型创建一个新的客户端。
php artisan migrate
This command will migrate the laravel/passport migration file to generate two default clients for each type that laravel/passport currently supported. You can also create a client for password grant flow with
该命令将迁移 laravel/passport 迁移文件,为 laravel/passport 当前支持的每种类型生成两个默认客户端。您还可以为密码授予流程创建一个客户端
php artisan passport:client --password
When you have a new client for password grant type, try POSTing again to /oauth/token to generate a token with your new generated client_id and client_secret
当您有密码授予类型的新客户端时,请尝试再次 POST 到 /oauth/token 以使用新生成的 client_id 和 client_secret 生成令牌
回答by Krutika Modi
I was also facing the same issue , i got the solution from this link. Please check that. https://github.com/laravel/passport/issues/71
我也遇到了同样的问题,我从这个链接中得到了解决方案。请检查一下。 https://github.com/laravel/passport/issues/71
It says that : You make a call to /oauth/token just like you always would to get your token. But do so with a grant_type of custom_request. You'll need to add a byPassportCustomRequest($request)method to your User model(or whatever model you have configured to work with Passport). That method will accept a Illuminate\Http\Request and return the user model if you are able to authenticate the user via the request, or it will return null.
它说:您像往常一样调用 /oauth/token 来获取令牌。但是使用custom_request 的grant_type 这样做。您需要将byPassportCustomRequest($request)方法添加到您的User 模型(或您配置为使用 Passport 的任何模型)。如果您能够通过请求对用户进行身份验证,该方法将接受 Illuminate\Http\Request 并返回用户模型,否则它将返回 null。
回答by Cheran
if you tried everything and still it's not working means try this solution!! just give scope *.
如果您尝试了所有方法但仍然无法正常工作意味着尝试此解决方案!只给范围*。
$query = http_build_query([
'client_id' => 1,
'redirect_uri' => 'http://localhost:3000/callback',
'response_type' => 'code',
'scope' => '*'
]);
in my case this is the solution. I have checked
就我而言,这就是解决方案。我检查过
回答by fennelon
I had the same problem. When you execute php artisan passport:install
it issues you with two types of secrets, one for CLIENT grant type, and other for PASSWORD grant type.
我有同样的问题。当您执行php artisan passport:install
它时,会向您发出两种类型的机密,一种用于 CLIENT 授权类型,另一种用于 PASSWORD 授权类型。
I was using the CLIENT secret to issue PASSWORD tokens. Once I changed that up, I was able to generate the access_token
and refresh_token
normally.
我使用 CLIENT 密钥来发布 PASSWORD 令牌。一旦我改变了它,我就能够正常生成access_token
和refresh_token
。