iphpjs/socialite

OAuth 2 包集合。

资助包维护!
Patreon

3.2.1 2021-03-12 12:36 UTC

README

Latest Stable Version Latest Unstable Version Build Status Scrutinizer Code Quality Code Coverage Total Downloads License

Socialite 是一个 OAuth2 认证工具。它受到 laravel/socialite 的启发,您可以在任何 PHP 项目中轻松使用它。 中文文档

此工具现在支持 Facebook、GitHub、Google、LinkedIn、Outlook、QQ、Tapd、支付宝、淘宝、百度、钉钉、微博、微信、抖音、飞书、豆瓣、企业微信、腾讯云等平台。

需求

PHP >= 7.4

安装

$ composer require "overtrue/socialite" -vvv

使用

用户只需创建相应的配置变量,然后通过该工具为每个平台创建认证应用程序,即可轻松获取该平台的 access_token 和用户信息。工具的实现逻辑可参考主要平台的 OAuth2 文档以获取详细信息。

工具的使用步骤如下

  1. 配置平台配置
  2. 使用此工具创建平台应用程序
  3. 让用户重定向到平台认证
  4. 服务器从平台接收 Code 回调,并使用 Code 交换平台上的用户信息(包括 access_token)。

为 Laravel 用户创建的包更容易集成: overtrue/laravel-socialite

authorize.php:

<?php

use Overtrue\Socialite\SocialiteManager;

$config = [
    'github' => [
        'client_id'     => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect'      => 'https:///socialite/callback.php',
    ],
];

$socialite = new SocialiteManager($config);

$url = $socialite->create('github')->redirect();

return redirect($url); 

callback.php:

<?php

use Overtrue\Socialite\SocialiteManager;

$config = [
    'github' => [
        'client_id' => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect' => 'https:///socialite/callback.php',
    ],
];

$socialite = new SocialiteManager($config);

$code = request()->query('code');

$user = $socialite->create('github')->userFromCode($code);

$user->getId();        // 1472352
$user->getNickname();  // "overtrue"
$user->getUsername();  // "overtrue"
$user->getName();      // "安正超"
$user->getEmail();     // "anzhengchao@gmail.com"
...

配置

每次创建都使用相同的配置键: client_idclient_secretredirect

示例

$config = [
  'weibo' => [
    'client_id'     => 'your-app-id',
    'client_secret' => 'your-app-secret',
    'redirect'      => 'https:///socialite/callback.php',
  ],
  'facebook' => [
    'client_id'     => 'your-app-id',
    'client_secret' => 'your-app-secret',
    'redirect'      => 'https:///socialite/callback.php',
  ],
];

自定义应用名称

您可以使用任何您喜欢的名称作为应用程序的名称,例如 foo,并使用 provider 键设置提供者:

$config = [
    'foo' => [
        'provider' => 'github',  // <-- provider name
        'client_id' => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect' => 'https:///socialite/callback.php',
    ],
       
    // another github app
    'bar' => [
        'provider' => 'github',  // <-- provider name
        'client_id' => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect' => 'https:///socialite/callback.php',
    ],
    //...
];

扩展自定义提供者

您可以从自定义提供者轻松创建应用程序,您有两种方法可以这样做

  1. 使用自定义创建器:如下代码所示,为 Foo 应用程序定义了服务提供者名称,但工具本身不支持它,因此使用创建器 extend() 将服务提供者实例作为闭包函数创建。
$config = [
    'foo' => [
        'provider' => 'myprovider',  // <-- provider name
        'client_id' => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect' => 'https:///socialite/callback.php',
    ],
];

$socialite = new SocialiteManager($config);
   
$socialite->extend('myprovider', function(array $config) {
    return new MyCustomProvider($config);
});

$app = $socialite->create('foo');
  1. 使用提供者

👋🏻 您的自定义提供者类必须是 Overtrue\Socialite\Contracts\ProviderInterface 的实现。

class MyCustomProvider implements \Overtrue\Socialite\Contracts\ProviderInterface 
{
    //...
}

然后使用类名设置 provider

$config = [
    'foo' => [
        'provider' => MyCustomProvider::class,  // <-- class name
        'client_id' => 'your-app-id',
        'client_secret' => 'your-app-secret',
        'redirect' => 'https:///socialite/callback.php',
    ],
];

