dev-object/laravel-cognito-auth

Laravel 的认证驱动程序,用于在 AWS Cognito 用户池中验证用户

dev-main 2021-08-30 07:44 UTC

This package is not auto-updated.

Last update: 2024-09-24 22:06:28 UTC


README

这是一个用于 Laravel 5 的简单认证包,用于在 Amazon Cognito 用户池中验证用户。

该包与 Laravel 的原生认证系统兼容,允许验证已在 Amazon Cognito 用户池中注册的用户。它不提供用户管理功能,例如将用户注册到用户池、密码重置等。

内容

安装和设置

此包使用aws-sdk-php-laravel 包。除了设置和配置此包外,您还需要配置aws-sdk-php-laravel 以使认证工作。下面是如何操作的说明。如果您已经安装、设置和配置了aws-sdk-php-laravel,则可以跳过下面提到的部分。

安装

dev-object/laravel-cognito-auth 添加到 composer.json 并运行 composer update 以获取最新版本

"dev-object/laravel-cognito-auth": "~1.0"

或使用 composer require

composer require dev-object/laravel-cognito-auth

将服务提供者和 aws-sdk-php-laravel 服务提供者添加到 config/app.php 中的 providers 数组。

'providers' => [
    ...
    Aws\Laravel\AwsServiceProvider::class,
    Pallant\LaravelAwsCognitoAuth\ServiceProvider::class,
    ...
]

打开 app/Http/Kernel.php 并将默认的 \Illuminate\Session\Middleware\AuthenticateSession::class 中间件替换为 \Pallant\LaravelAwsCognitoAuth\AuthenticateSession::class

protected $middlewareGroups = [
    'web' => [
        ...
        \Pallant\LaravelAwsCognitoAuth\AuthenticateSession::class,
        ...
    ],
];

通过运行以下命令将配置文件以及 aws-sdk-php-laravel 配置文件发布到您的 config 目录:

php artisan vendor:publish --provider="Pallant\LaravelAwsCognitoAuth\ServiceProvider"

php artisan vendor:publish --provider="Aws\Laravel\AwsServiceProvider"

配置

打开 config/auth.php 并将默认保护者的驱动设置为 aws-cognito。默认情况下,默认保护者是 web,因此您的 config/auth.php 可能看起来像这样:

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

...

'guards' => [
    'web' => [
        'driver' => 'aws-cognito',
        'provider' => 'users',
    ],
]

打开 config/aws-cognito-auth.php 并添加您的 AWS Cognito 用户池的 ID 和用户池应用的用户池 client-id

'pool-id' => '<xxx-xxxxx>',

...

'apps' => [
    'default' => [
        'client-id' => '<xxxxxxxxxx>',
        'refresh-token-expiration' => 30,
    ],
]

当为您的用户池创建应用时,默认的刷新令牌过期时间为 30 天。如果您为您的应用设置了不同的过期时间,请确保相应地更新配置文件中的 refresh-token-expiration 值。

'apps' => [
    'default' => [
        'client-id' => '<xxxxxxxxxx>',
        'refresh-token-expiration' => <num-of-days>,
    ],
]

打开 config/aws.php 文件并将 region 值设置为您的用户池所在的区域。使用 php artisan vendor:publish --provider="Aws\Laravel\AwsServiceProvider" 命令创建的默认 config/aws.php 文件不包括 IAM 凭据属性,因此您需要手动添加它们。将以下内容添加到 config/aws.php 文件中,其中 key 是 IAM 用户访问密钥 ID,secret 是相应的密钥:

'credentials' => [
    'key' => <xxxxxxxxxx>,
    'secret' => <xxxxxxxxxx>,
]

您的最终 config/aws.php 应该看起来像这样:

'credentials' => [
    'key' => <xxxxxxxxxx>,
    'secret' => <xxxxxxxxxx>,
],
'region' => <xx-xxxx-x>,
'version' => 'latest',
'ua_append' => [
    'L5MOD/' . AwsServiceProvider::VERSION,
],

