codexshaper/php-oauth2

PHP 的 OAuth2 认证。

v1.0.1 2020-06-07 10:32 UTC

This package is auto-updated.

Last update: 2024-09-08 20:14:00 UTC


README

License Build Status StyleCI Quality Score Downloads Latest Version on Packagist

描述

PHP 的 OAuth2 认证

安装

composer require codexshaper/php-oauth2

设置数据库

use Illuminate\Support\Facades\Facade;
use Illuminate\Container\Container;
use CodexShaper\Database\Database;

Facade::setFacadeApplication(new Container);

$db = new Database([
	"driver" 		=> "mysql",
	"host" 			=> 'localhost',
	"database" 		=> 'php-oauth2',
	"username" 		=> 'root',
	"password" 		=> '',
	"prefix"   		=> '',
	"charset"   	=> 'utf8mb4',
	"collation"   	=> 'utf8mb4_unicode_ci',
]);

$db->run();

有关数据库的更多详细信息,请访问以下链接 https://github.com/Codexshaper/php-database

迁移表

use CodexShaper\OAuth2\Server\Manager;

Manager::migrate();

回滚表

use CodexShaper\OAuth2\Server\Manager;

Manager::rollback();

刷新表

use CodexShaper\OAuth2\Server\Manager;

Manager::refresh();

客户端凭证授权

客户端将发送一个带有以下表单参数的 POST 请求到授权服务器

`grant_type` with the value `client_credentials`
`client_id` with the client’s ID
`client_secret` with the client’s secret
`scope` with a space-delimited list of requested scope permissions.

授权服务器将响应一个包含以下属性的 JSON 对象

`token_type` with the value Bearer
`expires_in` with an integer representing the TTL of the access token
`access_token` a JWT signed with the authorization server’s private key

密码授权

客户端然后将一个带有以下表单参数的 POST 请求发送到授权服务器

`grant_type` with the value `password`
`client_id` with the the client’s ID
`client_secret` with the client’s secret
`scope` with a space-delimited list of requested scope permissions.
`username` with the user’s username
`password` with the user’s password

授权服务器将响应一个包含以下属性的 JSON 对象

`token_type` with the value Bearer
`expires_in` with an integer representing the TTL of the access token
`access_token` a JWT signed with the authorization server’s private key
`refresh_token` an encrypted payload that can be used to refresh the access token when it expires.

获取访问令牌

use CodexShaper\OAuth2\Server\Http\Controllers\AccessTokenController;
use League\OAuth2\Server\Exception\OAuthServerException;

try {
	
	$controller = new AccessTokenController;
	$response = $controller->issueAccessToken();
    
} catch (OAuthServerException $exception) {

    return $exception->generateHttpResponse($response);
    
}

客户端将发送一个带有以下表单参数的 POST 请求到授权服务器

grant_type with the value refresh_token
refresh_token with the refresh token
client_id with the the client’s ID
client_secret with the client’s secret
scope with a space-delimited list of requested scope permissions. This is optional; if not sent the original scopes will be used, otherwise you can request a reduced set of scopes.

授权服务器将响应一个包含以下属性的 JSON 对象

token_type with the value Bearer
expires_in with an integer representing the TTL of the access token
access_token a new JWT signed with the authorization server’s private key
refresh_token an encrypted payload that can be used to refresh the access token when it expires

获取刷新令牌

use CodexShaper\OAuth2\Server\Http\Controllers\RefreshTokenController;
use League\OAuth2\Server\Exception\OAuthServerException;

try {
	
	$controller = new RefreshTokenController;
	$response = $controller->issueAccessToken();
    
} catch (OAuthServerException $exception) {

    return $exception->generateHttpResponse($response);
    
}

第一部分

客户端将用户重定向到授权服务器,并在查询字符串中包含以下参数

response_type with the value code
client_id with the client identifier
redirect_uri with the client redirect URI. This parameter is optional, but if not send the user will be redirected to a pre-registered redirect URI.
scope a space delimited list of scopes
state with a CSRF token. This parameter is optional but highly recommended. You should store the value of the CSRF token in the user’s session to be validated when they return.

所有这些参数都将由授权服务器进行验证。

然后,用户将被要求登录到授权服务器并批准客户端。

如果用户批准了客户端,他们将被重定向到客户端的重定向 URI,并在查询字符串中包含以下参数

code with the authorization code
state with the state parameter sent in the original request. You should compare this value with the value stored in the user’s session to ensure the authorization code obtained is in response to requests made by this client rather than another client application.
use CodexShaper\OAuth2\Server\Http\Controllers\RefreshTokenController;
use CodexShaper\OAuth2\Server\Models\User;
use League\OAuth2\Server\Exception\OAuthServerException;

// Step 1
try {
	
	$user = User::find(1);
	$authorize = new AuthorizationController;
	$authRequest = $authorize->authorize($user);
    
} catch (OAuthServerException $exception) {

    return $exception->generateHttpResponse($response);
    
}

// Redirect to callback if skip authorization is true

$client = new Client;

if($client->isSkipsAuthorization()) {

	$headers = $authRequest->getHeaders();
	$locations = $headers['Location'];

	foreach ($locations as $location) {
		header('Location: ' . $location);
	}
	die();
}

// If skip authorization is false then display html button to choose approve or deny. First set authRequest in your session to retrieve later for access token

session_start();

	$_SESSION['authRequest'] = $authRequest;

$html = <<<HTML
	<!DOCTYPE html>
	<html>
		<head>
			<title></title>
		</head>
		<body>
			<form>
				<a href="http://site.com/approve.php?action=approve">Approve</a>
				<a href="http://site.com/approve.php?action=deny">Deny</a>
			</form>
		</body>
	</html>
HTML;

echo $html;

// approve.php
// You need to setup database before call any request

if(isset($_SESSION['authRequest']) && $_REQUEST['action'] === 'approve') {
	try {

		$user = User::find(1);

		$authorize = new AuthorizationController;
		$authRequest = $_SESSION['authRequest'];

		var_dump($authRequest);

		$response = $authorize->approve($authRequest, $user);

		$headers = $response->getHeaders();
		$locations = $headers['Location'];

		foreach ($locations as $location) {
			header('Location: ' . $location);
		}
		die();

		session_destroy();

	} catch(\Exception $ex) {

	}
}

第二部分

客户端现在将发送一个带有以下参数的 POST 请求到授权服务器

grant_type with the value of authorization_code
client_id with the client identifier
client_secret with the client secret
redirect_uri with the same redirect URI the user was redirect back to
code with the authorization code from the query string

请注意,您需要先对 code 查询字符串进行解码。您可以使用 urldecode($code) 来做。

授权服务器将响应一个包含以下属性的 JSON 对象

token_type with the value Bearer
expires_in with an integer representing the TTL of the access token
access_token a JWT signed with the authorization server’s private key
refresh_token an encrypted payload that can be used to refresh the access token when it expires.

回调

if (isset($_GET['code'])) {
	// call part 2. Here I used guzzle http request

	$code = urldecode($_GET['code']);
	$http = new GuzzleHttp\Client;

	$response = $http->post('http://site.com/oauth/access_token', [
	    'form_params' => [
	        'grant_type' => 'authorization_code',
	        'client_id' => 'CLIENT_ID',
	        'client_secret' => 'CLIENT_SECRET',
	        'code' => $code,
	    ],
	]);

	$data = json_decode((string) $response->getBody(), true);

	var_dump($data);
}