$socialite = new SocialiteManager($config);
$app = $socialite->create('foo');

平台

不同的平台有不同的配置方法,请检查您使用的平台设置。

支付宝

您必须具有以下配置。

$config = [
  'alipay' => [
    // This can also be named as 'app_id' like the official documentation.
    'client_id' => 'your-app-id', 
 
    // Please refer to the official documentation, in the official management background configuration RSA2.
    // Note: This is your own private key.
    // Note: Do not allow the private key content to have extra characters.
    // Recommendation: For security, you can read directly from the file. But here as long as the value, please remember to remove the head and tail of the decoration.
    'rsa_private_key' => 'your-rsa-private-key',

    // Be sure to set this value and make sure that it is the same address value as set in the official admin system.
    // This can also be named as 'redirect_url' like the official documentation.
    'redirect' => 'https:///socialite/callback.php',
  ]
  ...
];

$socialite = new SocialiteManager($config);

$user = $socialite->create('alipay')->userFromCode('here is auth code');

// See this documents "User interface"
$user->getId();        // 1472352
$user->getNickname();  // "overtrue"
$user->getUsername();  // "overtrue"
$user->getName();      // "安正超"
...

仅支持 RSA2 个人私钥,因此如果您想使用证书登录,请保持关注。

钉钉

按照文档进行操作,并按照以下方式配置。

注意:它仅支持二维码访问第三方网站。即交换用户信息(openid、unionid 和昵称)

$config = [
  'dingtalk' => [
      // or 'app_id'
      'client_id' => 'your app id',

      // or 'app_secret' 
      'client_secret' => 'your app secret',

      // or 'redirect_url'
      'redirect' => 'redirect URL'
  ]
];

$socialite = new SocialiteManager($config);

$user = $socialite->create('dingtalk')->userFromCode('here is auth code');

// See this documents "User interface"
$user->getId();        // 1472352
$user->getNickname();  // "overtrue"
$user->getUsername();  // "overtrue"
$user->getName();      // "安正超"
...

抖音

注意:使用抖音创建时,如果您直接使用访问令牌获取用户信息,请先设置openid。openid可以在获取访问令牌时通过code获取,因此可以自动配置您自己的openid调用userFromCode(),如果先调用userFromToken(),则先调用withOpenId()

$config = [
  'douyin' => [
      'client_id' => 'your app id',

      'client_secret' => 'your app secret',

      'redirect' => 'redirect URL'
  ]
];

$socialite = new SocialiteManager($config);

$user = $socialite->create('douyin')->userFromCode('here is auth code');

$user = $socialite->create('douyin')->withOpenId('openId')->userFromToken('here is the access token');

百度

您可以使用withDisplay()来选择您想要显示的表单。

  • 页面
  • 弹出窗口
  • 对话框
  • 移动设备
  • 电视
  • 平板电脑
$authUrl = $socialite->create('baidu')->withDisplay('mobile')->redirect();

popup模式是默认的显示设置。basic是默认的带有权限范围。

飞书

一些简单的内部应用模式和配置app_ticket的使用方式。

$config = [
    'feishu' => [
        // or 'app_id'
        'client_id' => 'your app id',

        // or 'app_secret' 
        'client_secret' => 'your app secret',

        // or 'redirect_url'
        'redirect' => 'redirect URL',

        // if you want to use internal way to get app_access_token
        // set this key by 'internal' then you already turn on the internal app mode 
        'app_mode' => 'internal'
    ]
];

$socialite = new SocialiteManager($config);

$feishuDriver = $socialite->create('feishu');

$feishuDriver->withInternalAppMode()->userFromCode('here is code');
$feishuDriver->withDefaultMode()->withAppTicket('app_ticket')->userFromCode('here is code');

淘宝

您可以使用withView()来选择您想要显示的表单。

$authUrl = $socialite->create('taobao')->withView('wap')->redirect();

web模式是默认的显示设置。user_info是默认的带有权限范围。

微信

我们支持开放平台第三方平台网页授权,代表公众号进行。

您只需输入以下配置。公众号授权不需要。