用户表

Cognito 不被视为“用户数据库”,仅用于授权用户。只有当用户已在应用程序数据库中存在时,才会向 Cognito 发出请求。这意味着您仍然需要一个填充有您想要验证的用户的 users 表。至少,此表需要 idemailremember_token 字段。

在Cognito中,每个用户都有一个用户名。当使用Cognito进行认证时,此包将需要一个用户的属性与Cognito用户名匹配。默认情况下,它使用用户的电子邮件属性。

如果您想使用不同的属性来存储用户的Cognito用户名,则可以通过首先在您的users表中添加一个新字段,例如cognito_username,然后在config/aws-cognito-auth.php文件中将username-attribute设置为该字段的名称来实现。

用法

安装和配置后,认证工作方式与Laravel本地认证相同。有关详细信息,请参阅Laravel的文档

认证

认证

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
]);

认证并记住

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], true);

获取认证用户

Auth::user();

注销

Auth::logout();

除了默认功能外,还提供了一些额外的方法来访问用户的Cognito访问令牌、ID令牌等。

Auth::getCognitoAccessToken();
Auth::getCognitoIdToken();
Auth::getCognitoRefreshToken();
Auth::getCognitoTokensExpiryTime();
Auth::getCognitoRefreshTokenExpiryTime();

处理失败的认证

AWS Cognito可能由于多种原因而无法进行认证,从简单地输入错误的凭据,到在用户成功认证之前需要额外的检查或操作。

因此,包中提供了几个选项,以适当地处理失败尝试。

方法

您可以通过在调用Auth::attempt()Auth::validate()方法时传递额外的$errorHandler参数来指定如何处理失败尝试。

Auth::attempt(array $credentials, [bool $remember], [$errorHandler]);

Auth::validate(array $credentials, [$errorHandler]);
无错误处理

如果没有传递$errorHandler,则所有失败的认证尝试都会被内部处理和抑制,并且Auth::attempt()Auth::validate()方法将简单地返回truefalse,表示认证尝试是否成功。

抛出异常

要将Auth::attempt()Auth::validate()方法抛出异常,请将AWS_COGNITO_AUTH_THROW_EXCEPTION作为$errorHandler参数传递。

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], false, AWS_COGNITO_AUTH_THROW_EXCEPTION);

Auth::validate([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], AWS_COGNITO_AUTH_THROW_EXCEPTION);

如果认证失败,则将抛出\Pallant\LaravelAwsCognitoAuth\AuthAttemptException异常,可以通过调用异常的getResponse()方法来访问底层错误。关于AuthAttemptException

try {
    Auth::attempt([
        'email' => 'xxxxx@xxxxx.xx',
        'password' => 'xxxxxxxxxx',
    ], false, AWS_COGNITO_AUTH_THROW_EXCEPTION);
} catch (\Pallant\LaravelAwsCognitoAuth\AuthAttemptException $e) {
    $response = $e->getResponse();
    // Handle error...
}
返回尝试实例

要使Auth::attempt()Auth::validate()方法返回尝试对象,请将AWS_COGNITO_AUTH_RETURN_ATTEMPT作为$errorHandler参数传递。

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], false, AWS_COGNITO_AUTH_RETURN_ATTEMPT);

Auth::validate([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], AWS_COGNITO_AUTH_RETURN_ATTEMPT);

当使用AWS_COGNITO_AUTH_RETURN_ATTEMPT时,两个方法都将返回一个\Pallant\LaravelAwsCognitoAuth\AuthAttempt实例,可以用来检查认证尝试是否成功。

$attempt = Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], false, AWS_COGNITO_AUTH_RETURN_ATTEMPT);

if ($attempt->successful()) {
    // Do something...
} else {
    $response = $attempt->getResponse();
    // Handle error...
}

对于失败的认证尝试,可以使用尝试实例的getResponse()方法来访问底层错误。此方法将返回一个包含不同值的数组,具体取决于失败尝试的原因。

