pallant/laravel-aws-cognito-auth

Laravel 的一个认证驱动程序,用于在 AWS Cognito 用户池中进行用户认证

v1.2.0 2019-07-24 15:12 UTC

This package is not auto-updated.

Last update: 2024-09-28 20:40:52 UTC


README

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

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

内容

安装和配置

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

安装

pallant/laravel-aws-cognito-auth 添加到 composer.json 并运行 composer update 以拉取最新版本

"pallant/laravel-aws-cognito-auth": "~1.0"

或使用 composer require

composer require pallant/laravel-aws-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()方法,该方法在认证尝试失败时会被调用。该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' => [...],
]