Nette OAuth2 Provider 程序包

dev-master 2024-06-09 21:53 UTC

This package is not auto-updated.

Last update: 2024-09-15 22:58:53 UTC


README

此存储库正在开发中,非常不稳定。

要求

Drahak/OAuth2 需要 PHP 版本 5.3.0 或更高。唯一的依赖项是Nette 框架 2.0.x

安装和设置

最简单的方法是使用Composer

$ composer require drahak/oauth2:@dev

然后在创建容器之前将以下代码添加到您的应用程序引导文件中

Drahak\OAuth2\DI\Extension::install($configurator);

或者注册到 config.neon 中

extensions:
  restful: Drahak\Restful\DI\RestfulExtension

Neon 配置

oauth2:
	accessTokenLifetime: 3600 # 1 hour
	refreshTokenLifetime: 36000 # 10 hours
	authorizationCodeLifetime: 360 # 6 minutes
	storage: 'ndb' # allowed values: 'ndb', 'dibi'
	accessTokenStorage: 'Drahak\OAuth2\Storage\NDB\AccessTokenStorage'
	authorizationCodeStorage: 'Drahak\OAuth2\Storage\NDB\AuthorizationCodeStorage'
	clientStorage: 'Drahak\OAuth2\Storage\NDB\ClientStorage'
	refreshTokenStorage: 'Drahak\OAuth2\Storage\NDB\RefreshTokenStorage'
  • accessTokenLifetime - 访问令牌的生命周期(以秒为单位)
  • refreshTokenLifetime - 刷新令牌的生命周期(以秒为单位)
  • authorizationCodeLifetime - 授权代码的生命周期(以秒为单位)
  • storage - 存储将在默认的 NDB 和 dibi 存储之间切换。您可以为每个存储部分使用自己的存储。

OAuth2

抽象协议流程

     +--------+                               +---------------+
     |        |------ Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<------ Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |------- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<--------- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |---------- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<------- Protected Resource ---|               |
     +--------+                               +---------------+

OAuth 角色

客户端 - 第三方应用程序

此应用程序希望从资源服务器获取用户数据,因此它需要获取一个访问令牌。

资源服务器 - API

客户端想要的数据在这里。API 服务器使用访问令牌访问用户信息。

资源所有者

授予对账户某些部分的访问权限。

另请参阅OAuth 2 简化原始规范

OAuth 演示者

提供访问权限的演示者(IOAuthPresenter)。在基础实现中,它有两个主要方法,issueAccessTokenissueAuthorizationCode。简单的 OAuth(资源所有者)演示者可能如下所示

namespace MyApp\OAuth;

use Drahak\OAuth2\Grant\IGrant;
use Drahak\OAuth2\Application;
use Drahak\OAuth2\OAuthException;

class AuthorizationPresenter extends Application\OAuthPresenter
{

	/**
	 * Authorization
	 * @param string $response_type
	 * @param string $redirect_uri
	 * @param string|null $scope
	 */
	public function actionAuthorize($response_type, $redirect_uri, $scope = NULL)
	{
		if (!$this->user->isLoggedIn()) {
			$this->redirect('AnyUser:login', array('backlink' => $this->storeRequest()));
		}

		if ($response_type == 'code') {
			$this->issueAuthorizationCode($response_type, $redirect_uri, $scope);
		} else if ($response_type == 'token') {
			$this->issueAccessToken(IGrant::IMPLICIT, $redirect_uri);
		}
	}

	/**
	 * Access token provider
	 */
	public function actionToken()
	{
		try {
			$this->issueAccessToken();
		} catch (OAuthException $e) {
			$this->oauthError($e);
		}
	}

}

方法issueAccessTokengrant_type参数中确定正确的授权类型。在出错时抛出一些OAuthException,这可以在默认实现中的oauthError方法中处理。

操作authorize更复杂。这用于生成授权代码(见下文 - 授权代码),但对于隐式授权类型,在此处生成访问令牌是必要的。如果用户未登录,则将用户重定向到某个登录页面,然后使用回链恢复授权请求。

授权类型

grant_type参数确定。支持 OAuth2 规范中定义的基本授权类型:授权代码、隐式、密码、客户端凭据和刷新令牌。

  1. 授权代码

此授权类型非常适合可以安全存储客户端密钥代码的第三方应用程序。

要生成访问令牌,您首先需要获取授权代码。您可以通过调用issueAuthorizationCodeIOAuthPresenter获取它

授权代码请求
GET //oauth.presenter.url/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email
  • [必需] response_type - 您想要生成授权code
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
  • [必需] redirect_uri - 在成功或出错时重定向的 URL 地址
  • [可选] scope - 指定访问请求的范围
授权代码响应

