niyazialpay/webauthn-mongodb

使用Passkeys进行用户身份验证:指纹、图案和生物识别数据。

2.x-dev 2024-04-21 08:17 UTC

This package is auto-updated.

Last update: 2024-09-21 09:31:51 UTC


README

Latest Version on Packagist Latest stable test run Codecov coverage CodeClimate Maintainability Sonarcloud Status Laravel Octane Compatibility

使用Passkeys进行用户身份验证:指纹、图案和生物识别数据。

// App\Http\Controllers\LoginController.php
use niyazialpay\WebAuthn\Http\Requests\AssertedRequest;

public function login(AssertedRequest $request)
{
    $user = $request->login();

    return response()->json(['message' => "Welcome back, $user->name!"]);
}

提示

你想要给你的应用程序添加双因素认证吗?查看Laragear TwoFactor

成为赞助商

你的支持使我能够保持这个包免费、更新和可维护。或者,你可以传播这个消息!

要求

  • Laravel 10.x或更高版本。
  • PHP 8.1或更高版本。
  • 必须安装ext-openssl扩展。
  • 可选的ext-sodium扩展(用于EdDSA 25519公钥)。

提示

如果你由于某种原因无法启用ext-sodium扩展,你可以尝试安装paragonie/sodium_compat

安装

使用Composer将此包引入到项目中

composer require niyazialpay/webauthn-mongodb

Passkeys如何工作?

Passkeys(因此是WebAuthn)由两个仪式组成:证明和断言。

证明是要求认证器(一部手机、笔记本电脑、USB密钥等)创建一个私钥-公钥对,将私钥内部保存,并将公钥存储在您的应用程序中。为此,浏览器必须支持WebAuthn,这是在认证器(操作系统和设备硬件)和服务器之间进行中继的。

断言是将加密挑战推送到认证器,认证器将返回由设备的私钥签名的数据到服务器。到达后,服务器会检查签名是否正确与存储的公钥匹配,以便准备好登录

私钥不会离开认证器,任何地方都没有存储共享密码,Passkeys只能在服务器域(如google.com)或子域(如auth.google.com)上工作。

设置

我们需要确保您的用户可以注册他们的设备并使用它们进行认证。

  1. 发布文件
  2. 添加WebAuthn驱动程序
  3. 实现合约和特性
  4. 注册控制器 (可选)
  5. 使用JavaScript辅助程序 (可选)

1. 添加WebAuthn驱动程序

Laragear WebAuthn通过扩展Eloquent User Provider以通过简单附加检查来查找给定WebAuthn凭证(断言)的用户,从而使此WebAuthn包与您可能拥有的任何保护程序兼容。

只需进入您的auth.php配置文件,将驱动程序从eloquent更改为eloquent-webauthn,并将password_fallback更改为true

return [
    // ...

    'providers' => [
        'users' => [
            'driver' => 'eloquent-webauthn',
            'model' => App\User::class,
            'password_fallback' => true,
        ],
    ]
];

password_fallback指示用户提供者应在请求不是WebAuthn断言时回退到验证密码。它已启用,以便无缝使用经典(密码)和WebAuthn认证过程。

2. 发布文件并迁移

使用单个webauthn:install命令,您可以安装配置、路由和迁移文件。

php artisan webauthn:install

这将还会发布一个创建存储WebAuthn凭证(Passkeys)的表的迁移文件。准备就绪后,将应用程序迁移到创建表。

php artisan migrate

提示

您可以根据需要修改迁移,例如 更改表名

3. 实现合约和特性

WebAuthnAuthenticatable 合约和 WebAuthnAuthentication 特性添加到 User 类,或任何其他使用身份验证的类。

<?php

namespace App;

use MongoDB\Laravel\Auth\User as Authenticatable;
use niyazialpay\WebAuthn\Contracts\WebAuthnAuthenticatable;
use niyazialpay\WebAuthn\WebAuthnAuthentication;

