Laravel 通过 Passport 实现 API 请求认证:第三方应用篇(授权码获取令牌)

把待接入的第三方应用看作前端系统,把自己的平台看作后端系统。

在后端系统注册第三方应用

在后端应用 blog 中注册对应的第三方应用 testapp,在 blog 项目根目录下运行以下命令来注册 testapp

php artisan passport:client
> 
> testapp
> http://app.test/auth/callback

# 显示结果
CLIENT_ID=9
CLIENT_SECRET=Xde5hsAbpEU8MMjwELFh6RNOzxX2LsrxgFTZvXkP

编写第三方应用路由和控制器

第一步是到后端系统请求授权,如果用户在后端系统没有登录需要先登录,登录之后让用户确认授权,授权之后通过 callback 配置的跳转地址回跳到前端应用,并且在 URL 中带上授权码,然后用户再通过这个授权码获取访问令牌,拿到访问令牌之后就可以请求后端系统认证 API 接口了。

所以,需要在前端应用的 routes/web.php 中新增两个路由:

  • 一个用于请求授权获取授权码
  • 一个用于从后端应用跳转回来,通过授权码在回跳的路由中发起后端请求获取令牌
Route::get(\'/auth\', \'Auth\\LoginController@oauth\');
Route::get(\'/auth/callback\', \'Auth\\LoginController@callback\');
public function oauth()
{

    $query = http_build_query([
        \'client_id\' => 9,
        \'redirect_uri\' => \'http://app.test/auth/callback\',
        \'response_type\' => \'code\',
        \'scope\' => \'\',
    ]);

    return redirect(\'http://blog.test/oauth/authorize?\' . $query);
}

public function callback(Request $request)
{
    $code = $request->get(\'code\');
    if (!$code) {
        dd(\'授权失败\');
    }
    
    $http = new Client();
    $response = $http->post(\'http://blog.test/oauth/token\', [
        \'form_params\' => [
            \'grant_type\' => \'authorization_code\',
            \'client_id\' => 9,  // your client id
            \'client_secret\' => "Xde5hsAbpEU8MMjwELFh6RNOzxX2LsrxgFTZvXkP",   // your client secret
            \'redirect_uri\' => \'http://app.test/auth/callback\',
            \'code\' => $code,
        ],
    ]);

    return response($response->getBody());
}

测试通过授权码获取令牌

在浏览器中访问 http://app.test/auth,在第三方应用中通过后端系统进行授权认证,如果在后端应用 blog.test 上还没有登录,会先跳转到登录页面,登录之后则跳转到确认授权页面。

点击绿色的授权按钮,就可以跳转到第三方应用的回调路由,然后发起获取令牌的请求获取访问令牌。

下次从第三方应用 app.test 中访问后端系统 API 接口时,就可以通过在请求头中带上 access_token 来获取 blog.test 上的认证资源了,对应的逻辑和通过密码获取令牌访问是一样的。

通过 Postman 进行测试,将 access_token 值拷贝到 Token 字段,然后就可以发起对认证 API 接口 http://blog.test/api/user 的请求了。

上一篇:Http协议Netty项目,调用Https协议passport(本地调试)


下一篇:[Graphql + Netlify] Solve @Apollo/client CORS problem