如何使用Corbado将Passkey身份验证添加到PHP Symfony应用
#教程 #php #symfony #passkeys

Passkeys是Web身份验证的新标准登录方法,但到目前为止,很少有开发人员教程显示如何在代码级别上添加它们。

在以下内容中,我们将使用Corbado的Web组件将PHP Symfony应用程序的基于密码的登录名更改为无密码的,Passkey-Fort的身份验证。

Web组件是一个易于集成的,轻巧的身份验证层,并具有出色的开箱即用的Passkey UX。

设置

GitHub logo vincentdelitz / tutorial-passkeys-php-symfony-webcomponent

完整的教程,用于使用PHP Symfony集成Corbado Web组件,用于Passkey-Fir-First验证。

Complete PHP Symfony integration example for Corbado's passkey-first web component

This is a sample implementation of frontend and backend where the Corbado web component is integrated.

Note: In this tutorial a customer system is created with some pre-existing password-based users. Have a look at our docs,如果您没有任何用户,请查看集成。

1.文件结构

2.设置

-

让我们先获取整个图片!我们使用带有三个容器的Dockerized设置:

  1. 第一个容器运行我们的PHP Symfony应用程序
  2. 第二个容器与现有用户托管数据库。
  3. 第三个容器运行phpmyadmin,可轻松访问数据库

System structure

我们的文件夹结构看起来像这样

├── ...
├── config      
|   └── services.yaml               # Service configurations
├── src                             
│   ├── Controller                  
│   │   ├── WebhookController.php   # Manages endpoints for webhook
│   └── └── AppController.php       # Manages endpoints for application
├── templates                     
│   ├── home.html.twig              # Home page which you only get to see if you are logged in
│   ├── login.html.twig             # Login page which contains the Corbado web component; Acts as landing page if you are not logged in
├── .env                            # Contains all Symfony environment variables
└── ...

使用docker compose up启动系统。
我们的前端在http://localhost:8000上运行,而我们的后端可在http://localhost:8000/api上找到。

我们的登录页面看起来像这样:

Login page

要集成Corbado Web组件,我们按照以下步骤进行操作:

  1. Create project in the Corbado developer panel
  2. Integrate web component in the frontend
  3. Create backend endpoint to generate a session
  4. (Optional) Enable password-based login as fallback
  5. (Optional) Make your local application reachable for Corbado via Corbado CLI

1.在Corbado开发人员面板中创建项目

我们从前往Corbado developer panel并创建一个帐户开始。我们受到此屏幕的欢迎

Corbado developer panel

我们单击“集成指南”以逐步完成所有操作。

Corbado developer panel

我们想使用“ Web组件”,所以这就是我们选择的。

Corbado developer panel

另外,我们有一个具有现有用户群的系统,因此我们单击“是”。之后,我们发现自己处于开发人员面板的概述(如果是您的第一次,则需要通过电子邮件确认您的帐户)。

前往“集成指南”。这引导我们完成了整合工作所需的所有步骤。

Corbado developer panel

在步骤1中,我们创建一个API秘密。稍后,我们需要项目ID和生成的API秘密,以便与Corbado的API通信。另外,我们需要配置我们的授权来源。授权的来源是从集成了Web组件的站点的浏览器URL(与协议和端口,但没有路径)。我们需要CORS(交叉启用请求共享)和对其进行约束的Passkeys。在我们的情况下,我们将其发送到http://localhost:8000

Corbado developer panel

在第二个可选步骤中,我们配置了Webhook。这是需要的,因此Corbado可以与我们的后端进行交流,例如检查现有用户匹配的用户名和密码。稍后有关的更多详细信息。

Corbado developer panel

我们稍后将使用p36qlbyrvhozdtâ和``Z9asidcu2xlyou作为凭据设置了我们的Webhook,yound.p36qlbyrvhozdt-

在步骤3中,我们添加了应用程序URL并重定向URL。应用程序URL是Web组件运行的前端中的URL。例如,它在单击电子邮件魔术链接后再次将用户转发到Web组件。
重定向URL是在Corbado成功身份验证用户后,可以接收Corbado的会话令牌作为GET参数,因此可以启动会话。我们稍后在http://localhost:8000/redirect上实施重定向URL,但是我们可以在这里输入。