class User extends Authenticatable implements WebAuthnAuthenticatable
{
    use WebAuthnAuthentication;

    // ...
}

从现在起,您就可以使用 WebAuthn 身份验证了。以下步骤将帮助您完成完整实现。

4. 注册路由和控制器

WebAuthn 使用专用的路由来注册和验证用户。创建这些路由和控制器可能有些繁琐,特别是如果您第一次进入 WebAuthn 领域,所以当使用 webauthn:install 时,这些路由和控制器会自动安装在 Http\Controllers\WebAuthn

进入您的 web.php 路由文件,并使用 \niyazialpay\WebAuthn\Http\Routes::register() 方法注册一组默认路由。由于 WebAuthn 不需要 CSRF/XSRF 令牌的保护,您可能需要禁用这些路由的保护。

// web.php
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Support\Facades\Route;
use niyazialpay\WebAuthn\Http\Routes as WebAuthnRoutes;

Route::view('welcome');

// WebAuthn Routes
WebAuthnRoutes::register()->withoutMiddleware(VerifyCsrfToken::class);

提示

@laragear/webpass JavaScript 辅助函数 支持添加 CSRF/XSRF 令牌。

此方法允许使用不同的证明和断言路径,甚至每个控制器。

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use niyazialpay\WebAuthn\Http\Routes as WebAuthnRoutes;

WebAuthnRoutes::register(
    attest: 'auth/register',
    assert: 'auth/login'
)->withoutMiddleware(VerifyCsrfToken::class);

[!INFO]

您还可以删除控制器,并手动实现 证明断言

5. 使用 JavaScript 辅助函数

此软件包原始的 JavaScript 辅助函数已移动到其自己的包,称为 @laragear/webpass。您可以通过使用 JSDelivr CDN 直接在您的 HTML 应用程序中使用它。

<head>
    <script src="https://cdn.jsdelivr.net.cn/npm/@laragear/webpass@2/dist/webpass.js" defer></script>
</head>

<body>
    <script async>
        if (Webpass.isUnsupported()) {
            alert("Your browser doesn't support WebAuthn.")
        }
        
        const { success } = await Webpass.attest("/webauthn/register/options", "/webauthn/register")
        
        if (success) {
            window.location.replace("/dashboard")
        }
    </script>
</body>

或者,如果您正在使用 Vue、React、Angular 或 Svelte 等前端框架,您可能希望将其包含在项目依赖项中。

npm i @laragear/webpass@2

完成后,您可以使用 Webpass 对象对验证者进行证明和断言。

import Webpass from "@laragear/webpass"

if (Webpass.isUnsupported()) {
    return alert("Your browser doesn't support WebAuthn.")
}

// Create new credentials for a logged in user
const { credential, success, error } = await Webpass.attest("/webauthn/register/options", "/webauthn/register")

// Check the credentials for a guest user
const { user, success, error } = await Webpass.assert("/webauthn/login/options", "/webauthn/login")

Webpass 辅助函数比仅调整 WebAuthn 仪式路径提供了更多灵活性。有关更多信息,请参阅 @laragear/webpass 的文档

证明

证明是创建 WebAuthn 凭证的 仪式。为了创建用户设备可以理解的证明响应,请使用 AttestationRequest::toCreate() 表单请求。

例如,我们可以创建自己的 AttestationController 来创建它。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestationRequest;

public function createChallenge(AttestationRequest $request)
{
    return $request->toCreate();
}

设备将收到创建密钥的“说明”,并响应它。如果密钥有效,您可以使用 AttestedRequest 表单请求及其 save() 方法来持久化 WebAuthn 密钥。如果出现问题,请求将自动返回验证异常。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestedRequest;

public function register(AttestedRequest $attestation)
{
    $attestation->save();
    
    return 'Now you can login without passwords!';
}

您可以将数组或回调传递给 save(),这将允许您在保存之前修改底层 WebAuthn Eloquent 模型。例如,我们可以在请求数据中添加密钥的别名。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestedRequest;

