lucinda/oauth2-client

抽象OAuth2提供者(例如:facebook)与PHP应用程序通信的API,基于IETF标准

v3.1.2 2022-06-05 07:28 UTC

README

目录

关于

这个API的想法是基于构建一个基于IETF规范的共享驱动程序,该驱动程序抽象了与流行的OAuth2提供者的通信,这样你就不必强制使用它们膨胀的PHP客户端。

diagram

现在,它已经成为一个成熟的时间考验的API,通过这一系列步骤几乎完全隐藏了与这些提供者的通信复杂性

  • 注册:在OAuth2提供者上注册您的网站,以便以后可以查询它们
  • 配置:设置一个XML文件,其中为每个开发环境设置一个或多个记录器
  • 初始化:基于上述XML和当前开发环境创建一个Lucinda\OAuth2\Wrapper实例,然后根据请求的页面调用getDriver()方法
  • 查询提供者:使用上述方法得到的共享驱动程序Lucinda\OAuth2\Driver实例查询相应的提供者

API完全符合PSR-4规范,仅需要PHP 8.1+解释器、Lucinda URL Requester和SimpleXML扩展。要快速了解其工作原理,请查看

注册

OAuth2要求您的网站(客户端)在互联网上可用,以便与提供者(服务器)通信。为此,您的网站必须在提供者网站上注册,就像用户一样!支持提供者的注册端点是

到达那里后,您将在注册过程中被要求填写一个表格,您需要提供以下信息:

  • redirect_uri:(总是)OAUTH2供应商将授权码重定向到您网站的完整链接
  • scopes:(有时)您的网站在每个网站客户端账户上需要特定于供应商的权利
  • application_name:(仅GitHub)唯一名称,用于区分您的网站和其他网站

注册完成后,您的网站将获得以下信息:

  • client_id:在OAUTH2供应商网站上标识您网站的公共ID
  • client_secret:与您网站关联的私钥,用于在授权码-访问令牌交换中使用

要了解更多关于它们如何工作的信息,请查看专业文章

配置

要配置此API,您必须有一个包含以下标签的XML文件

<oauth2>
	<{ENVIRONMENT}>
		<driver name="..." client_id="..." client_secret="..." callback="..." scopes="..." {OPTIONS}/>
		...
	</{ENVIRONMENT}>
	...
</oauth2>

