websitinu / laravel-socialite-google-one-tap
一个轻量级的包,用于在已安装Socialite的Laravel Web应用程序中安装Google One Tap登录
Requires
- php: ^8.0
- ext-json: *
- google/apiclient: ^2.16
- socialiteproviders/manager: ^4.6
README
轻量级包,用于安装Laravel Socialite的Google One Tap提供程序
安装Laravel Socialite Google One Tap
composer require websitinu/laravel-socialite-google-one-tap
使用
设置Google项目
首先,您可能需要在 Google Cloud控制台 中创建一个新的项目,设置OAuth同意屏幕并创建一个新的OAuth客户端ID。在凭据菜单中,您可以找到客户端ID和客户端密钥,这些用于身份验证。
添加配置
您需要将客户端ID和客户端密钥存储在您的.env文件中,并将配置添加到config/services.php中。您还需要添加一个重定向URL,该URL将用于Google One Tap的登录和注册。此包针对Google One Tap的特定.env值,以避免与标准Google Socialite提供程序发生冲突。
# .env GOOGLE_CLIENT_ID_ONE_TAP=176204740264-36ufetlsp0u32ont3ag091fsf5ssmfq2q5.apps.googleusercontent.com GOOGLE_CLIENT_SECRET_ONE_TAP=GOCSPuX-4-h099j3hOKcAWmCsE0kgyvdg5nU GOOGLE_LOGIN_URI_ONE_TAP=/google-one-tap
# config/services.php return [ // other providers 'laravel-google-one-tap' => [ 'client_id' => env('GOOGLE_CLIENT_ID_ONE_TAP'), 'client_secret' => env('GOOGLE_CLIENT_SECRET_ONE_TAP'), 'redirect' => env('GOOGLE_LOGIN_URI_ONE_TAP'), ], ];
添加提供程序事件监听器
配置包的监听器以监听SocialiteWasCalled事件。将事件添加到app/Providers/EventServiceProvider中的listen[]数组中。有关详细说明,请参阅基本安装指南。
# 例如,在Laravel 11+
在app/providers/AppServiceProvider.php。
namespace App\Providers; use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; use LaravelSocialite\GoogleOneTap\LaravelGoogleOneTapServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. */ public function boot(): void { Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) { $event->extendSocialite('laravel-google-one-tap', LaravelGoogleOneTapServiceProvider::class); }); } }
# 例如,在Laravel 10或以下版本
在app/providers/AppServiceProvider.php。
namespace App\Providers; use Illuminate\Support\ServiceProvider; use LaravelSocialite\GoogleOneTap\LaravelGoogleOneTapServiceProvider; class EventServiceProvider extends ServiceProvider { protected $listen = [ \SocialiteProviders\Manager\SocialiteWasCalled::class => [ // other providers LaravelGoogleOneTapServiceProvider::class, ], ]; }
前端使用
Google One Tap需要在前后端进行特定的实现。
前端
在您想要使用Google One Tap的每个页面上,您需要在html模板的头部包含以下脚本。
@guest <script src="https://#/gsi/client" async defer></script> @endguest
实际的Google One Tap提示可以通过javascript或html来启动。以下代码处理html端的服务器端响应。您可以将此代码放在任何位置。您还可以将data-client_id和data-login_uri添加到任何现有的html元素中。有关更多设置和变体的详细信息,例如完整的javascript实现,请参阅参考资料。
@guest <div id="g_id_onload" data-auto_select="true" data-client_id="{{ config('services.laravel-google-one-tap.client_id') }}" data-login_uri="{{ config('services.laravel-google-one-tap.redirect') }}" data-use_fedcm_for_prompt="true" data-_token="{{ csrf_token() }}" ></div> @endguest
由于Google One tap正在迁移到FedCM,因此此元素的风格不会产生影响,这意味着如果浏览器支持,提示将由浏览器本身处理。
对于注销,您应该在注销按钮中添加一个g_id_signout类,以避免由于前一个片段中的data-auto_select而产生的重定向循环。
<form action="{{ route('logout') }}" method="post"> @csrf <button class="g_id_signout">Sign out</button> </form>
当用户关闭Google One Tap提示时,Google One Tap有一个冷却期。用户关闭提示的频率越高,提示重新出现给用户的时间就越长。因此,您需要包含一个登录按钮作为Google Sign-In提示的回退。您可能只想在登录和注册页面上包含此按钮。只需需要数据类型字段。
<div class="g_id_signin" data-type="standard"></div>
后端
Google One Tap 是基于 OAuth 构建的,但与使用访问令牌和刷新令牌的方式不同,它使用的是用于认证的 JWT 令牌。在此上下文中不会使用 redirect() 和 refreshToken() 方法,并将抛出 Error 以作为提醒。
您的控制器无需重定向用户,而是可以直接解析令牌来代替解析用户。
use Laravel\Socialite\Facades\Socialite; return Socialite::driver('laravel-google-one-tap')->userFromToken($token);
此方法将返回 JWT 令牌的有效负载或如果提供的令牌无效,将抛出 Error。
有效负载数组
连接有效负载
包含 email 的有效负载后,您现在可以处理用户流程,在用户完成与 Google One Tap 提示的交互后。这通常涉及两种情况之一:如果电子邮件不在您的数据库中,则注册用户;如果您已注册具有此电子邮件的用户,则登录用户。
// routes/web.php use App\Controllers\GoogleOneTapController; use Illuminate\Support\Facades\Route; Route::post('google-one-tap', [GoogleOneTapController::class, 'connect']) ->middleware('guest') ->name('google-one-tap.Connect');
// GoogleOneTapController.php use App\Models\User; use Illuminate\Http\Request; use Laravel\Socialite\Facades\Socialite; use LaravelSocialite\GoogleOneTap\InvalidIdToEx; public function connect(Request $request) { // Verify and validate JWT received from Google One Tap prompt try { $googleUser = Socialite::driver('laravel-google-one-tap')->userFromToken($request->input('credential')); } catch (InvalidIdToEx $exception) { return response()->json(['error' => $exception]); } // Log the user in if the email is associated with a user try { $googleUser = User::where('email', $googleUser['email'])->firstOrfail(); } catch (\Exception $ex) { $user = User::create([ 'name' => $googleUser->getName(), 'lastName' => $googleUser->getNickName(), 'provider_name' => 'google-one-tap', 'email' => $googleUser->getEmail(), 'password' => Hash::make($googleUser->getId()), 'email_verified_at' => $googleUser->user['email_verified'] ? now() : null, 'profile_photo_path' => $googleUser->getAvatar() ]); Auth::login($user, $remember = true); return redirect()->route('home'); } Auth::login($googleUser, $remember = true); // Send user to Home return redirect()->route('home'); }
参考资料
- https://developers.google.com/identity/gsi/web/guides/overview
- https://developers.google.com/identity/gsi/web/reference/html-reference
- https://developers.google.com/identity/gsi/web/reference/js-reference
- https://github.com/googleapis/google-api-php-client
- https://googleapis.github.io/google-api-php-client/main/
许可
此软件包采用 MIT 许可证(MIT)许可。有关更多详细信息,请参阅 LICENSE。