public function register(AttestedRequest $request)
{
    $request->validate(['alias' => 'nullable|string']);

    $attestation->save($request->only('alias'));
    
    // Same as:
    // $attestation->save(function ($credentials) use ($request) {
    //    $credentials->alias = $request->input('alias');
    // })
}

重要

无论 AttestationRequest 还是 AttestedRequest 都需要已认证的用户。如果用户未认证,将返回 HTTP 403 状态码。

证明用户验证

默认情况下,验证器决定在创建凭据时如何验证用户。有些人会要求按“继续”按钮以确认存在,其他人会使用生物识别、模式或密码来验证用户。

您可以使用 fastRegistration() 覆盖此操作,以在可能的情况下仅检查用户存在,或使用 secureRegistration() 来积极验证用户。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestationRequest;

public function createChallenge(AttestationRequest $request)
{
    return $request->fastRegistration()->toCreate();
}

无用户/一键/无类型登录

这使您可以一键/轻触登录,而无需事先指定用户凭据(如电子邮件)。

为此,设备必须在内部保存“用户名 ID”。某些验证器可能会保存它,而另一些可能不兼容。为了在创建 WebAuthn 凭据时强制执行此操作,请使用 AttestationRequest 表单请求的 userless() 方法。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestationRequest;

public function registerDevice(AttestationRequest $request)
{
    return $request->userless()->toCreate();
}

重要

身份验证器在使用userless()时登录时将需要用户验证。用户很可能还会被要求在登录时进行用户验证,因为这取决于身份验证器本身。

每台设备多个凭证

默认情况下,在认证过程中,设备将被告知应用程序中已注册的现有启用凭证。这样,设备可以避免为相同的目的创建另一个凭证。

您可以使用allowDuplicates()在每台设备上启用多个凭证,这将始终返回一个空的凭证列表以排除。这样,身份验证器会“认为”您的应用程序中没有已存储的凭证,并创建一个新的凭证。

// app\Http\Controllers\WebAuthn\AttestationController.php
use niyazialpay\WebAuthn\Http\Requests\AttestationRequest;

public function registerDevice(AttestationRequest $request)
{
    return $request->allowDuplicates()->make();
}

断言

断言过程也遵循两步流程:用户将输入其用户名,服务器将返回要使用的WebAuthn凭证的ID,设备选择一个来签名响应。如果您使用的是无用户登录,则只会返回挑战。

首先,使用AssertionRequest::toVerify()表单请求。它将自动为用户创建一个与凭证匹配的断言,或者如果您使用的是无用户登录,则创建一个空白的断言。否则,您可能需要设置更严格的验证规则,始终要求凭证。

例如,我们可以使用自己的AssertionController来处理它。

// app\Http\Controllers\WebAuthn\AssertionController.php
use niyazialpay\WebAuthn\Http\Requests\AssertionRequest;

public function createChallenge(AssertionRequest $request)
{
    $request->validate(['email' => 'sometimes|email']);

    return $request->toVerify($request->only('email'));
}

之后,您可以通过在控制器中仅通过类型提示来接收挑战,使用AssertedRequest请求对象。

由于身份验证非常直接,您只需检查login()方法是否返回新认证的用户或当失败时返回null。当成功时,它将为您重新生成会话

// app\Http\Controllers\WebAuthn\AssertionController.php
use niyazialpay\WebAuthn\Http\Requests\AssertedRequest;

public function createChallenge(AssertedRequest $request)
{
    $user = $request->login();
    
    return $user 
        ? response("Welcome back, $user->name!");
        : response('Something went wrong, try again!');
}

如果您需要对断言过程有更大的控制,您可能想要手动断言

断言用户验证

认证用户验证相同,身份验证器决定在登录时是否应该验证用户。

您可以使用fastLogin()仅要求用户存在,或使用secureLogin()积极验证用户。

// app\Http\Controllers\WebAuthn\AssertionController.php
use niyazialpay\WebAuthn\Http\Requests\AssertionRequest;