在任何情况下(错误或成功),资源所有者都使用redirect_uri将授权代码作为查询参数重定向回客户端

//redirect_uri/?code=AnlSCIWYbchsCc5sdc5ac4caca8a2

或者

//redirect_uri/?error=unauthorized_client&error_description=Client+is+not+found

由于您已经有了授权代码,您可以发出访问令牌请求(数据作为application/x-www-form-urlencoded提供)

访问令牌请求
POST //oauth.presenter.url/token
	grant_type=authorization_code
	&code=AUTHORIZATION_CODE
	&client_id=CLIENT_ID
	&client_secret=CLIENT_SECRET
  • [必需] grant_type - 此参数指示OAuth使用授权码
  • [必需] code - 从资源所有者那里获得的授权码
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
  • [必需] client_secret - 请求访问令牌的客户端(例如应用程序)密钥
访问令牌响应
{
	"access_token": "AnlSCIWYbchsCc5sdc5ac4caca8a2",
	"token_type": "bearer",
	"expires_in": 3600,
	"refresh_token": "DS6SA512ADCVa51adc54VDS51VD5"
}

在出现错误时,提供JSON响应

{
	"error": "invalid_request",
	"error_description": "Invalid authorization code"
}
  1. 隐式授权

用于基于浏览器(Web)或移动应用程序,在这些应用程序中,您无法安全地存储客户端密钥,因此您无法使用它来获取访问令牌。

访问令牌请求
GET //oauth.presenter.url/authorization?response_type=token&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=email
  • [必需] response_type - 由于您从资源所有者请求访问令牌,因此您必须告诉您想要访问令牌(而不是授权码)
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
  • [必需] redirect_uri - 成功或错误发生时重定向的URL
  • [可选] scope - 指定访问请求的范围
访问令牌响应

重定向到 redirect_uri

//redirect_uri/#access_token=AnlSCIWYbchsCc5sdc5ac4caca8a2&expires_in=3600&token_type=bearer

在出现错误时重定向到

//redirect_uri/#error=unauthorized_client&error_description=Client+is+not+found
  1. 密码

用于受信任的(通常是第一方)应用程序,您完全信任客户端,因为您从真实用户凭据(用户名、密码)生成访问令牌

访问令牌请求
POST //oauth.presenter.url/token
	grant_type=password
	&username=USERNAME
	&password=PASSWORD
	&client_id=CLIENT_ID
  • [必需] grant_type - 密码授权类型使用标识符(意外地)password
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
  • [必需] username - 真实用户的用户名
  • [可选] password - 真实用户的密码
访问令牌响应
{
	"access_token": "AnlSCIWYbchsCc5sdc5ac4caca8a2",
	"token_type": "bearer",
	"expires_in": 3600,
	"refresh_token": "DS6SA512ADCVa51adc54VDS51VD5"
}

在出现错误时

{
	"error": "invalid_request",
	"error_description": "Invalid authorization code"
}
  1. 客户端凭据

如果应用程序需要在任何特定用户之外获取访问令牌,这可能是一种最佳方式。

访问令牌请求
POST //oauth.presenter.url/token
	grant_type=client_credentials
	&client_id=CLIENT_ID
	&client_SECRET=CLIENT_SECRET
  • [必需] grant_type - 密码授权类型使用标识符(意外地)password
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
  • [必需] client_secret - 请求访问令牌的客户端(例如应用程序)密钥
访问令牌响应
{
	"access_token": "AnlSCIWYbchsCc5sdc5ac4caca8a2",
	"token_type": "bearer",
	"expires_in": 3600,
	"refresh_token": "DS6SA512ADCVa51adc54VDS51VD5"
}

在出现错误时

{
	"error": "invalid_request",
	"error_description": "Invalid authorization code"
}
  1. 刷新令牌

用于在不进行身份验证过程的情况下恢复(实际上是重新生成)访问令牌。刷新令牌几乎与每种授权类型一起提供(除了隐式授权)。

请求刷新令牌
POST //oauth.presenter.url/token
	grant_type=refresh_token
	&refresh_token=DS6SA512ADCVa51adc54VDS51VD5
	&client_id=CLIENT_ID
  • [必需] grant_type - 刷新令牌标识符
  • [必需] refresh_token - 刷新令牌本身,您几乎可以从任何访问令牌中获得
  • [必需] client_id - 请求访问令牌的客户端 ID(例如应用程序)
访问令牌响应
{
	"access_token": "AnlSCIWYbchsCc5sdc5ac4caca8a2",
	"token_type": "bearer",
	"expires_in": 3600,
	"refresh_token": "DS6SA512ADCVa51adc54VDS51VD5"
}

在出现错误时

{
	"error": "invalid_request",
	"error_description": "Invalid refresh token"
}