sun-asterisk/php-auth

1.1.0 2023-11-06 03:29 UTC

This package is auto-updated.

Last update: 2024-09-06 06:40:34 UTC


README

CILicense

🌟 简介

Sun* Auth 是一个库,旨在为 Web/移动应用程序提供身份验证和授权功能。它使用现代技术构建,并提供了一系列功能,使得它易于集成到现有应用程序中。

使用 Sun* Auth 的一个关键原因是其易于使用。它提供了一个简单的库,使得向任何应用程序添加身份验证和授权变得容易。此外,它设计得高度可定制,允许开发者根据其特定需求进行定制。

使用 Sun* Auth 可以节省开发者的时间和精力,因为我们不必独立编写和测试复杂的身份验证和授权功能。此外,Sun* Auth 提供了一个简单易懂的库,使其易于集成到现有的 Web/移动应用程序中。

Sun* Auth 提供的一些功能包括用户注册和登录、密码重置和恢复。

🔌 安装

通过 Composer 安装包

composer require sun-asterisk/php-auth

Laravel

将服务提供者添加到 config/app.php 配置文件中的 providers 数组中,如下所示

<?php
# config/app.php
return [
    // ...
    'providers' => [
        // ...
        SunAsterisk\Auth\SunServiceProvider::class
    ]
];

发布配置文件

php artisan vendor:publish --provider="SunAsterisk\Auth\SunServiceProvider" --tag=sun-asterisk

Lumen

<?php
// bootstrap/app.php

$app->register(SunAsterisk\Auth\SunServiceProvider::class);

配置

mkdir -p config
cp vendor/sun-asterisk/config/sun-asterisk.php config/sun-asterisk.php

其他

use SunAsterisk\Auth\Factory;

$configs = config('/path/to/sun-asterisk.php')

$factory = (new Factory)->withConfig($configs);
$service = $factory->createAuthJwt();

配置

mkdir -p config
cp vendor/sun-asterisk/config/sun-asterisk.php config/sun-asterisk.php

审查配置文件

config/sun-asterisk.php
详细
<?php

return [
  'auth' => [
      /*
      |---------------------------------------------------------
      | Attribute login
      |---------------------------------------------------------
      |
      | E.g. 'email or username'
      |
      */
      'login_username' => 'email',
      /*
      |---------------------------------------------------------
      | Attribute field_credentials
      |---------------------------------------------------------
      | Use 1 of the list for authentication
      | E.g. 'username or email or phone'
      |
      */
      'field_credentials' => [
          'email',
      ],
      /*
      |---------------------------------------------------------
      | Attribute token_payload_fields
      |---------------------------------------------------------
      | Use the items in the list to create an access token
      |
      | E.g. 'id or email'
      |
      */
      'token_payload_fields' => [
          'id',
          'email',
      ],
      /*
      |---------------------------------------------------------
      | Attribute login
      |---------------------------------------------------------
      |
      | E.g. 'password or passwd'
      |
      */
      'login_password' => 'password',
      /*
      |---------------------------------------------------------
      | Model login
      |---------------------------------------------------------
      |
      | E.g. 'App\Models\User::class or App\Models\Admin::class'
      |
      */
      'model' => App\Models\User::class,
      /*
      |---------------------------------------------------------
      | Token forgot password
      |---------------------------------------------------------
      |
      | Default 5 minutes
      | E.g. '5'
      |
      */
      'token_expires' => 5, // minutes
      /*
      |---------------------------------------------------------
      | Key for jwt access token
      |---------------------------------------------------------
      |
      | E.g. 'xxxx'
      |
      */
      'jwt_key' => 'jwt_key',
      /*
      |---------------------------------------------------------
      | Key for jwt refresh access token
      |---------------------------------------------------------
      |
      | E.g. 'xxxx'
      |
      */
      'jwt_refresh_key' => 'jwt_refresh_key',
      /*
      |---------------------------------------------------------
      | TTL for jwt
      |---------------------------------------------------------
      |
      | Default 60 minutes
      | E.g. '60'
      |
      */
      'jwt_ttl' => 60, // minutes
      /*
      |---------------------------------------------------------
      | TTL for refresh access token
      |---------------------------------------------------------
      |
      | Default 20160 minutes
      | E.g. '60'
      |
      */
      'jwt_refresh_ttl' => 20160, // minutes
      /*
      |---------------------------------------------------------
      | use Socialite Providers for social login
      |---------------------------------------------------------
      |
      | Default false
      |
      */
      'enabled_social' => false,
  ],
];

 