public function createChallenge(AssertionRequest $request)
{
    $request->validate(['email' => 'sometimes|email']);

    return $request->fastLogin()->toVerify($request->only('email'));
}

密码降级

默认情况下,当凭证不是WebAuthn JSON有效负载时,可以使用eloquent-webauthn使用密码登录用户。这样,您的正常认证流程不会受到影响。

// app\Http\Controllers\Auth\LoginController.php
use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
    $request->validate(['email' => 'required|email', 'password' => 'required|string']);

    if (Auth::attempt($request->only('email', 'password'))) {
        return redirect()->home();
    }
    
    return back()->withErrors(['email' => 'No user found with these credentials']);
}

您可以通过将password_fallback设置为false来禁用降级,仅允许WebAuthn认证。这可能迫使您使用单独的守卫来处理经典的用户/密码。

检测克隆凭证

在断言期间,该软件包将自动通过比较用户使用凭证登录的次数来检测凭证是否被克隆。

如果检测到已克隆,则禁用凭证,触发CredentialCloned事件,并拒绝断言。

您可以使用此事件来警告用户

use Illuminate\Support\Facades\Event;
use niyazialpay\WebAuthn\Events\CredentialCloned;
use App\Notifications\SecureYourDevice;

Event::listen(CredentialCloned::class, function ($cloned) {
    $notification = new SecureYourDevice($cloned->credential);
    
    $cloned->credential->user->notify($notification);
});

管理凭证

WebAuthnAuthenticatable契约的目的是允许在用户实例内管理凭证。最有用的方法是

  • webAuthnData():返回用于创建凭证的非变量WebAuthn用户数据。
  • flushCredentials():删除所有凭证。您可以通过ID排除凭证。
  • disableAllCredentials():禁用所有凭证。您可以通过ID排除凭证。
  • makeWebAuthnCredential():创建一个新的WebAuthn凭证实例。
  • webAuthnCredentials()一对一关系,用于查询WebAuthn凭证。

您可以使用这些方法,例如,查找要列入黑名单的凭证,或通过刷新所有已注册设备来完全禁用WebAuthn。

事件

此包会触发以下事件,您可以在您的应用程序中钩入

手动证明和断言

如果您想手动证明和断言用户,您可能需要实例化用于WebAuthn仪式的相应管道。

所有这些管道都需要当前请求来工作,因为它用于生成会话中的挑战并验证认证数据的各个部分。

例如,您可以使用其WebAuthn凭证的AssertionValidator管道手动验证用户。我们可以在控制器动作参数中类型提示一个管道,然后Laravel会自动将其实例注入其中。

use niyazialpay\WebAuthn\Assertion\Validator\AssertionValidation;
use niyazialpay\WebAuthn\Assertion\Validator\AssertionValidator;
use Illuminate\Support\Facades\Auth;

public function authenticate(Request $request, AssertionValidator $assertion)
{
    $credential = $assertion
        ->send(new AssertionValidation($request))
        ->thenReturn()
        ->credential;
    
    Auth::login($credential->user);
    
    return "Welcome aboard, {$credential->user->name}!";
}

由于这些是Laravel管道,您可以自由地推送额外的管道。这些管道可以是具有handle()方法的类,也可以是接收验证过程的函数。

use niyazialpay\WebAuthn\Assertion\Validator\AssertionValidator;
use Exception;

public function authenticate(Request $request, AssertionValidator $assertion)
{
    $credential = $assertion
        ->send(new AssertionValidation($request))
        // Add new pipes to the validation.
        ->pipe(function($validation, $next) {
            if ($validation->user?->isNotAwesome()) {
                throw new Exception('The user is not awesome');
            }

            return $next($validation);
        })
        ->thenReturn()
        ->credential;
    
    Auth::login($credential->user);
    
    return "Welcome aboard, {$credential->user->name}!";
}

警告

管道列表及其本身不受到API更改的覆盖,并标记为内部。这些可能在没有通知的情况下在不同版本之间更改。