其中:

  • oauth2:(必填)包含全局OAUTH2设置。
    • {ENVIRONMENT}:开发环境名称(将被替换为“local”,“dev”,“live”等)
      • driver:通过属性存储有关单个OAUTH2提供者的信息
        • name:(必填)OAuth2提供者的名称。可以是:Facebook、GitHub、Google、LinkedIn、Instagram、VK、Yahoo、Yandex!
        • client_id:(必填)在OAUTH2供应商网站上标识您网站的公共ID(见:注册
        • client_secret:(必填)与您网站关联的私钥,用于在授权码-访问令牌交换中使用(见:注册
        • callback:(必填)OAUTH2供应商将授权码重定向到您网站上的相对URI(页面)(见:注册)。必须是唯一的!
        • scopes:(可选)您的网站在客户端供应商账户上需要哪些权利级别(见:注册
        • {OPTIONS}:某些供应商所需但不是规范一部分的额外属性列表
          • application:(如果provider = GitHub则为必填)您的网站名称(见:注册

示例

<oauth2>
    <live>
        <driver name="Facebook" client_id="YOUR_CLIENT_ID" client_secret="YOUR_CLIENT_SECRET" callback="login/facebook" scopes="public_profile,email"/>
        <driver name="Google" client_id="YOUR_CLIENT_ID" client_secret="YOUR_CLIENT_SECRET" callback="login/google" scopes="https://www.googleapis.com/auth/plus.login,https://www.googleapis.com/auth/plus.profile.emails.read"/>
    </live>
</oauth2>

执行

初始化

现在XML已配置,您可以通过查询Lucinda\OAuth2\Wrapper获取与请求页面匹配的登录URI的驱动程序

$requestedPage = (!empty($_SERVER["REQUEST_URI"])?substr($_SERVER["REQUEST_URI"], 1):"");
$object = new Lucinda\OAuth2\Wrapper(simplexml_load_file(XML_FILE_NAME), DEVELOPMENT_ENVIRONMENT);
$driver = $object->getDriver($requestedPage);

返回的驱动程序是Lucinda\OAuth2Client\Driver实例,每个实例对应一个“driver”标签,其回调与请求页面匹配,每个实例都通过以OAUTH2客户端操作为中心的通用接口隐藏了供应商的复杂性。如果没有找到与请求页面匹配的驱动程序,则返回NULL!

注意:由于XML解析成本较高,建议在应用生命周期中某处保存$object并重用。

查询提供者

一旦您获得驱动程序,您就可以自动查询它。但是,首先您需要在处理所有REDIRECT_URI(因为此逻辑在供应商之间是相同的)的控制器中从提供者那里获取访问令牌

if (empty($_GET["code"])) {
    // redirects to vendor in order to get authorization code
    $redirectURL = $driver->getAuthorizationCodeEndpoint();
    header("Location: ".$redirectURL);
    exit();
} else {
    // exchanges authorization code with an access token
    $accessTokenResponse = $driver->getAccessToken($_GET["code"]);
    
    // save $accessTokenResponse to storage
    // save $driver to storage
}

访问令牌保存后,您可以使用它来在当前或未来的请求中验证对供应商的资源请求。在使用之前,您需要确保令牌尚未过期

// loads $accessTokenResponse from storage
if ($accessTokenResponse->getExpiresIn() && $accessTokenResponse->getExpiresIn()>time()) {
    $accessTokenResponse = $driver->refreshAccessToken($accessTokenResponse->getRefreshToken());
    // save $accessTokenResponse to storage
}

然后检索任何客户端批准作用域的供应商资源

$accessToken = $accessTokenResponse->getAccessToken();
$information = $driver->getResource(accessToken, RESOURCE_URI, ?RESOURCE_FIELDS);

示例

假设驱动程序是

<driver name="Facebook" client_id="YOUR_CLIENT_ID" client_secret="YOUR_CLIENT_SECRET" callback="login/facebook" scopes="public_profile,email"/>

如果$_SERVER["REQUEST_URI"]的值为"login/facebook",则在查询供应商上面的行中,首先检查是否存在"code"查询字符串参数

  • NO:重定向到服务提供商并要求客户端批准访问public_profile和email可视化权限。如果批准,供应商将重定向到同一页面但带有"code"参数
  • YES:要求服务提供商用短期授权代码("code"参数的值)与长期访问令牌进行交换

现在获取了访问令牌,开发者可以使用它从供应商网站上检索关于客户端的public_profile和email信息

// load $driver from storage
// load $accessToken from storage
$userInformation = $driver->getResource($accessToken, "https://graph.facebook.com/v2.8/me", ["id","name","email"]);

安装

首先选择一个文件夹,将其关联到域名,然后在控制台那里写入此命令

composer require lucinda/oauth2-client

然后创建一个configuration.xml文件,其中包含配置设置(参见上文的配置),以及一个index.php文件(在项目根目录下参见初始化,以下代码)

require(__DIR__."/vendor/autoload.php");
$requestedPage = (!empty($_SERVER["REQUEST_URI"])?substr($_SERVER["REQUEST_URI"], 1):"");
$object = new Lucinda\OAuth2\Wrapper(simplexml_load_file("configuration.xml"), "local");
$driver = $object->getDriver($requestedPage);

然后确保域名对万维网可用,并将指向它的所有请求重定向到index.php

RewriteEngine on
RewriteRule ^(.*)$ index.php

单元测试

对于测试和示例,请检查API源中的以下文件/文件夹