使用

我们将以 Laravel 为例说明使用方法。

配置 Auth 守护者

在 config/auth.php 文件中,您需要做一些更改以进行配置

'guards' => [
    'api' => [
        'driver' => 'sun',
        'provider' => 'users',
    ],
]

将 auth:api 中间件添加到需要登录认证的路由中

Route::group([
    'middleware' => 'auth:api',
], function ($router) {
    // routes
}

使用 JWT 注入依赖项

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use SunAsterisk\Auth\Contracts\AuthJWTInterface;

class AuthController extends Controller
{
    protected AuthJWTInterface $service;

    public function __construct(AuthJWTInterface $service)
    {
        $this->service = $service;
    }
    ...
}

使用 Session 注入依赖项

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use SunAsterisk\Auth\Contracts\AuthSessionInterface;

class AuthController extends Controller
{
    protected AuthSessionInterface $service;

    public function __construct(AuthSessionInterface $service)
    {
        $this->service = $service;
    }
    ...
}

登录

POST /login
  • 参数
  • 响应

JWT 使用示例

详细
public function login(Request $request)
{
    $params = $request->only(['username', 'password']);
    // use service package
    $rs = $this->service->login($params, [], function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    });

    return response()->json($rs['auth']);
}
 

Session 使用示例

详细
public function showLoginForm()
{
    return view('auth.login');
}

public function login(Request $request)
{
    $params = $request->only(['email', 'password']);

    $this->service->login($params, [], function ($entity) {
        //
    });

    return redirect()->intended('home');
}
 

示例

curl -X 'POST' \
  'https:///api/login' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "user1234",
  "password": "passwordRequired@123"
}'
{
  "refresh_token": "eyJ0eXAiOiJKV1QiLC...",
  "access_token": "eyJ0eXAiOiJKV1...",
  "token_type": "bearer",
  "expires_at": 1676281826
}

登出

POST /logout
  • 参数
  • 响应

JWT 使用示例

详细
public function logout(Request $request)
{
   auth('api')->logout();

   return response()->noContent();
}
 

Session 使用示例

详细
public function logout(Request $request)
{
    $this->service->logout($request);

    return view('auth.login');
}
 

示例

curl -X 'POST' \
  'https:///api/logout' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1...' \
  -d ''
{}

注册

POST /register
  • 参数
  • 响应

JWT 使用示例

详细
public function register(Request $request)
{
    $rules = [];
    $fields = $request->only(['username', 'password', 'email']);

    $result = $this->service->register($fields, $rules, function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    });

    return response()->json($result);
}
 

Session 使用示例

详细
public function showRegistrationForm()
{
    return view('auth.register');
}

public function register(Request $request)
{
    $fields = $request->only(['username', 'password', 'email']);
    $fields['name'] = $fields['username'];

    $this->service->register($fields, [], function ($entity) {
        //
    });

    return redirect()->intended('home');
}
 

如果您想在注册后进行用户认证,请将 $setGuard 参数设置为 true

$this->service->register($fields, [], function ($entity) {
        //
    }, true);

示例

curl -X 'POST' \
  'https:///api/register' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "user123456",
  "password": "passwordRequired@123",
  "email": "testuser02@local.ltd"
}'
{
  "id": 13,
  "email": "testuser02@local.ltd",
  "username": "user123456"
}