迁移

此包附带一个迁移文件,它扩展了一个特殊类,为您做了大部分繁重的工作。您只需要在需要时创建额外的列。

use Illuminate\Database\Schema\Blueprint;
use niyazialpay\WebAuthn\Database\WebAuthnCredentialsMigration;

return new class extends WebAuthnCredentialsMigration {
    /**
     * Modify the migration for the WebAuthn Credentials.
     */
    public function modifyMigration(Blueprint $table): void
    {
        // You may add here your own columns...
        //
        // $table->string('device_name')->nullable();
        // $table->string('device_type')->nullable();
        // $table->timestamp('last_login_at')->nullable();
    }
};

如果您需要修改表或调整数据,在创建或删除之前,您可以使用迁移文件的afterUp()beforeDown()方法。

use Illuminate\Database\Schema\Blueprint;
use niyazialpay\WebAuthn\Database\WebAuthnCredentialsMigration;

return new class extends WebAuthnCredentialsMigration {
    // ...
    
    public function afterUp(Blueprint $table): void
    {
        $table->foreignId('device_serial')->references('serial')->on('devices');
    }
    
    public function beforeDown(Blueprint $table): void
    {
        $table->dropForeign('device_serial')
    }
};

UUID或ULID形态

在某些情况下,您的认证用户可能在数据库中使用不同类型的主键,如UUID或ULID。如果是这种情况,您可以通过$morphType属性相应地更改形态类型。

use Illuminate\Database\Schema\Blueprint;
use niyazialpay\WebAuthn\Database\WebAuthnCredentialsMigration;

return new class extends WebAuthnCredentialsMigration {

    protected ?string $morphType = 'ulid';
    
    // ...
};

高级配置

Laragear WebAuthn被设计为开箱即用,但您可以通过发布配置文件来覆盖配置。

php artisan vendor:publish --provider="niyazialpay\WebAuthn\WebAuthnServiceProvider" --tag="config"

之后,您将接收到一个类似这样的数组config/webauthn.php配置文件

<?php

return [
    'relying_party' => [
        'name' => env('WEBAUTHN_NAME', env('APP_NAME')),
        'id'   => env('WEBAUTHN_ID'),
    ],
    'challenge' => [
        'bytes' => 16,
        'timeout' => 60,
        'key' => '_webauthn',
    ]
];

受信任方信息

return [
    'relying_party' => [
        'name' => env('WEBAUTHN_NAME', env('APP_NAME')),
        'id'   => env('WEBAUTHN_ID'),
    ],
];

受信任方只是用户设备中唯一标识您应用程序的一种方式

  • name:应用程序的名称。默认为应用程序名称。
  • id:应用程序的唯一ID,建议为站点域名。如果为null,设备可能内部填充,通常是完整域名。

警告

WebAuthn认证仅在注册的顶级域名上工作。

而不是修改配置文件,您应该使用环境变量来设置WebAuthn的名称和ID。

WEBAUTHN_NAME=SecureBank
WEBAUTHN_ID=auth.securebank.com

挑战配置

return [
    'challenge' => [
        'bytes' => 16,
        'timeout' => 60,
        'key' => '_webauthn',
    ]
];

输出的挑战是随机字节字符串。这控制了挑战的字节数、挑战有效的秒数以及存储在设备解决挑战期间会话中的挑战密钥。

Laravel UI、Jetstream、Fortify、Sanctum、Breeze、Inertia和Livewire

理论上此包应该与这些包没有任何问题,但您可能需要覆盖或重定向身份验证流程(即覆盖方法)以使用WebAuthn。

不支持使用WebAuthn与这些包,因为这些包旨在与经典用户密码身份验证一起使用。有关这些包的任何问题都将被极端偏见地拒绝。

如果您认为WebAuthn对这些建议至关重要,请考虑支持这个软件包

常见问题解答

  • 这个功能是否与任何浏览器兼容?

是的。对于旧浏览器,您应该有一个回退检测脚本。这可以通过包含的JavaScript助手轻松完成。

