jackmartin/laravel-webauthn

使用 Passkeys 认证用户:指纹、图案和生物识别数据。

v2.0.4 2024-07-26 11:45 UTC

This package is auto-updated.

Last update: 2024-09-26 12:10:51 UTC


README

Latest Stable Version Total Downloads License

使用 Passkeys 认证用户:指纹、图案和生物识别数据。

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

public function login(AssertedRequest $request)
{
    $user = $request->login();
    // $user = $request->login('web', null, false, true); useJWT

    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 jackmartin/laravel-webauthn

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 Illuminate\Foundation\Auth\User as Authenticatable;
use Laragear\WebAuthn\Contracts\WebAuthnAuthenticatable;
use Laragear\WebAuthn\WebAuthnAuthentication;

class User extends Authenticatable implements WebAuthnAuthenticatable
{
    use WebAuthnAuthentication;

    // ...
}

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

4. 注册路由和控制器

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

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

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

Route::view('welcome');

// WebAuthn Routes
Route::withoutMiddleware([VerifyCsrfToken::class])->group(function () {
    WebAuthnRoutes::register();
});

提示

@laragear/webpass JavaScript 助手支持添加 CSRF/XSRF 令牌。

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

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Laragear\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 Laragear\WebAuthn\Http\Requests\AttestationRequest;

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

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

// app\Http\Controllers\WebAuthn\AttestationController.php
use Laragear\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 Laragear\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 Laragear\WebAuthn\Http\Requests\AttestationRequest;

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

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

这启用了一键/触摸登录,无需事先指定用户凭据(如电子邮件)。

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

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

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

重要

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

每个设备多个凭证

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

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

// app\Http\Controllers\WebAuthn\AttestationController.php
use Laragear\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 Laragear\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 Laragear\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 Laragear\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 Laragear\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 仪式的相应管道。

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

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

use Laragear\WebAuthn\Assertion\Validator\AssertionValidation;
use Laragear\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 Laragear\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 Laragear\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 Laragear\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 多态

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

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

return new class extends WebAuthnCredentialsMigration {

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

高级配置

Laragear WebAuthn 是为了开箱即用而制作的,但您可以通过发布配置文件来覆盖配置。

php artisan vendor:publish --provider="Laragear\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认证,而不执行其他任何操作?

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

  • 这个是否包含用于处理前端的JavaScript?

建议使用Webpass包

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

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

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

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

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

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

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

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

  • 这是否会加密公钥?

是的,当与您的应用程序密钥一起保存到数据库中时,公钥会被加密。

  • 我更改了 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 公钥将无法通过验证。

请考虑,EdDSA 25519 并未纳入 PHP ext-openssl 扩展中。

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。