忘记密码

POST /forgot-password
  • 参数
  • 响应

创建 postForgotPassword 函数如下

详细
# App\Http\Controllers\AuthController
public function postForgotPassword(Request $request)
{
    $email = $request->email;
    $status = $this->service->postForgotPassword($email, function ($token, $user) {
        // Use send mail from framework
        sendEmail($user, $token);
    });

    return response()->json([
        'ok' => $status,
        'type' => 'forgotPassword',
    ]);
}
 

创建 confirm 函数如下

详细
public function confirm(Request $request)
{
   $token = $request->token;
   $status = $this->service->verifyToken($token);

   return response()->json([
       'ok' => $status,
   ]);
}
 

创建 newPassword 函数如下

详细
# App\Http\Controllers\AuthController
public function postNewPassword(Request $request)
{
   $params = $request->only(['password', 'token']);
   $status = $this->service->changePassword($params, null, function ($user, &$attr) {
       // Update attr
   });

   return response()->json([
       'ok' => $status,
       'type' => 'newPassword',
   ]);
}
 

示例

curl -X 'POST' \
  'https:///api/forgot-password' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "testuser01@local.ltd"
}'
{
  "ok": true,
  "type": "forgotPassword"
}

验证

GET /confirm
  • 参数
  • 响应
curl -X 'GET' \
  'https:///api/confirm?token=eyJ0eXAiOiJKV1QiLC...' \
  -H 'accept: application/json'
{
  "ok": true
}

新密码

POST /new-password
  • 参数
  • 响应
curl -X 'POST' \
  'https:///api/new-password' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "password": "passwordRequired@123",
  "token": "eyJ0eXAiOiJKV1QiLC..."
}'
{
  "ok": true,
  "type": "newPassword"
}

刷新令牌

POST /refresh
  • 参数
  • 响应

创建刷新函数如下

# App\Http\Controllers\AuthController;
public function refresh(Request $request)
{
    $token = $request->refresh_token;

    $rs = $this->service->refresh($token);

    return response()->json($rs);
}

示例

curl -X 'POST' \
  'https:///api/refresh' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "refresh_token": "refresh_token_secret"
}'
{
  "refresh_token": "eyJ0eXAiOiJKV1QiLC...",
  "access_token": "eyJ0eXAiOiJKV1...",
  "token_type": "bearer",
  "expires_at": 1676281826
}

自定义社交登录

使用 Google 登录

要使用它,您需要通过 composer 安装 socialiteproviders/google

composer require socialiteproviders/google

将配置添加到 config/services.php

# config/services.php
...
'google' => [    
  'client_id' => env('GOOGLE_CLIENT_ID'),  
  'client_secret' => env('GOOGLE_CLIENT_SECRET'),  
  'redirect' => env('GOOGLE_REDIRECT_URI'),
],

将 config/sun-asterisk.php 中的 config enabled_social 设置为 true

config/sun-asterisk.php

详细
# config/sun-asterisk.php
...
/*
|---------------------------------------------------------
| use Socialite Providers for social login
|---------------------------------------------------------
|
| Default false
|
*/
'enabled_social' => true,
 

routes/web.php

详细
# routes/web.php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use SunAsterisk\Auth\Contracts\AuthSocialInterface;
...

// Redirect Endpoint
Route::get('social/{provider}/redirect', function (Request $request) {
    $provider = $request->provider;
    // use service from package
    return app(AuthSocialInterface::class)->socialSignIn($provider);
});

// Callback Endpoint
Route::get('social/{provider}/callback', function (Request $request) {
    $provider = $request->provider;
    // use service from package
    $socialUser = app(AuthSocialInterface::class)->socialCallback($provider);

    $user = \App\Models\User::updateOrCreate([
        'social_id' => $socialUser->id,
        'social_type' => $provider,
    ], [
        'name' => $socialUser->name,
        'email' => $socialUser->email,
        'avatar' => $socialUser->avatar,
    ]);

    Auth::login($user);

    return redirect('/dashboard');
});
 