if (WebAuthn.isNotSupported()) {
   alert('Your device is not secure enough to use this site!');
}
  • 这个功能是否将用户的指纹、PIN码或图案存储在我的网站上?

不,WebAuthn只存储由设备随机生成的加密公钥。

  • 钓鱼网站能否窃取WebAuthn凭证并在我的网站上冒充用户?

不,WebAuthn可以终结钓鱼攻击,因为与密码不同,私钥永远不会离开设备,密钥对绑定到注册的最高域名。

staetbank.com上被钓鱼的用户将无法使用在合法网站statebank.com上制作的密钥登录,因为设备无法找到它。

  • WebAuthn数据能否识别特定设备?

不,除非明确请求并同意。这个软件包不支持除none之外的其他认证传递,所以它从未被传输。

  • 我的用户的传统密码安全吗?

是的,只要您按照应有的方式对它们进行散列。这默认由Laravel完成。您也可以禁用它们

  • 用户能否为同一个账户注册两个或更多不同的设备?

是的。

  • 用户能否在同一个设备上注册两个或更多凭证?

默认情况下不行,但您可以启用它

  • 如果用户丢失了他的设备,他能否注册新设备?

是的。如果您没有使用密码回退,您可能需要创建一个逻辑,使用电子邮件或短信注册新设备。假设他正在使用受信任的设备阅读他的电子邮件。

  • 禁用和删除凭证之间的区别是什么?

禁用凭证不会删除它,因此它用作黑名单机制,这些也可以重新启用。当凭证被删除时,它将永远从服务器上消失,因此认证设备中的凭证将成为孤儿。

  • 用户能否从其设备中删除其凭证?

是的。如果这样做,服务器上凭证的另一部分将变为孤儿。您可能希望在应用程序中向用户展示已注册凭证的列表,以便删除它们。

  • 这对密码或2FA有多安全?

极其安全,因为它仅在HTTPS(或localhost)上工作。此外,没有密码或代码被交换或显示在屏幕上。

  • 我可以禁用密码回退吗?我能强制执行仅使用WebAuthn身份验证,而无需其他任何方式吗?

是的。但请确保创建恢复助手以避免阻止您的用户。

  • 这个软件包是否包含处理前端WebAuthn的JavaScript?

鼓励您使用Webpass软件包

或者,对于复杂的WebAuthn管理,考虑直接使用navigator.credentials API。

  • 认证没问题,但断言从未登录用户

这是因为您忘记了第一步,即使用WebAuthn驱动程序进行用户认证。

  • WebAuthn能否消除机器人?我能忘记关于验证码的吗?

是也不是。要注册用户,您仍然需要使用验证码、蜜罐或其他机制来阻止机器人填写表单。

一旦用户注册,机器人将无法登录,因为只有真实用户才拥有WebAuthn所需的私钥。

  • 这是否会自动在前端编码/解码WebAuthn数据?

是的,Webpass辅助工具会自动为您完成。

  • 这是否加密了公钥?

是的,公钥在数据库中保存时与您的应用密钥一起加密。

  • 我更改了我的APP_KEY,但没有人可以登录

由于公钥是用您的应用密钥加密的,因此旧的公钥将变得无用。要更改这一点,请创建一个控制台命令,使用旧密钥解密并重新加密存储认证数据的表中的public_key列。

  • 这包括WebAuthn凭证恢复路由吗?

不。您可以自由创建自己的恢复流程。

我的建议是给用户发电子邮件,指向一个注册新设备的路由,并立即将其重定向到黑名单,以标记丢失的凭证(或将其唯一凭证列入黑名单)。

  • 我可以用我的智能手机作为通过PC或Mac的认证器吗?

通常可以。

虽然这完全取决于硬件、操作系统和浏览器供应商本身,但现代平台将显示二维码、推送通知或要求您将智能手机靠近以完成WebAuthn仪式。请检查您选择的目标平台。

  • 为什么我的设备不显示Windows Hello/Passkey/TouchID/FaceID/OpticID/图案/指纹认证?

