tflori/oauth2

此包已废弃,不再维护。未建议替代包。

一个小型oauth2库,用于提供oauth2服务

1.1.1 2016-11-23 13:14 UTC

This package is auto-updated.

Last update: 2020-10-16 05:45:08 UTC


README

Build Status Coverage Status Latest Stable Version Total Downloads License

此库帮助您使用oauth2三腿认证机制创建oauth服务。

目前唯一支持的流程是带有刷新令牌的“隐式”流程

     +----------+
     | Resource |
     |   Owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)-- & Redirection URI ---->|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Authorization Code ---------'      |
     |  Client |          & Redirection URI                  |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)

这在此处描述:[https://tools.ietf.org/html/rfc6749#section-4.1](https://tools.ietf.org/html/rfc6749#section-4.1)

安全

oauth2有多安全?为什么?主要问题是存储客户端的密钥。无论如何,您将其实现为在用户端运行的app:您可以反向工程app以获取密钥。唯一使其安全的方法是将密钥存储在获取授权码并从授权服务请求访问码的服务上。

那么安全吗?不。每个app都可以请求您的服务。您知道如何验证请求确实来自您的app?太好了:向thflori@gmail.com发送建议。

oauth背后的主要思想不是确保app确实是它所说的app。我们能证明的唯一一件事是:用户确实是拥有密码和用户标识(或您的实现中如何进行认证)的用户。

用法

设置

... 待办:编写如何设置 composer require tflori/oauth2 ...

在示例中,我们将使用nikic/fast-route进行路由和tflori/dependency-injector进行依赖注入,但您可以使用任何其他路由器和依赖注入器。

获取授权码(A通过B到C)

授权码使客户端能够获取访问令牌(和刷新令牌)。客户端将用户发送到授权服务器。如果用户已经登录(通常是通过cookies),则将用户发送回回调,并提供授权码。

示例

<?php

$handler = new Oauth2\Handler(new Oauth2\Tests\Fake\Storage());
$client = new Oauth2\Client(1, '~^https://www\.example\.com~', 'my-long-secret');
$user = new Oauth2\User();
$user->permit($client, ['basic']);

$result = $handler->getAuthToken($_SESSION['oauthId'], $client, $user, $_GET['redirect_uri']);
if ($result['status'] == OAuth2\Handler::STATUS_GRANTED) {
    header('Location: ' . $result['redirectUri']);
}

获取访问令牌(D到E)

有了访问令牌,客户端可以访问数据。要获取访问令牌,客户端需要提供客户端ID、客户端密钥和先前生成的授权码。

示例

<?php

$handler = new Oauth2\Handler(new Oauth2\Tests\Fake\Storage());

$result = $handler->getAccessToken($_GET['client_id'], $_GET['client_secret'], $_GET['code']);
header('Content-Type: application/json');
echo json_encode($result);

检查授权

当客户端请求资源时,它将访问令牌发送到header中(通常:Authorization: Bearer <access_token>)。资源服务器必须检查此访问令牌是否有效。

有两种可能的场景

同一服务器上的资源服务器

当资源服务器在同一服务器上运行时,您只需创建一个处理器并向其请求即可

<?php

$handler = new Oauth2\Handler(new Oauth2\Tests\Fake\Storage());

$accessToken = substr($_SERVER['HTTP_AUTHORIZATION'], strrpos($_SERVER['HTTP_AUTHORIZATION'], ' '));
if ($handler->isAuthorized($accessToken, 'this-resource')) {
    $user = $handler->getUser($accessToken);
    // request the resource and send him data
} else {
    header('HTTP/1.1 403 Forbidden');
}

另一服务器上的资源服务器

在这种情况下,您需要向授权服务器发送请求

<?php

$accessToken = substr($_SERVER['HTTP_AUTHORIZATION'], strrpos($_SERVER['HTTP_AUTHORIZATION'], ' '));
$result = json_decode(file_get_contents(
    'https://auth.example.com/validate.php?access_token=' . $accessToken . '&scope=this-resource'
));

在授权服务器上执行与之前相同的操作

<?php

$handler = new Oauth2\Handler(new Oauth2\Tests\Fake\Storage());

header('Content-Type: application/json');
if (!$handler->isAuthorized($_GET['access_token'], $_GET['scope'])) {
    echo json_encode(false); // or echo 'false';
} else {
    echo json_encode($handler->getUser($_GET['access_token']));
}

退出登录

当用户退出登录时,每个会话的访问令牌应立即失效。这很简单

<?php

$handler = new Oauth2\Handler(new Oauth2\Tests\Fake\Storage());
$handler->destroySession($_SESSION['oauthId']);