架构

架构登录

工作流程

Sun_ Auth _ Architecture Design-Login (1)

解释

接口

/**
* [login]
* @param  array         $credentials [The user's attributes for authentication.]
* @param  array|null    $attributes  [The attributes use for query.]
* @param  callable|null $callback    [The callback function has the entity model.]
* @return [array]
*/
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array;
  1. 验证器
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
  $this->loginValidator($credentials)->validate();
  ...
}
...
protected function loginValidator(array $data)
{
    return Validator::make($data, [
        $this->username()  => 'required',
        $this->passwd() => 'required',
    ]);
}
  1. 按属性查找项
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    $item = $this->repository->findByAttribute($attributes);
}
  1. 比较哈希密码
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    if (! $item || ! Hash::check(Arr::get($credentials, $this->passwd()), $item->{$this->passwd()})) {
        throw ValidationException::withMessages([
            'message' => $this->getFailedLoginMessage(),
        ]);
    }
}
  1. 从 jwt 生成 accessToken & refreshToken
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    $payload = $this->jwt->make($itemArr)->toArray();
    $payloadRefresh = $this->jwt->make($itemArr, true)->toArray();

    $jwt = $this->jwt->encode($payload);
    $refresh = $this->jwt->encode($payloadRefresh, true);

    $this->tokenMapper->add($payload, $refresh);
}

login 方法将返回一个数组

'item' => $itemArr,
'auth' => [
    'refresh_token' => 'eyJhbGciOiJIUzI1NiIsIn...',
    'access_token' => 'eyJiwibmFtZSI6Ikpva...',
    'token_type' => 'bearer',
    'expires_at' => 1675742447,
],
  • $itemArr 是用户模型的对象数组。我们可以通过回调函数进行自定义,如下所示
# App\Http\Controllers\AuthController
$rs = $this->service->login($params, [], function ($entity) {
    // Custom $itemArr
    return $entity->only(['id', 'email', 'username']);
});

BTW:我们还可以更改登录流程的 SQL 查询,如下所示

# App\Http\Controllers\AuthController
$rs = $this->service->login(
    $params,
    [
        'username' => $params['username'],
        'is_active' => true, // custom query attributes
    ],
    function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    },
);

架构登出

工作流程

解释

  1. 将守护者设置为服务提供者
# SunAsterisk\Auth\SunServiceProvider
/**
 * Extend Laravel's Auth.
 *
 * @return void
 */
protected function extendAuthGuard(): void
{
    $this->app['auth']->extend('sun', function ($app, $name, array $config) {
    $storage = $app->make(Providers\Storage::class);
    $blackList = new SunBlacklist($storage);
    $jwt = new SunJWT($blackList, $app->config->get('sun-asterisk.auth'));
    $tokenMapper = new SunTokenMapper($storage);

    $guard = new SunGuard(
        $jwt,
        $app['auth']->createUserProvider($config['provider']),
        $app['request'],
        $tokenMapper
    );
    app()->refresh('request', $guard, 'setRequest');

    return $guard;
});
}
  1. SunGuard 中创建 logout 方法
# SunAsterisk\Auth\SunGuard
/**
 * Logout the user, thus invalidating the token.
 *
 * @return void
 */
public function logout()
{
    try {
        $token = $this->request->bearerToken();
        $rawToken = $this->jwt->decode($token);
        $refreshToken = $this->tokenMapper->pullRefreshToken($rawToken['jti']);

        $this->jwt->invalidate($token);
        if ($refreshToken) {
            $this->jwt->invalidate($refreshToken, true);
        }
    } catch (\Exception $e) {
        throw new Exceptions\JWTException($e->getMessage());
    }
}
  1. 使 tokenrefreshToken 失效