在AWS Cognito API抛出异常的事件中,例如使用无效凭据时,返回的数组将包含原始异常。

[
    'exception' => CognitoIdentityProviderException {...},
]

在AWS Cognito API由于其他原因无法认证的事件中,例如必须通过挑战时,返回的数组将包含错误详情。

[
    'ChallengeName' => 'NEW_PASSWORD_REQUIRED',
    'Session' => '...',
    'ChallengeParameters' => [...],
]
使用闭包

要通过闭包处理失败的认证尝试,请将闭包作为Auth::attempt()Auth::validate()方法的$errorHandler参数传递。

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], false, function (\Pallant\LaravelAwsCognitoAuth\AuthAttemptException $e) {
    $response = $e->getResponse();
    // Handle error...
});

Auth::validate([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], function (\Pallant\LaravelAwsCognitoAuth\AuthAttemptException $e) {
    $response = $e->getResponse();
    // Handle error...
};

如果认证失败,则将运行闭包,并传递一个\Pallant\LaravelAwsCognitoAuth\AuthAttemptException实例,可以用来通过调用异常的getResponse()方法来访问底层错误。关于AuthAttemptException

使用自定义类

要通过自定义类处理失败的认证尝试,请将类的名称作为Auth::attempt()Auth::validate()方法的$errorHandler参数传递。

Auth::attempt([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], false, \App\MyCustomErrorHandler::class);

Auth::validate([
    'email' => 'xxxxx@xxxxx.xx',
    'password' => 'xxxxxxxxxx',
], \App\MyCustomErrorHandler::class);

错误处理类应该有一个 handle() 方法,当身份验证尝试失败时将被调用。该方法将接收一个 \Pallant\LaravelAwsCognitoAuth\AuthAttemptException 实例,可以通过调用异常的 getResponse() 方法来访问底层错误。有关 AuthAttemptException 的说明

<?php

namespace App;

use Pallant\LaravelAwsCognitoAuth\AuthAttemptException;

class MyCustomErrorHandler
{
    public function handle(AuthAttemptException $e)
    {
        $response = $e->getResponse();
        // Handle error...
    }
}

默认错误处理器

除了在线定义错误处理程序之外,您还可以在 config/aws-cognito-auth.php 文件中定义默认错误处理程序。上面详细说明了相同的错误处理方法。当使用 AWS_COGNITO_AUTH_THROW_EXCEPTIONAWS_COGNITO_AUTH_RETURN_ATTEMPT 时,将值设为字符串,不要使用常量。

抛出异常

'errors' => [
    'handler' => 'AWS_COGNITO_AUTH_THROW_EXCEPTION',
],

返回尝试

'errors' => [
    'handler' => 'AWS_COGNITO_AUTH_RETURN_ATTEMPT',
],

使用闭包

'errors' => [
    'handler' => function (\Pallant\LaravelAwsCognitoAuth\AuthAttemptException $e) {
        $e->getResponse();
        // Do something...
    },
],

使用自定义类

'errors' => [
    'handler' => \App\MyCustomErrorHandler::class,
],

关于 AuthAttemptException

当使用 AWS_COGNITO_AUTH_THROW_EXCEPTION 错误处理程序时,将抛出 \Pallant\LaravelAwsCognitoAuth\AuthAttemptException 异常;或者当使用错误处理的 Clousre 方法时,将其作为参数传递。

异常的 getResponse() 方法将返回一个包含不同值的数组,这些值取决于失败尝试的原因。

在AWS Cognito API抛出异常的事件中,例如使用无效凭据时,返回的数组将包含原始异常。

[
    'exception' => CognitoIdentityProviderException {...},
]

在 AWS Cognito API 由于某些其他原因(例如,必须通过挑战)无法进行身份验证的事件中,返回的数组将包含错误详情。

[
    'ChallengeName' => 'NEW_PASSWORD_REQUIRED',
    'Session' => '...',
    'ChallengeParameters' => [...],
]