codewiser/oauth2-resource-server

该包已弃用,不再维护。未建议替代包。

OAuth 2.0 资源服务器

0.4 2020-11-06 14:46 UTC

This package is auto-updated.

Last update: 2023-11-23 14:17:20 UTC


README

OAuth 是一个授权服务器。它提供并验证令牌。它是构建分布式 API 基础设施的最佳解决方案。

基础设施可能包括许多 API 服务器,称为资源服务器。这些服务器接受的每个请求都必须包含授权信息——授权服务器签发的 access_token

每个资源服务器都是 OAuth 客户端。它拥有 client_idclient_secret,可以使用 client_credentials 授予权限签发自己的 access_token。另一方面,它可能是一个个人 access_token,通过传统方式由用户签发。签发 access_token 后,服务器将使用它向邻居(同一基础设施中的其他资源服务器)发出请求,或提供对本地资源的访问。

当服务器收到包含授权信息的请求时,它将检查(参见 rfc7662)请求中的 access_token。API 服务器调用 OAuth 服务器,并从它那里接收有关给定 access_token 的信息。

如果令牌有效且具有适当的范围,服务器将处理请求。如果不这样做,服务器将返回错误。

RFC

基于 league/oauth2-client 的包

先决条件

您的 OAuth 服务器必须实现 rfc7662(令牌检查端点)。请参阅 ipunkt/laravel-oauth-introspection

安装

composer require codewiser/oauth2-resource-server

发布包配置。

php artisan vendor:publish --provider="Codewiser\ResourceServer\Providers\ResourceServerServiceProvider"

设置

一个环境需要所有标准 OAuth 客户端属性。

OAUTH_SERVER=https://oauth.example.com
CLIENT_ID=123
CLIENT_SECRET=***
SCOPE="read write"

SCOPE 是请求访问令牌的默认范围。

以下为可选的,有默认值。

REDIRECT_URI=oauth/callback
AUTHORIZE_ENDPOINT=oauth/authorize
TOKEN_ENDPOINT=oauth/token
RESOURCE_OWNER_ENDPOINT=api/user
INTROSPECTION_ENDPOINT=oauth/introspect

您可以提供完整的 URL 或仅路径。

外观和中间件

资源服务器

ResourceServer 是 OAuth-client 的一层,负责保持 Client Credentials Access Token 并保护 API 资源。

$accessToken = ResourceServer::getAccessToken();

这将返回缓存的(或新签发的)客户端访问令牌。使用它调用其他 API 服务器。

令牌可以发送为 Athorization 标头(参见 rfc6750#section-2.1),
作为 access_token 主体参数(参见 rfc6750#section-2.2)或
作为 access_token 查询参数(参见 rfc6750#section-2.3)。

然后您的服务器收到带有 Bearer 令牌的 API 请求,它应该在 OAuth-server 上检查令牌。

$introspected = ResourceServer::getIntrospectedToken($request->bearerToken());

简单地,您可以使用 ResourceServerMiddleware 保护路由。在 app/Http/Kernel.php 中以您喜欢的方式定义它。

protected $routeMiddleware = [
    'scope' => \Codewiser\ResourceServer\Http\Middleware\ResourceServerMiddleware::class,
];

然后保护您的路由。

Route::get('resource', 'ApiController@list')->middleware('scope:read');

class ApiController extends Controller
{
  public function list(Request $request)
  {
     // Get user profile from OAuth server
     $owner = ResourceServer::getTokenOwner($request);
    
    // Your code here
  }
}

否则,您可以使用中间件保护一组路由,并在控制器中验证范围。

Route::get('resource', 'ApiController@list')->middleware('scope');

class ApiController extends Controller
{
  public function list(Request $request)
  {
    ResourceServer::introspect($request)
        ->validateScope('read');
    
    // Your code here
  }
}

如果请求未验证,则抛出的异常会渲染适当的响应(根据 rfc6750)。

OAuthClient

OAuthClient 是 OAuth-client 的一层,负责授权用户并保持他们的 Personal Access Token

if (!OAuthClient::hasAccessToken()) {
    
    // Will remeber current page to get user back here.
    OAuthClient::setReturnUrl($request->fullUrl());
    
    // Set required scopes
    OAuthClient::setScope('read write email etc');

    return redirect(OAuthClient::getAuthorizationUrl())
}

授权服务器将用户返回到 CallbackController。您可以使用内置的或定义新的。

try {
    
    // Callback will exchange authorization_code to access_token and stores it into session.
    OAuthClient::callback($request);
    
    // Then return user back to the page we previously stores.
    return redirect(OAuthClient::getReturnUrl('/'));
} catch (\Throwable $e) {

}

因此,如果我们有个人访问令牌,我们应该向用户提供所需信息。

if (OAuthClient::hasAccessToken()) {
    
    ResourceServer::getIntrospectedToken(OAuthClient::getAccessToken())
        ->validateScope('read');
    
    // Your code here
}

以简单的方式,您可以使用PersonalAccessMiddleware来保护路由。在app/Http/Kernel.php中以您喜欢的方式定义它。

protected $routeMiddleware = [
    'private' => \Codewiser\ResourceServer\Http\Middleware\PersonalAccessMiddleware::class,
];

然后保护您的路由。

Route::get('profile', 'PersonalController@show')->middleware('private:read')

如果用户没有个人访问令牌,他或她将被重定向到授权服务器。

缓存

所有令牌都会在本地缓存一段时间。