...
[
    'wechat' =>
        [
            'client_id' => 'client_id',
            'client_secret' => 'client_secret',
            'redirect' => 'redirect-url',

            // Open Platform - Third-party Platform Need
            'component' => [
                'id' => 'component-app-id',
                'token' => 'component-access-token', // or Using a callable as value.
            ]
        ]
],
...

一些技巧

作用域

在将用户重定向之前,您还可以使用scopes()方法在请求中设置"权限范围"。此方法将覆盖所有现有权限范围

$response = $socialite->create('github')
                ->scopes(['scope1', 'scope2'])->redirect();

重定向 URL

您可能还想动态设置redirect_uri,您可以使用以下方法来更改redirect_uri URL

$url = 'your callback url.';

$socialite->redirect($url);
// or
$socialite->withRedirectUrl($url)->redirect();

状态

您的应用可以使用状态参数来确保响应属于由同一用户发起的请求,从而防止跨站请求伪造(CSRF)攻击。CSRF攻击发生在恶意攻击者欺骗用户执行仅用户有权在受信任的Web应用程序上执行的不想执行的操作,所有操作都将在不涉及或提醒用户的情况下完成。

以下是提供状态如何使您的应用更安全的简单示例。在这个例子中,我们使用会话ID作为状态参数,但您可以使用任何您想要的逻辑来为状态创建值。

使用 state 参数重定向

<?php
session_start();
 
$config = [
    //...
];

// Assign to state the hashing of the session ID
$state = hash('sha256', session_id());

$socialite = new SocialiteManager($config);

$url = $socialite->create('github')->withState($state)->redirect();

return redirect($url); 

验证回调 state

一旦用户已授权您的应用,用户将被重定向回您的应用的redirect_uri。OAuth服务器将返回不变的状态参数。检查在redirect_uri中提供的状态是否与您的应用生成状态匹配

<?php
session_start();
 
$state = request()->query('state');
$code = request()->query('code');
 
// Check the state received with current session id
if ($state != hash('sha256', session_id())) {
    exit('State does not match!');
}
$user = $socialite->create('github')->userFromCode($code);

// authorized

了解更多关于state参数的信息

附加参数

要包含请求中的任何可选参数,请使用关联数组调用with()方法

$response = $socialite->create('google')
                    ->with(['hd' => 'example.com'])->redirect();

用户界面

标准用户 API

$user = $socialite->create('github')->userFromCode($code);
{
  "id": 1472352,
  "nickname": "overtrue",
  "name": "安正超",
  "email": "anzhengchao@gmail.com",
  "avatar": "https://avatars.githubusercontent.com/u/1472352?v=3",
  "raw": {
    "login": "overtrue",
    "id": 1472352,
    "avatar_url": "https://avatars.githubusercontent.com/u/1472352?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/overtrue",
    "html_url": "https://github.com/overtrue",
    ...
  },
  "token_response": {
    "access_token": "5b1dc56d64fffbd052359f032716cc4e0a1cb9a0",
    "token_type": "bearer",
    "scope": "user:email"
  }
}

您可以通过以下数组键获取用户属性

$user['id'];        // 1472352
$user['nickname'];  // "overtrue"
$user['name'];      // "安正超"
$user['email'];     // "anzhengchao@gmail.com"
...

或使用以下方法

mixed   $user->getId();
?string $user->getNickname();
?string $user->getName();
?string $user->getEmail();
?string $user->getAvatar();
?string $user->getRaw();
?string $user->getAccessToken(); 
?string $user->getRefreshToken();
?int    $user->getExpiresIn();
?array  $user->getTokenResponse();

从 OAuth API 获取原始响应

$user->getRaw()方法将返回一个API原始响应的array

使用 userFromCode() 获取令牌响应

$user->getTokenResponse()方法将返回一个API获取令牌(访问令牌)响应的array

注意:此方法仅在您使用userFromCode()时返回一个有效的array,否则将返回null,因为使用userFromToken()没有令牌响应。

使用访问令牌获取用户

$accessToken = 'xxxxxxxxxxx';
$user = $socialite->userFromToken($accessToken);

享受它! ❤️

参考

PHP 扩展包开发

想知道如何从零开始构建PHP扩展包吗?

请关注我的实战课程,我将在该课程中分享一些扩展开发经验 —— 《PHP 扩展包实战教程 - 从入门到发布》

许可

MIT