Laravel 的 5.3 通行证和 API 路由 [英] Laravel's 5.3 passport and api routes

查看:29
本文介绍了Laravel 的 5.3 通行证和 API 路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Laravel Framework 5.3.9 版,全新下载没有通过作曲家添加任何内容(除了 "laravel/passport": "^1.0").

我做了

我正在使用 Postman 访问 api/v1/users/register 路由,该路由具有 auth 中间件和以下 JSON application/json

<代码>{"grant_type": "authorization_code",client_id":5,"client_secet": "y5dvPIOxQJOjYn7w2zzg4c6TRrphsrNFWbG4gAUL"}

这当然会导致

{"error":"未经身份验证."}

说的太有道理了.出于纯粹的好奇,我将 /register 路由更改为:

Route::group(['中间件' =>[],], 功能 (){路线::组(['前缀' =>'用户','作为' =>'用户::',], 功能 (){//Route::get('/register', ['as' => 'register', 'uses' => 'ApiV1SocialController@register',]);Route::post('/register', ['as' => 'register', 'uses' => 'LaravelPassportHttpControllersAccessTokenController@issueToken',]);});});

使用与之前相同的 json.这导致 {"error":"invalid_client","message":"Client authentication failed"}.

我已经找到了处理vendor/leagueoauth2-server/src/Grant/AbstractGrant`.

$client 为空.现在这可能与 Passport 相关,也可能不相关,因为关于它的文档相当缺乏,并且通过一个包的怪物来追踪可能主要是由于我没有做正确的事情的错误的想法并没有让我感到震惊作为一个好主意,我别无选择.老实说,我什至不知道问题出在哪里.

真的,在这一点上,任何指向正确方向的东西都非常受欢迎.

问题部分是

解决方案

Laravel 5.3 Passport 的问题在于,与之前 lucadegasperi 提供的 OAuth 2.0 Server for Laravel 库不同,它没有 API 可以直接创建客户端.所以好像现在客户端只能通过前端制作.仅供参考,我们想仅将 laravel 护照用于我们的移动应用程序,因此在创建和注册用户时,我们将只有 EMAIL &密码,在某些情况下仅用于 Facebook 登录的 Facebook 用户 ID.因此,以下方法对我们的案例非常有效,可能因您的情况而异,但从长远来看可能会帮助您使用 Laravel 护照.

注意:在执行以下操作之前,假设您已在应用程序中启用密码授予.

所以我们在 laravel 5.3 上的项目解决方法如下:

  1. 在 oauth_clients 中,将 id 字段转换为普通字段,即将其作为主键删除,并将数据类型设为 varchar,以便我们可以将电子邮件地址存储为 client_ids,因为它们对于您的系统也是唯一的.在 Facebook 登录的情况下,我们将 Facebook 用户 ID 存储在此列中,这对于我们的每个客户来说也是唯一的.也适用于其他表,如:oauth_access_tokens、oauth_auth_codes &oauth_personal_access_clients 将 client_id 更改为 VARCHAR(255),以便它可以存储电子邮件地址或 Facebook 用户 ID.

  2. 现在转到您的模型并为 oauth_clients 表创建一个模型,以便您可以在创建用户时通过代码以编程方式创建客户端.

  3. 然后在你的 api.php 路由文件中添加以下路由:

    Route::post('/register-user', function (Request $request) {$name = $request->input('name');$email = $request->input('email'),$password = $request->input('password'),//保存新用户$user = AppUser::create(['名称' =>$姓名,'电子邮件' =>$电子邮件,'密码' =>bcrypt($password),]);//创建 oauth 客户端$oauth_client = AppOauthClient::create(['user_id' =>$user->id,'id' =>$电子邮件,'名称' =>$姓名,'秘密' =>base64_encode(hash_hmac('sha256',$password, 'secret', true)),'password_client' =>1、'personal_access_client' =>0,'重定向' =>'','撤销' =>0,]);返回 ['消息' =>'用户已成功创建.'];});

在上面的代码片段中,您必须注意,要生成 oauth_client 机密,您必须使用一些您觉得在您的应用程序中使用它时感觉舒适的强大加密公式.此外,使用相同的技术在您的移动应用上为相应的客户端/用户生成密钥.

  1. 现在您可以使用 laravel 护照提供的标准 POST API 通过使用以下参数的oauth/token"密码授权请求访问令牌:

    grant_type : '密码'client_id : '<用户注册的邮箱>'client_secret : '<从移动应用程序生成客户端密码>'username : '<用户注册的邮箱>'password : '<用户输入的密码>'scope : '<留空为默认值>'

  2. 上面会给你一个回复,如果一切正确,类似于:

    <代码>{"token_type": "承载",expires_in":3155673600,的access_token":eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3In0.eyJhdWQiOiJzaHVqYWhtQGdtYWlsLmNvbSIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3IiwiaWF0IjoxNDc4MTQ1NjMyLCJuYmYiOjE0NzgxNDU2MzIsImV4cCI6NDYzMzgxOTIzMiwic3ViIjoiMSIsInNjb3BlcyI6W119.dj3g9b2AdPCK-im5uab-01SP71S7AR96R0FQTKKoaZV7M5ID1pSXDlmZw96o5Bd_Xsy0nUqFsPNRQsLvYaOuHZsP8v9mOVirBXLIBvPcBc6lDRdNXvRidNqeh4JHhJu9a5VzNlJPm3joBYSco4wYzNHs2BPSxXuuD3o63nKRHhuUHB-HwjVxj2GDwzEYXdZmf2ZXOGRJ99DlWGDvWx8xQgMQtd1E9Xk_Rs6Iu8tycjBpKBaC24AKxMI6T8DpelnFmUbMcz-pRsgCWCF_hxv6FpXav3jr1CLhhT58_udBvXjQAXEbtHeB7W_oaMcaqezHdAeOWDcnqREZHsnXHtKt0JpymcTWBkS2cg7sJzy6P9mOGgQ8B4gb8wt44_kHTeWnokk4yPFRZojkHLVZb8YL6hZxLlzgV1jCHUxXoHNe1VKlHArdlV8LAts9pqARZkyBRfwQ8oiTL-2m16FQ_qGg-9vI0Suv7d6_W126afI3LxqDBi8AyqpQzZX1FWmuJLV0QiNM0nzTyokzz7w1ilJP2PxIeUzMRlVaJyA395zq2HjbFEenCkd7bAmTGrgEkyWM6XEq1P7qIC_Ne_pLNAV6DLXUpg9bUWEHhHPXIDYKHS-c3N9fPDt8UVvGI8n0rPMieTN92NsYZ_6OqLNpcm6TrhMNZ9eg5EC0IPySrrv62jE",refresh_token": BbwRuDnVfm7tRQk7qSYByFbQKK + shYPDinYA9 + Q5C/ovIE1xETyWitvq6PU8AHnI5FWb06Nl2BVoBwCHCUmFaeRXQQgYY/i5vIDEQ/TJYFLVPRHDc7CKILF0kMakWKDk7wJdl5J6k5mN38th4pAAZOubiRoZ + 2npLC7OSZd5Mq8LCBayzqtyy/QA5MY9ywCgb1PErzrGQhzB3mNhKj7U51ZnYT3nS5nCH7iJkCjaKvd/Hwsx2M6pXnpY45xlDVeTOjZxxaOF/E0 + VT2FP2 + TZMDRfrSMLBEkpbyX0M/VxunriRJPXTUvl3PW0sVOEa3J7 + fbce0XWAKz7PNs3 + hcdzD2Av2VHYF7/bJwcDCO77ky0G4JlHjqC0HnnGP2UWI5qR + tCSBga7 + M1P3ESjcTCV6G6H + 7f8SOSv9FECcJ8J5WUrU + EHrZ95bDtPc9scE4P3OEQaYchlC9GHk2ZoGo5oMJI6YACuRfbGQJNBjdjxvLIrAMrB6DNGDMbH6UZodkpZgQjGVuoCWgFEfLqegHbp34CjwL5ZFJGohV + E87KxedXE6aEseywyjmGLGZwAekjsjNwuxqD2QMb05sg9VkiUPMsvn45K9iCLS5clEKOTwkd + JuWw2IU80pA24aXN64RvOJX5VKMN6CPluJVLdjHeFL55SB7nlDjp15WhoMU1A ="}

这只是一个临时解决方案,直到 laravel 支持应用程序的外部 API,该应用程序只有移动设备作为创建 oAuth 客户端和用户的唯一可能接口.

希望对你有帮助!干杯.

I'm using Laravel Framework version 5.3.9, fresh download nothing added on via composer(except "laravel/passport": "^1.0").

I did all the things suggested in the docs. Tables are created, routes are up, everything works fine. However I need passport for an API.

My routes look like so:

+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+
| Domain | Method   | URI                                     | Name                 | Action                                                                     | Middleware |
+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+
|        | GET|HEAD | /                                       |                      | Closure                                                                    | web        |
|        | GET|HEAD | api/v1/users/register                   | api::users::register | AppHttpControllersApiV1SocialController@register                      | api,auth   |
|        | POST     | oauth/authorize                         |                      | LaravelPassportHttpControllersApproveAuthorizationController@approve  | web,auth   |
|        | GET|HEAD | oauth/authorize                         |                      | LaravelPassportHttpControllersAuthorizationController@authorize       | web,auth   |
|        | DELETE   | oauth/authorize                         |                      | LaravelPassportHttpControllersDenyAuthorizationController@deny        | web,auth   |
|        | GET|HEAD | oauth/clients                           |                      | LaravelPassportHttpControllersClientController@forUser                | web,auth   |
|        | POST     | oauth/clients                           |                      | LaravelPassportHttpControllersClientController@store                  | web,auth   |
|        | PUT      | oauth/clients/{client_id}               |                      | LaravelPassportHttpControllersClientController@update                 | web,auth   |
|        | DELETE   | oauth/clients/{client_id}               |                      | LaravelPassportHttpControllersClientController@destroy                | web,auth   |
|        | GET|HEAD | oauth/personal-access-tokens            |                      | LaravelPassportHttpControllersPersonalAccessTokenController@forUser   | web,auth   |
|        | POST     | oauth/personal-access-tokens            |                      | LaravelPassportHttpControllersPersonalAccessTokenController@store     | web,auth   |
|        | DELETE   | oauth/personal-access-tokens/{token_id} |                      | LaravelPassportHttpControllersPersonalAccessTokenController@destroy   | web,auth   |
|        | GET|HEAD | oauth/scopes                            |                      | LaravelPassportHttpControllersScopeController@all                     | web,auth   |
|        | POST     | oauth/token                             |                      | LaravelPassportHttpControllersAccessTokenController@issueToken        |            |
|        | POST     | oauth/token/refresh                     |                      | LaravelPassportHttpControllersTransientTokenController@refresh        | web,auth   |
|        | GET|HEAD | oauth/tokens                            |                      | LaravelPassportHttpControllersAuthorizedAccessTokenController@forUser | web,auth   |
|        | DELETE   | oauth/tokens/{token_id}                 |                      | LaravelPassportHttpControllersAuthorizedAccessTokenController@destroy | web,auth   |
+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+

All the web routes are there, there are no api related routes, since Passport doesn't provide anything of that sort out of the box.

The API itself is intended to be used by a trusted client, it's made for a mobile application that does require a login however, said login will bypass a few steps.

Once a user access the /register route, the registration process itself is quite simple: access the user's facebook account an grab a few fields - email, facebook id, name an profile picture and from that point onwards the users is considered registered. But the user will NOT login with facebook(this is a very important aspect). The consumer app will be issued a token and use that token to access various endpoints of the api(that require a token to use).

So it boils down to this. I need to issue an access token to the consumer app that access the API. The API itself will only have one client, that is the mobile app itself. Users that use the app are not considered clients of the API but clients of the mobile app itself.

So far Passport is a headache to work with when it comes to implementing API related stuff, either that or I can't figure out how to make it work properly.

I've created a test client in the oauth_clients table that looks like so:

I'm using Postman to access api/v1/users/register route that has the auth middleware with the following JSON application/json

{
    "grant_type" : "authorization_code",
    "client_id" : 5,
    "client_secet": "y5dvPIOxQJOjYn7w2zzg4c6TRrphsrNFWbG4gAUL"
}

Which of course will result in a

{"error":"Unauthenticated."}

It makes perfect sense. Out of pure curiosity I changed the /register route to this:

Route::group([
    'middleware' => [
    ],
], function ()
{
    Route::group([
        'prefix' => 'users',
        'as'     => 'users::',
    ], function ()
    {
//        Route::get('/register', ['as'   => 'register', 'uses' => 'ApiV1SocialController@register',]);
        Route::post('/register', ['as'   => 'register', 'uses' => 'LaravelPassportHttpControllersAccessTokenController@issueToken',]);
    });

});

With the same json as before. That resulted in {"error":"invalid_client","message":"Client authentication failed"}.

I've tracked down the function that, I think, handles the validateClient part in vendor/leagueoauth2-server/src/Grant/AbstractGrant`.

The $client is null. Now this may or may not be related to Passport, since the documentation on it rather lacking and the thought of digging thru a monster of a package to track down the error that may be largely due to me not doing something right doesn't strike me as a good idea, I'm out of options. To be perfectly honest I don't even know what the problem is.

Really, at this point any sort pointing in the right direction is more than welcome.

The part in questions is

解决方案

The problem with Laravel 5.3 passport is that unlike previous OAuth 2.0 Server for Laravel library offered by lucadegasperi, it has no API to make clients directly. So as if now the client can only be made through the front-end. FYI we wanted to use laravel passport solely for our mobile app so while creating and registering user we would have only EMAIL & Password and in some cases only Facebook UserID for facebook sign-in. So the following approach worked pretty well for our case and might differ for your scenario but may help you in the longer term to play around with laravel passport.

Note: Before following the below its assumed you have enabled Password Grant in your application.

So the way we solved it for our project on laravel 5.3 is as follows:

  1. in the oauth_clients convert the id field into a normal field i.e. remove it as being primary key and make the data type as varchar so that we can store email address as client_ids as they are also unique for your system. Incase of Facebook login we store Facebook user IDs here in this column which again will be unique for each our client. Also for other tables like: oauth_access_tokens, oauth_auth_codes & oauth_personal_access_clients change client_id to VARCHAR(255) so that it can store email addresses or Facebook User IDs.

  2. Now go to your models and create a model for oauth_clients table so that you can create client programmatically from the code while creating users.

    <?php
    namespace App;
    
    
    use IlluminateDatabaseEloquentModel;
    
    class OauthClient extends Model
    {
        protected $table = 'oauth_clients';
    }
    

  3. Then in your api.php route file add the following route:

    Route::post('/register-user', function (Request $request) {
    
        $name     = $request->input('name');
        $email    = $request->input('email'),
        $password = $request->input('password'),    
    
        // save new user
        $user = AppUser::create([
          'name'     => $name,
          'email'    => $email,
          'password' => bcrypt($password),
        ]);
    
    
        // create oauth client
        $oauth_client = AppOauthClient::create([
            'user_id'                => $user->id,
            'id'                     => $email,
            'name'                   => $name,
            'secret'                 => base64_encode(hash_hmac('sha256',$password, 'secret', true)),
            'password_client'        => 1,
            'personal_access_client' => 0,
            'redirect'               => '',
            'revoked'                => 0,
        ]);
    
    
        return [
            'message' => 'user successfully created.'
        ];
    });
    

In the above code snippet, you have to note that to generate the oauth_client secret you have to use some strong formula of encryption that you feel comfortable using it with your application. Also, use the same technique to generate the secret key on your mobile app for the respective client/user.

  1. Now you can use the standard POST API offered by laravel passport to request access token through password grant using "oauth/token" using the following parameters:

    grant_type : 'password'
    client_id  : '<email with which the user is registered>'
    client_secret : '<generate the client secret from the mobile app>'
    username : '<email with which the user is registered>'
    password : '<password entered by the user>'
    scope : '<leave empty as default>'
    

  2. The above will give you a response, if everything is correct, similar to :

    {
      "token_type": "Bearer",
      "expires_in": 3155673600,
      "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3In0.eyJhdWQiOiJzaHVqYWhtQGdtYWlsLmNvbSIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3IiwiaWF0IjoxNDc4MTQ1NjMyLCJuYmYiOjE0NzgxNDU2MzIsImV4cCI6NDYzMzgxOTIzMiwic3ViIjoiMSIsInNjb3BlcyI6W119.dj3g9b2AdPCK-im5uab-01SP71S7AR96R0FQTKKoaZV7M5ID1pSXDlmZw96o5Bd_Xsy0nUqFsPNRQsLvYaOuHZsP8v9mOVirBXLIBvPcBc6lDRdNXvRidNqeh4JHhJu9a5VzNlJPm3joBYSco4wYzNHs2BPSxXuuD3o63nKRHhuUHB-HwjVxj2GDwzEYXdZmf2ZXOGRJ99DlWGDvWx8xQgMQtd1E9Xk_Rs6Iu8tycjBpKBaC24AKxMI6T8DpelnFmUbMcz-pRsgCWCF_hxv6FpXav3jr1CLhhT58_udBvXjQAXEbtHeB7W_oaMcaqezHdAeOWDcnqREZHsnXHtKt0JpymcTWBkS2cg7sJzy6P9mOGgQ8B4gb8wt44_kHTeWnokk4yPFRZojkHLVZb8YL6hZxLlzgV1jCHUxXoHNe1VKlHArdlV8LAts9pqARZkyBRfwQ8oiTL-2m16FQ_qGg-9vI0Suv7d6_W126afI3LxqDBi8AyqpQzZX1FWmuJLV0QiNM0nzTyokzz7w1ilJP2PxIeUzMRlVaJyA395zq2HjbFEenCkd7bAmTGrgEkyWM6XEq1P7qIC_Ne_pLNAV6DLXUpg9bUWEHhHPXIDYKHS-c3N9fPDt8UVvGI8n0rPMieTN92NsYZ_6OqLNpcm6TrhMNZ9eg5EC0IPySrrv62jE",
      "refresh_token": "BbwRuDnVfm7tRQk7qSYByFbQKK+shYPDinYA9+q5c/ovIE1xETyWitvq6PU8AHnI5FWb06Nl2BVoBwCHCUmFaeRXQQgYY/i5vIDEQ/TJYFLVPRHDc7CKILF0kMakWKDk7wJdl5J6k5mN38th4pAAZOubiRoZ+2npLC7OSZd5Mq8LCBayzqtyy/QA5MY9ywCgb1PErzrGQhzB3mNhKj7U51ZnYT3nS5nCH7iJkCjaKvd/Hwsx2M6pXnpY45xlDVeTOjZxxaOF/e0+VT2FP2+TZMDRfrSMLBEkpbyX0M/VxunriRJPXTUvl3PW0sVOEa3J7+fbce0XWAKz7PNs3+hcdzD2Av2VHYF7/bJwcDCO77ky0G4JlHjqC0HnnGP2UWI5qR+tCSBga7+M1P3ESjcTCV6G6H+7f8SOSv9FECcJ8J5WUrU+EHrZ95bDtPc9scE4P3OEQaYchlC9GHk2ZoGo5oMJI6YACuRfbGQJNBjdjxvLIrAMrB6DNGDMbH6UZodkpZgQjGVuoCWgFEfLqegHbp34CjwL5ZFJGohV+E87KxedXE6aEseywyjmGLGZwAekjsjNwuxqD2QMb05sg9VkiUPMsvn45K9iCLS5clEKOTwkd+JuWw2IU80pA24aXN64RvOJX5VKMN6CPluJVLdjHeFL55SB7nlDjp15WhoMU1A="
    }
    

Its only a temporary solution till laravel supports an external API for applications which only has a mobile as the only possible interface for creating oAuth clients and user.

Hope it helps you! Cheers.

这篇关于Laravel 的 5.3 通行证和 API 路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