# SunAsterisk\Auth\SunJWT
public function invalidate(string $token, bool $isRefresh = false): bool
{
    if (! $this->blackList) {
        throw new Exceptions\JWTException('You must have the blacklist enabled to invalidate a token.');
    }

    $payload = $this->decode($token, $isRefresh, false);

    return $this->blackList->add($payload);
}

架构注册

工作流程

Sun_ Auth _ Architecture Design-Register

解释

接口

/**
* [register]
* @param  array         $fields    [The user's attributes for register.]
* @param  array         $rules     [The rules for register validate.]
* @param  callable|null $callback  [The callback function has the entity model.]
* @return [array]
*/
public function register(array $params = [], array $rules = [], callable $callback = null): array;
  1. 验证器
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    if (empty($rules)) {
        $rules = [
            'username' => ['required', 'string', "unique:{$table}," . $this->username()],
            'password' => [
                'required',
                'min:6',
                'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\x])(?=.*[!@#$%]).*$/',
            ],
        ];

        if (isset($params['email'])) {
            $rules['email'] = ['required', 'string', "unique:{$table},email"];
        }
    }
    ...
}
  1. 哈希密码
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    ...
    $params[$this->passwd()] = Hash::make($params[$this->passwd()]);
}
  1. 将参数插入数据库
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    ...
    $item = $this->repository->create($params);
}

register 方法将返回一个数组

自定义注册

您可以根据以下内容更改或验证属性

# App\Http\Controllers\AuthController
public function register(Request $request)
{
    $fields = $request->only(['password', 'email']);
    // customer validate
    $rules = [
        'email' => 'required|email',
        'password' => 'required',
    ];

    $result = $this->service->register($fields, $rules);

    return response()->json($result);
}

架构忘记密码

工作流程

Sun_ Auth _ Architecture Design-Resending confirmation request_email

解释

接口

/**
* [postForgotPassword]             
* @param  string        $email     [The user's email for receive token]
* @param  callable|null $callback  [The callback function response token & entity model.]
* @return [bool]
*/
public function postForgotPassword(string $email, callable $callback = null): bool;

/**
* [verifyForgotPasswordToken]
* @param  string        $token     [The token from user's email]
* @param  callable|null $callback  [The callback function has the token & entity model.]
* @return [bool]
*/
public function verifyToken(string $token, callable $callback = null): bool;

/**
* [changePassword]
* @param  array         $params    [The params for change password (passwd | ?old_passwd | ?token)]
* @param  int|null      $userId    [The user's id when user authenticate.]
* @param  callable|null $callback  [The callback function have the entity model & pointer of users's attributes.]
* @return [bool]
*/
public function changePassword(array $params = [], ?int $userId = null, callable $callback = null): bool;
  1. 验证电子邮件
# SunAsterisk\Auth\Services\AuthJWTService;
public function postForgotPassword(string $email, callable $callback = null): bool
{
   ...
   // Validate Email
   Validator::make(['email' => $email], [
       'email' => ['required', 'email'],
   ])->validate();

   // Check Email exists
   $item = $this->repository->findByAttribute(['email' => $email]);
   if (!$item) {
       throw ValidationException::withMessages([
           'message' => 'The email is invalid.',
       ]);
   }
   ...
}
  1. 生成令牌
# SunAsterisk\Auth\Services\AuthJWTService;
public function postForgotPassword(string $email, callable $callback = null): bool
{
   ...
   $obj = [
       'id' => $item->id,
       'created_at' => Carbon::now()->timestamp,
   ];

   $token = Crypt::encryptString(json_encode($obj));
   ...
}
  1. 验证令牌
# SunAsterisk\Auth\Services\AuthJWTService;
public function verifyToken(string $token, callable $callback = null): bool
{
     ...
     $objStr = Crypt::decryptString($token);
     $obj = json_decode($objStr, true);
     ...
     $diffSeconds = Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($obj['created_at']));

     if ($diffSeconds >= $this->config['token_expires'] * 60) {
          throw new AuthException('Token is invalid!');
     }
}
  1. 更改密码
