javaabu / efaas-socialite
eFaas Provider for Laravel Socialite
Requires
- php: ^7.4 || ^8.0 || ^8.1
- ext-openssl: *
- illuminate/support: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0
- laravel/socialite: ^5.15
- lcobucci/clock: ^2.0 || ^3.0
- lcobucci/jwt: ^4.3 || ^5.0
- phpseclib/phpseclib: ^3.0.39
- strobotti/php-jwk: ^1.4
Requires (Dev)
- mockery/mockery: ^1.6
- orchestra/testbench: ^4.0 || ^5.0 || ^6.44 || ^7.0 || ^8.0 || ^9.0
- phpunit/phpunit: ^8.5 || ^9.5 || ^10.5
README
Laravel Socialite 的 eFaas 提供商,针对 eFaas。
注意:本包的当前版本基于 eFaas 文档版本 2.2
- eFaas Laravel Socialite
要求
本包需要以下依赖项
- Laravel 6.0 或更高版本
- PHP 7.4 或更高版本
- ext-openssl PHP 扩展
安装
对于 Laravel 6.0 及更高版本,您可以通过 composer
安装此包
composer require javaabu/efaas-socialite
对于 Laravel 5.6,请使用 1.x 版本
composer require javaabu/efaas-socialite:^1.0
将配置添加到您的 .env
文件中
将以下配置添加到您的 .env
文件中
EFAAS_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx EFAAS_CLIENT_SECRET=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx EFAAS_REDIRECT_URI=https://your-app.com/path/to/efaas/callback EFAAS_MODE=development # for production use #EFAAS_MODE=production
发布配置文件
可选地,您也可以将配置文件发布到 config/efaas.php
php artisan vendor:publish --provider="Javaabu\EfaasSocialite\Providers\EfaasSocialiteServiceProvider" --tag="efaas-config"
这是配置文件的默认内容
<?php return [ /** * eFaas client config */ 'client' => [ /** * eFaas Client ID */ 'client_id' => env('EFAAS_CLIENT_ID'), /** * eFaas Client Secret */ 'client_secret' => env('EFAAS_CLIENT_SECRET'), /** * eFaas Redirect url */ 'redirect' => env('EFAAS_REDIRECT_URI'), /** * Development mode * supports "production" and "development" */ 'mode' => env('EFAAS_MODE', 'development'), /** * Default scopes for the eFaas client */ 'scopes' => [ 'openid', 'efaas.profile', 'efaas.birthdate', 'efaas.email', 'efaas.mobile', 'efaas.photo', 'efaas.permanent_address', 'efaas.country', 'efaas.passport_number', 'efaas.work_permit_status' ], ], /* * This model will be used to store efaas session sids * The class must implement \Javaabu\EfaasSocialite\Contracts\EfaasSessionContract */ 'session_model' => \Javaabu\EfaasSocialite\Models\EfaasSession::class, /* * This handler will be used to manage saving and destroying efaas session records * The class must implement \Javaabu\EfaasSocialite\Contracts\EfaasSessionHandlerContract */ 'session_handler' => \Javaabu\EfaasSocialite\EfaasSessionHandler::class, /* * This is the name of the table that will be created by the migration and * used by the EfaasSession model shipped with this package. */ 'table_name' => 'efaas_sessions', /* * This is the database connection that will be used by the migration and * the EfaasSession model shipped with this package. In case it's not set * Laravel's database.default will be used instead. */ 'database_connection' => env('EFAAS_SESSIONS_DB_CONNECTION'), ];
发布迁移文件
本包包含用于 efaas_sessions
表的迁移,可用于实现后通道注销。您可以使用以下 Artisan 命令发布这些迁移
php artisan vendor:publish --provider="Javaabu\EfaasSocialite\Providers\EfaasSocialiteServiceProvider" --tag="efaas-migrations"
发布迁移后,您可以运行它们
php artisan migrate
使用方法
注意:本包的演示实现可在 此处 获取。
现在您应该能够像通常使用 Socialite 一样使用提供程序(假设您已安装了外观)。有关更多信息,请参阅 官方 Social 文档。
警告:如果您在 Laravel 应用请求 eFaas 授权端点时遇到 403 Forbidden
错误,请请求 NCIT 将您的服务器 IP 地址列入白名单。
return Socialite::driver('efaas')->redirect();
并在您的回调处理程序中,您可以如此访问用户数据。请记住保存用户的 id_token
和 sid
(会话 ID)。
$efaas_user = Socialite::driver('efaas')->user(); $id_token = $efaas_user->id_token; $sid = $efaas_user->sid; session()->put('efaas_id_token', $id_token); session()->put('efaas_sid', $sid);
启用 PKCE
默认情况下,此包已禁用 PKCE。要启用 PKCE,请在您的重定向调用和回调处理程序中分别使用 enablePKCE()
方法。
return Socialite::driver('efaas')->enablePKCE()->redirect();
// inside callback handler $efaas_user = Socialite::driver('efaas')->enablePKCE()->user();
注销 eFaas 用户
在您的 Laravel 注销重定向中,使用在登录过程中保存的 ID 令牌,使用提供程序的 logOut()
方法进行重定向
$id_token = session('id_token'); return Socialite::driver('efaas')->logOut($id_token, $post_logout_redirect_url);
注意:由于 id_token
可能非常长,在重定向时可能会遇到 nginx 错误。要修复此问题,您可以将以下内容添加到您的 nginx 配置中。更多信息请点击 这里。
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
使用 eFaas One-tap 登录
此包将自动将 /efaas-one-tap-login 端点添加到您的 Web 路由中,该端点将重定向到 eFaas 并使用 eFaas 登录代码。
有时您可能希望自定义 Efaas 提供商定义的路由。为了实现这一点,您首先需要在您的应用程序的 AppServiceProvider
的 register 方法中添加 EfaasProvider::ignoreRoutes
来忽略 Efaas 提供商注册的路由
use Javaabu\EfaasSocialite\EfaasProvider; /** * Register any application services. */ public function register(): void { EfaasProvider::ignoreRoutes(); }
然后,您可以将 Efaas 提供商在 其路由文件 复制到您的应用程序的 routes/web.php 文件中,并根据您的需求修改它们
Route::group([ 'as' => 'efaas.', 'namespace' => '\Javaabu\EfaasSocialite\Http\Controllers', ], function () { // Efaas routes... });
实现前通道单点注销
首先,在登录期间,在您的 efaas 回调处理方法中,将用户的 sid
(会话 ID)保存到您的会话中。
$efaas_user = Socialite::driver('efaas')->user(); $sid = $efaas_user->sid; session()->put('efaas_sid', $sid);
然后,在您的单点登出控制器处理方法中,首先使用 eFaas 提供商的 getLogoutSid()
方法检索登出令牌的 sid
。如果提供的登出令牌无效,该方法将返回 null
。然后,您可以将当前会话中保存的 sid
与检索到的 sid
进行比较,如果它们匹配,则登出用户。
... public function handleFrontChannelSingleSignOut(Request $request) { $saved_sid = session('efaas_sid'); $request_sid = Socialite::driver('efaas')->getLogoutSid(); if ($request_sid && $saved_sid == $request_sid) { // the logout session matches your saved sid // logout your user here auth()->guard('web')->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); } return redirect()->to('/your-redirect-url') } ...
实现后通道单点注销
对于后端登出,您需要使用 Laravel 的 database
会话驱动程序和提供的 efaas_sessions
迁移。
在登录期间,使用 eFaas 提供商的 sessionHandler()
保存用户的 sid
(会话 ID)。
$efaas_user = Socialite::driver('efaas')->user(); $sid = $efaas_user->sid; Socialite::driver('efaas') ->sessionHandler() ->saveSid($sid);
然后,在您的单点登出控制器处理方法中,首先使用 eFaas 提供商的 getLogoutSid()
方法检索登出令牌的 sid
。如果提供的登出令牌无效,该方法将返回 null
。然后,您可以使用 eFaas 提供商的 sessionHandler()
来登出所有与 sid
匹配的 Laravel 会话。
... public function handleBackChannelSingleSignOut(Request $request) { $sid = Socialite::driver('efaas')->getLogoutSid(); if ($sid) { Socialite::driver('efaas') ->sessionHandler() ->logoutSessions($sid); } // for back channel logout you must return 200 OK response return response()->json([ 'success' => ! empty($request_sid) ]); } ...
从移动应用进行身份验证
要验证来自移动应用程序的用户,请通过移动应用程序上的 Web View 将用户重定向到 eFaas 登录屏幕。然后在用户登录 eFaas 后,从您的网站重定向他们时截获 code
(授权代码)。
一旦您的移动应用程序收到授权代码,请将其发送到您的 API 端点。然后,您可以使用以下方式在服务器端使用授权代码获取 eFaas 用户详细信息。请记住,由于重定向是从您的服务器外部发起的,因此请使用 stateless()
选项。
$efaas_user = Socialite::driver('efaas')->stateless()->userFromCode($code);
收到 eFaas 用户后,您可以根据您用于 API 的任何身份验证方案颁发自己的访问令牌或 API 密钥。
更改 eFaas 登录提示行为
可以通过修改重定向请求中的提示选项来自定义 eFaas 登录提示行为。
return Socialite::driver('efaas')->with(['prompt' => 'select_account'])->redirect();
可用的提示选项包括
eFaas 提供商的可用方法
$provider = Socialite::driver('efaas'); $provider->parseJWT($token); // Parses a JWT token string into a Lcobucci\JWT\Token $provider->getSidFromToken($token); // Validates a given JWT token and returns the sid from the token $provider->getJwksResponse(false); // Returns the JWKs (JSON Web Keys) response as an array from the eFaas API. Optionally return the response as a json string using the optional boolean argument $provider->getPublicKey('5CDA5CF378397733DD33EFBDA82D0F317DCC1D53RS256'); // Returns the public key from JWKs for the given key id as a PEM key string
eFaas 用户可用方法和公共属性
$efaas_user->isMaldivian(); // Check if is a Maldivian $efaas_user->getDhivehiName(); // Full name in Dhivehi $efaas_user->getPhotoMimetype(); // Get the mimetype of the user photo $efaas_user->getPhotoExtension(); // Get the file extension of the user photo $efaas_user->getPhotoBase64(); // Get the user photo as a base64 encoded string $efaas_user->getPhotoDataUrl(); // Get the user photo as a data url $efaas_user->savePhoto('photo', './path/to/save'); // Saves the user photo to ./path/to/save/photo.jpg and returns the full file path $efaas_user->getAvatar(); // Alias of getPhotoBase64() $efaas_user->sid; // Session id of the user $efaas_user->id_token; // ID Token of the user $efaas_user->token; // Access token of the user
更改 eFaas 请求作用域
默认情况下,此包会将所有可用的作用域添加到 eFaas 重定向中。您可以通过发布包配置文件并更改作用域来修改默认作用域。要按请求自定义作用域,您可以在重定向期间覆盖作用域。
return Socialite::driver('efaas')->setScopes(['efaas.openid', 'efaas.profile'])->redirect();
从 eFaas 用户对象获取 eFaas 数据
$id_number = $oauth_user->idnumber;
eFaas 可用数据字段
不同的作用域与不同的数据相关联。默认情况下,包括所有作用域,因此您应该能够获取所有数据字段。
作用域: efaas.openid
作用域: efaas.profile
作用域: efaas.email
作用域: efaas.mobile
作用域: efaas.birthdate
作用域: efaas.photo
作用域: efaas.work_permit_status
作用域: efaas.passport_number
作用域: efaas.country
作用域: efaas.permanent_address
以下是 EfaasAddress
对象的字段
EfaasAddress
类还具有以下方法
$permanent_address = $efaas_user->permanent_address; $permanent_address->getFormattedAddress(); // Get the address with the ward abbreviation. eg: M. Blue Light $permanent_address->getDhivehiFormattedAddress(); // Get the address in Dhivehi with the ward abbreviation. eg: މ. ބުލޫ ލައިޓް
测试
您可以使用以下方式运行测试
./vendor/bin/phpunit
更新日志
有关最近更改的更多信息,请参阅 更改日志。
贡献
有关详细信息,请参阅 贡献指南。
安全
如果您发现任何安全问题,请通过电子邮件发送到 info@javaabu.com,而不是使用问题跟踪器。
致谢
许可
MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件。