Corbado developer panel

那样,该项目已建立!

2.将Corbado Web组件集成到前端

现在我们已经完成了Corbado设置,让我们开始编码!在前端,我们将Corbado Web组件集成到我们的登录页面中。添加以下内容,在HTML头部代码,因此它提前加载JavaScript:

<script defer src="https://auth.corbado.com/auth.js"></script>

之后,我们将当前登录表替换为Corbado的登录表(当然使用您自己的项目ID):

<corbado-auth project_id="<project ID>" conditional="yes"> 
  <input name="username" id="corbado-username" value="" required autocomplete="webauthn" autofocus/> 
</corbado-auth>

浏览浏览器中我们的登录页面,显示了Corbado Web组件:

Corbado web component

提示:如果您现在输入您的电子邮件地址并尝试注册或登录,则将收到一条错误消息。那是因为我们还没有配置后端。

3.创建后端端点以生成会话

一旦用户通过前端的Corbado Web组件成功身份验证,他将使用CorbadoSessionToken GET参数发送到重定向URL。我们将此重定向的URL配置为http://localhost:8000/redirect,还记得吗?我们现在实现此端点。

我们将在services.yaml文件中初始化corbado api客户端。为此,我们需要上面的项目ID和API秘密。

services:
    Corbado\Client:
        autowire: true
        bind:
            $baseURI: 'https://api.corbado.com'
            $username: '%app.projectID%'
            $password: '%app.apiSecret%'

我们在我们的RouteConfig中为所需端点添加了一条路由(通过我们的框架中的注释)。

#[Route(‘/api/redirect, name: success, methods: ‘GET’)]

在重定向端点中,我们读取了CorbadoSessionToken查询参数的值。然后,我们使用Corbado PHP SDK致电Corbado的SessionVerify API端点,这将为我们提供令牌所属用户的电子邮件和名称。

Public function redirect(UserRepository $userRepo, Request $request, SessionInterface $session, Client $apiClient): Response {
  $token = $request->query->get(corbadoSessionToken);
  $useragent = $request->headers->get(User-Agent);
  $remoteAddress = $request->server->get(REMOTE_ADDR);

  try {
    $result = $apiClient->widget()->sessionVerify($token, 
    $remoteAddress, $useragent);
  } catch (\Exception $e) {
    return new Response(Session token expired, 400);
  }

  $response = $result->getData()->getUserData(); // Parse json response from Corbado request
  $userData = json_decode($response, true); $username = 
  $userData[username];
  $userFullName = $userData[userFullName]; // Create user if not exists
  $user = $userRepo->findOneBy([email => $username]);

  if ($user === null) {
    $user = new User($userFullName, $username);
    $userRepo->save($user, true);
  }
  $session->set(userID, $user->getId()); // Forward the user to frontend page

  return $this->redirectToRoute(home);
}

我们现在知道谁只是登录我们的应用程序。我们为用户创建会话,然后将他重定向到应用程序的登录页面:

Homepage

如果您没有现有的用户群,那么将无密码,Passkey-First身份验证与Corbado!

集成所需的全部

4.(可选)启用基于密码的登录作为后备

我们不想锁定现有用户,因此我们将基于密码的身份验证作为后备。因此,Corbado需要与我们的后端进行交流。它通过我们后端设置的Webhook来做到这一点。在之前的步骤中,我们将Webhook URL设置为http://localhost:8000/corbado-webhook’以及Webhook用户名和密码。

Corbado提供了一些PHP代码,有助于添加Webhooks:

composer require corbado/webhook-php

然后,我们将Webhook的用户名和密码添加到我们的PHP Symfony环境变量中,以便当我们想对传入的Webhook调用:
进行身份验证时,它们可用

WEBHOOK_USERNAME=p36qLbyRvHoZDT
WEBHOOK_PASSWORD=z9aSidcu2xLyoU

现在我们为Webhook创建了一个路线:

# -------- Webhook --------
corbado:
  path: /corbado-webhook
  controller: App\Controller\WebhookController::corbado_webhook

以及使Webhook可用的控制器。

Project files

Webhook Controller使用先前安装的Corbado Webhook库以及我们通过HTTP Basic Auth受保护的路线。