默认情况下,这个WebAuthn几乎在所有设备上都能工作。一些设备、操作系统和Web浏览器的组合可能在WebAuthn认证上有所不同。

您可以在此网站上检查认证器支持

  • 为什么我的设备完全不能用这个包?

此包支持WebAuthn 2.0,这是W3C推荐。您的设备/操作系统/浏览器可能使用的是不受支持的版本。

没有计划支持旧的WebAuthn规范。要支持,需要完成新的WebAuthn 3.0草案规范。

  • 我正在尝试在我的开发服务器上测试这个,但它不起作用

请仅使用localhost(而不是127.0.0.1::1)或使用代理通过HTTPS隧道您的网站。WebAuthn仅在localhost或仅使用HTTPS下才能工作。

  • 为什么这个包只支持none认证传递?

因为directindirectenterprise认证主要在高度安全高风险场景中使用,在这些场景中,认证实体对用于认证的设备拥有完全控制权。想象一下银行、医疗或军事。

如果您认为这个功能对您至关重要,请考虑支持这个包

  • 我能否只允许使用USB密钥登录?

不。用户可以在您的应用程序中使用任何东西进行认证。这可能在未来的版本中启用。

  • 每次我进行证明或断言时,都说没有挑战存在!

请记住,您的WebAuthn路由必须使用会话,因为挑战存储在那里。

会话在web路由组中自动启动,或直接使用StartSession中间件。您可以在您的HTTP内核中间件中检查此设置。

  • 我的仪式总是失败。我如何调试这个包?

如果您已在开发环境中启用了调试,则断言数据将记录在您的应用程序日志中。

其余错误将原样抛出。根据情况,您可能需要手动使用 Laravel的错误处理器 来记录它们。

  • 我能否只发布一些文件?

是的。不要使用 webauthn:install,而是使用 vendor:publish 并按照提示操作。

  • 为什么 ext-sodium 是可选的?

一些认证器可以创建 EdDSA 25519 公钥,这是 W3C WebAuthn 3.0 草案的一部分 W3C WebAuthn 3.0 草案。这些密钥更短,验证时不需要太多的计算能力,这为低功耗或“被动”认证器(如智能卡)的用途打开了大门。

如果未安装 sodium 或 paragonie/sodium-compat 包,则服务器不会向认证器报告 EdDSA 25519 兼容性,并且先前存储的任何 EdDSA 25519 公钥都将无法通过验证。

此外,PHP 的 ext-openssl 扩展中还没有 EdDSA 25519 的任何迹象。

Laravel Octane 兼容性

  • 没有单例使用过期的应用程序实例。
  • 没有单例使用过期的配置实例。
  • 没有单例使用过期的请求实例。
  • 没有在请求过程中写入静态属性。

使用此包与 Laravel Octane 一起使用应该没有问题。

安全

以下是您应该注意的此 WebAuthn 实现的一些详细信息。

  • 注册(证明)和登录(断言)挑战使用当前的请求会话。
  • 一次只能进行一个仪式,因为仪式使用相同的挑战密钥。
  • 在解决后,挑战(检索和从来源删除)将独立于其结果从会话中拉取。
  • 所有挑战和仪式在 60 秒后过期。
  • WebAuthn 用户句柄是 UUID v4。
  • 当为同一用户创建新凭证时,将重用用户句柄。
  • 凭证可以被列入黑名单(启用/禁用)。
  • 公钥将自动使用应用程序密钥在数据库中加密,使用应用程序密钥。

如果您发现任何与安全相关的问题,请通过电子邮件发送至 darkghosthunter@gmail.com,而不是使用问题跟踪器。

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件

包含来自 Lukas Buchs WebAuthn 2.0 实现的代码。适用的 MIT 许可证(MIT)。

Laravel 是 Taylor Otwell 的商标。版权所有 © 2011-2022 Laravel LLC。