# SunAsterisk\Auth\Services\AuthJWTService;
public function changePassword(array $params = [], ?int $userId = null, callable $callback = null): bool
{
   ...
   $user = null;
   $attr = [];

   // For usecase forgot password
   if (isset($params['token'])) {
       $this->verifyToken($params['token'], function ($entity) use (&$user) {
           $user = $entity;
       });
   }
   ...

   if ($user) {
       $attr[$this->passwd()] = Hash::make($params[$this->passwd()]);
       ...

       $this->repository->updateById($user->id, $attr);
   }
   ...
}

架构刷新令牌

工作流程

Sun_ Auth _ Architecture Design-Refresh token

解释

接口

/**
* [refresh]
* @param  string $refreshToken     [refresh_token for user get access_token]
* @param  callable|null $callback  [The callback function has the entity model.]
* @return [array]
*/
public function refresh(?string $refreshToken, callable $callback = null): array;
  1. 解码刷新令牌
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $payload = $this->jwt->decode($refreshToken ?: '', true);
}
  1. 比较刷新令牌的过期时间
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    if (Carbon::createFromTimestamp($payload['exp'])->lte(Carbon::now())) {
        throw new InvalidArgumentException('The RefreshToken is invalid.');
    }
}
  1. 验证用户是否存在
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $item = $this->repository->findById($sub?->id);
    if (!$item) {
        throw new InvalidArgumentException('The RefreshToken is invalid.');
    }
}
  1. 撤销所有访问令牌
# SunAsterisk\Auth\Services\AuthJWTService;
public function revoke(array $keys = []): bool
    {
        try {
            return $this->jwt->revoke($keys);
        } catch (\Exception $e) {
            throw new Exceptions\JWTException('Revoke token is wrong.');
        }
    }
  1. 重新生成访问令牌
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $payload = $this->jwt->make((array) $sub)->toArray();
    $jwt = $this->jwt->encode($payload);

    $this->tokenMapper->add($payload, $refreshToken);
}

方法刷新将返回一个数组

# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    return [
        'refresh_token' => 'eyJhbGciOiJIUzI1NiIsIn...',
        'access_token' => 'eyJiwibmFtZSI6Ikpva...',
        'token_type' => 'bearer',
        'expires_at' => 1675742447,
    ];
}

自定义社交登录架构

工作流程

Sun_ Auth _ Architecture Design-Social sign-in (1)

解释

接口

/**
* [socialSignIn]
* @param  string $provider                   [The Provider should received from https://socialiteproviders.com/about/]
* @return [Illuminate\Http\RedirectResponse]
*/
public function socialSignIn(?string $provider): RedirectResponse;

/**
* [socialCallback]
* @param  string $provider     [The Provider should received from https://socialiteproviders.com/about/]
* @return [stdClass]
*/
public function socialCallback(?string $provider): stdClass;
  1. 重定向
# SunAsterisk\Auth\Services\AuthSocialService
/**
 * [socialSignIn]
 * @param  string $provider [The Provider should received from https://socialiteproviders.com/about/]
 * @return [Illuminate\Http\RedirectResponse]
 */
public function socialSignIn(?string $provider): RedirectResponse
{
    try {
        return Socialite::driver($provider)->redirect();
    } catch (\Exception $e) {
        throw new InvalidArgumentException('provider is invalid!');
   
  1. 回调
# SunAsterisk\Auth\Services\AuthSocialService
/**
 * [socialCallback]
 * @param  string $provider [The Provider should received from https://socialiteproviders.com/about/]
 * @return [stdClass]
 */
public function socialCallback(?string $provider): stdClass
{
    try {
        return Socialite::driver($provider)->user();
    } catch (\Exception $e) {
        throw new InvalidArgumentException('provider is invalid!');
    }
}