class WebhookController extends AbstractController
{
  #[Route('/corbado-webhook', name: 'corbado', methods: 'POST')]
  public function corbadoWebhook(UserRepository $userRepo, Request $request, string $webhookUsername, string $webhookPassword): Response
{
  try { 
  // Create new webhook instance with username and password. Both must be
  // set in the developer panel (https://app.corbado.com) and are used to secure your
  // webhook (this one here) with basic authentication.
  $webhook = new Webhook($webhookUsername, $webhookPassword);
  // Handle authentication so your webhook is secured (basic authentication). If username
  // and/or password are invalid handleAuthentication() will send HTTP status code
// 401 (Unauthorized) and terminate/exit execution here. $webhook->handleAuthentication();

如果用户在Web组件中输入电子邮件,我们刚刚安装的Webhook会接到电话。 corbado_webhook函数将处理它,从而导致kude4函数的呼叫。如果用户存在,这意味着他已经有了密码,Corbado可以选择通过密码登录。

function userStatus(UserRepository $userRepo, string $username): string
{
  $user = $userRepo->findOneBy(['email' => $username]);
  //Look up in database if $username exists and if $username is blocked/not permitted to login
  if ($user == null) {
    return AuthMethodsDataResponse::USER_NOT_EXISTS;
  } if ($user->isBlocked()) {
    return AuthMethodsDataResponse::USER_BLOCKED;
  } 
  return AuthMethodsDataResponse::USER_EXISTS;
}

用户输入密码后,发出了另一个Webhook调用,从而导致呼叫verifyPassword函数。在那里,我们检查给定凭证是否匹配并将响应发送回响应。

/**
* Verify given username and password.
* @param UserRepository $userRepo
* @param string $username
* @param string $password
* @return bool */
private function verifyPassword(UserRepository $userRepo, string $username, string $password): bool
{
  $user = $userRepo->findOneBy(['email' => $username]);
  if ($user == null || $user->getPassword() == null) {
    return false;
  }
  return password_verify($password, $user->getPassword());
}

完成!现在,我们所有的用户都可以使用PassKey,而现有的用户将密码作为后备选项。

但是,等等,如果我们的后端仅在本地运行,尤其是在开发过程中,Corbado如何调用端点?

5.通过Corbado CLI使您的本地申请可用于Corbado

使用Corbado CLI,我们为外界创建了本地应用程序的隧道,以便可以调用Webhook URL。我们通过遵循docs

来安装它

New system structure

启动后,在我们的机器上运行的网络钩从Corbado到我们本地实例。类似于上图,然后该过程如下:

  1. 浏览器请求我们的登录页面
  2. appController将包含Web组件的HTML页面发送回HTML页面。
  3. 用户输入电子邮件地址后,Web组件将其发送给Corbado。
  4. Corbado对其进行处理,并向我们的Webhook发送请求以检查用户是否存在。
  5. 该消息通过Corbado CLI转发,以达到我们的本地实例。 (如果您的解决方案正在生产中,Corbado可以直接致电Webhook Controller而无需Corbado Cli隧道,因为您会有一个公共地址)。
  6. 我们的Webhook控制器发送了请求的信息。
  7. 该消息再次通过Corbado Cli转发
  8. Corbado告诉Web组件如何做出反应(例如,向用户询问密码)。

之后,我们前往Corbado developer panel复制我们的CLI秘密。

我们使用项目ID和CLI秘密登录:

corbado login --projectID pro-1987097639455463555 --cliSecret 4uKn...

登录后,我们可以使用subscribe命令启动隧道(随着我们的Symfony应用程序在此处运行时,使用端口8000)。

corbado subscribe http://localhost:8000 --projectID pro-1987097639455463555 --cliSecret 4uKn...

现在,我们可以测试我们的Webhook是否可以通过进入https://app.corbado.com/app/settings/webhooks/testing,填写存根数据并运行测试。如果一切顺利,所有测试都将通过。

Corbado developer panel

如果我们现在转到http://localhost:8000/login并输入已经存在的帐户的电子邮件,则Web组件应询问您的密码(如果尚未创建该帐户的Passkey)。

Corbado web component

之后,要求用户为将来的登录创建一个Passkey。