league/oauth2-server 是用 PHP 编写的 OAuth 2.0 授权服务器的标准兼容实现,这使得使用 OAuth 2.0 变得轻而易举。您可以轻松配置 OAuth 2.0 服务器,以使用访问令牌保护您的 API,或允许客户端请求新的访问令牌并刷新它们。
文档译自:OAuth 2.0 Server – PHP, meet OAuth 2,其中难免有错误或不当的地方,欢迎指正。
部分内容引自:OAuth2.0 与 oauth2-server 库的使用
开箱即用,它支持以下授权:
这个库是由 Alex Bilbie 创建的。
更新日志
参见本项目完整更改历史记录。
支持
请在 Github 问题页面上提问。
有关商业支持和定制实现,请访问 Glynde Labs。
术语
- Grant – 授权是获取访问令牌的一种方法。
- Authorization code – 发放给应用程序的中间令牌,客户端应用使用此令牌交换 access token。
- Access token – 用于访问受保护资源的令牌。
- Authorization server – 授权服务器,专用于处理用户授权认证的服务器。
- Client – 代表资源所有者(如用户)访问受保护资源的应用程序。客户端可以托管在服务器、桌面、移动设备或其他设备上。
- Resource server – 位于受保护资源(例如“推文”、用户照片或个人数据)前面的服务器,能够使用访问令牌接受和响应受保护的资源请求。
- Resource owner – 授权应用程序访问其帐户的用户。应用程序对用户帐户的访问仅限于授予的授权的“范围”(例如读取或写入访问权限)。
- Scope – 授权范围。
- JWT – JSON Web 令牌是一种在 RFC 7519 中定义的两方之间安全表示声明的方法。
要求
为了防止中间人攻击,授权服务器必须要求对发送到授权和令牌端的任何请求使用 TLS 和服务器身份验证,如 RFC2818 定义的那样。客户端必须验证授权服务器的 TLS 证书,该证书由 RFC6125 定义并符合其服务器身份验证要求。
该库使用密钥加密来加密和解密,以及验证签名的完整性。有关如何生成密钥的详细信息,请参阅安装页面。
支持以下版本的 PHP:
- PHP 8.0
- PHP 8.1
- PHP 8.2
openssl 和 openssl 扩展是必需的。
传递到服务器的所有 HTTP 消息都应符合 PSR-7 标准。这确保了其他包和框架之间的互操作性。
安装
建议使用 Composer 安装。
在项目根目录中,运行:
composer require league/oauth2-server
确保已将项目设置为自动加载 Composer 安装包。
生成公钥和私钥
公钥/私钥对用于签名和验证传输的 JWT。授权服务器拥有用于签署令牌的私钥,资源服务器拥有相应的公钥来验证签名。要生成私钥,请在终端上运行以下命令:
openssl genrsa -out private.key 2048
如果要为私钥提供密码,请改为运行以下命令:
openssl genrsa -aes128 -passout pass:_passphrase_ -out private.key 2048
然后从私钥中提取公钥:
openssl rsa -in private.key -pubout -out public.key
或者使用您的密码(如果在生成私钥时提供):
openssl rsa -in private.key -passin pass:_passphrase_ -pubout -out public.key
私钥必须保密(即不在授权服务器的 Web 根目录之外)。授权服务器还需要公钥。
如果使用密码短语生成私钥,则必须将其提供给授权服务器。
公钥应分发到验证访问令牌的任何服务(例如资源服务器)。
生成加密密钥
加密密钥用于加密授权和刷新代码。接受 AuthorizationServer 两种加密密钥,密码 string 或 \Defuse\Crypto\Key 安全 PHP 加密库中的对象。
字符串密码
密码的强度可能因所选 string 密码而异。为了将其转换为强加密密钥,使用了 PBKDF2 密钥派生函数。此函数从密码派生加密密钥,设计速度较慢。它在几分之一秒内使用大量 CPU 资源,对密码应用密钥拉伸以减少暴力攻击的漏洞。
要生成 string AuthorizationServer 密码,可以在终端中运行以下命令:
php -r 'echo base64_encode(random_bytes(32)), PHP_EOL;'
关键对象
\Defuse\Crypto\Key 是强加密密钥。这消除了使用慢速密钥派生函数的需要,与使用 string 密码相比,减少了加密和解密时间。
可以使用 generate-defuse-key 脚本生成 A Key 。要生成 在 Key 终端中 AuthorizationServer 运行以下命令:
vendor/bin/generate-defuse-key
可以 string 加载为 Key, Key::loadFromAsciiSafeString($string) 例如:
use \Defuse\Crypto\Key; $server = new AuthorizationServer( $clientRepository, $accessTokenRepository, $scopeRepository, $privateKeyPath, Key::loadFromAsciiSafeString($encryptionKey) );
存储设置
这个库已经开发出来了,这样你就可以使用任何类型的后端存储;关系型、文档型、键值型、列式或者硬编码。
每个存储库接口的文档都描述了你可能想要存储的数据类型,而不是如何存储它。
选用哪种授权模式?
- 如果客户端是保密的,应使用授权码。
- 如果客户端是公开的,应使用隐性授权。
- 如果用户对于此客户端高度信任(例如:第一方应用程序或操作系统程序),应使用密码凭证。
- 如果客户端是以自己的名义,不与用户产生关系,应使用客户端凭证。
服务器授权事件
参见服务器授权事件。
保护 API
此库提供了一个 PSR-7 友好的资源服务器中间件,可以验证访问令牌。
设置
无论在何处初始化对象,都可以使用存储接口初始化资源服务器的新实例:
// Init our repositories $accessTokenRepository = new AccessTokenRepository(); // instance of AccessTokenRepositoryInterface // Path to authorization server's public key $publicKeyPath = 'file://path/to/public.key'; // Setup the authorization server $server = new \League\OAuth2\Server\ResourceServer( $accessTokenRepository, $publicKeyPath );
然后将中间件添加到堆栈中:
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware($server);
实现
将自动验证传入请求上的授权标头。
如果访问令牌有效,则将在服务器请求上设置以下属性:
- oauth_access_token_id – 访问令牌标识符
- oauth_client_id – 客户端标识符
- oauth_user_id – 访问令牌表示的用户标识符
- oauth_scopes – 字符串范围标识符数组
如果授权无效,将抛出一个实例 OAuthServerException::accessDenied 。