websitinu/laravel-socialite-google-one-tap

一个轻量级的包,用于在已安装Socialite的Laravel Web应用程序中安装Google One Tap登录

v1.1.0 2024-05-24 15:27 UTC

This package is auto-updated.

Last update: 2024-09-24 16:23:43 UTC


README

轻量级包,用于安装Laravel Socialite的Google One Tap提供程序

Build Status Total Downloads Latest Stable Version License

安装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_iddata-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');


}

参考资料

许可

此软件包采用 MIT 许可证(MIT)许可。有关更多详细信息,请参阅 LICENSE