🔑

Passkey認証を Cloudflare Pages+D1+KV の無料枠で試してみた。

2024/01/04に公開

概要

https://passkey-cloudflare.pages.dev/

Passkey認証を自分で実装してみたかったので、無料で動かせる構成を考えてCloudflareを使うことにしてみました。
使った技術スタックは以下の通り。

  • Infrastructure
    • Cloudflare Pages
    • Cloudflare D1
    • Cloudflare KV
  • Software
    • TypeScript
    • Remix + Remix Auth
    • simplewebauthnz
    • drizzle-orm

ソースはこちら
https://github.com/horiuchi/passkey-cloudflare

デモページについて

最初に「Log in」ページに行ったら、まずはGithubアカウントでログインして下さい。ログインできたら、その後に表示されるページで「Add Passkey」をクリックしてPasskeyの登録ができます。登録に成功したら、一旦「Log out」してもらえたらPasskeyでのログインが試せます。

このような手順になっている理由

Passkeyだけでは、ユーザのIdentityを特定できません。
つまり、いわゆる通常のSign upと同様な手順を辿って、ユーザのIDとpassword(今回は代わりにPasskeyと使う)、それと追加のprofileを入力してもらうページを用意して登録するようなフローが必要になる。その場合、emailの到達確認やマジックリンクをemailに送ってそこからsign upの続きをする様な実装が必要になる。
しかし、email送信までやるとなると面倒大変なので、それをやらない方向にしました。

そのため、フェデレーションを使って別のサービスのIDをそのまま使わせてもらうことにしました。
そして、色々なサービスと連携が可能な作りをしていますが、実装の関係上今のところはGithubだけ対応しています。本当ならGoogle、Apple、Microsoft辺りをサポートしておくと、ほとんどの人をサポートできるのでしょうね。

使った技術の選定理由

Cloudflare

https://www.cloudflare.com/
認証を行う上でDatabaseが必要になります。そのDBに無料枠があると聞いていたので、今回のデモを作ってみようと考えたのでした。
なので、Cloudflare D1が最初に決定していて、付随してPagesがあって、セッションの保持のために追加でKVも使ってます。

TypeScript

https://www.typescriptlang.org/
Web Frontendの開発では、自分の中で使うことがMustなので。

Remix + Remix Auth

https://remix.run/docs/
https://github.com/sergiodxa/remix-auth
Cloudflare Pagesで動かすに当たって、最初は普段から使っているNext.jsを検討したのですがnext-on-pagesがどれくらい使えるのかが未知数だった(普通にDeployはできるのでしょうが、Dev環境でHot Reloadができるかとか、Next14にどこまで対応しているのかとか)ので、公式に対応しているRemixを使うことにしました。
RemixはReact Routerがベースになっているようで、昔少しだけ見たそれとほとんど同じでした。あまり使ったことはなかったのですが、ルールがシンプルなのとTutorialが良くできているので、使い始めるのがそれほど大変ではありませんでした。

認証に対応するため、Remix Authも導入。Passport.js on expressは知っていたので、必要性/有用性は分かっていたので特に問題なく採用。

simplewebauthnz

https://simplewebauthn.dev/
今回のメイン要素、Passkeyの実装のため(というかWebAuthn)のライブラリ。
npmで調べた限り、WebAuthnに対応しているライブラリはこれ以外にはあまり無さそうでした。現状、TypeScriptで使えるライブラリのデファクトになっているようです。

drizzle-orm

https://orm.drizzle.team/docs/overview
Cloudflare D1に公式に対応しているORM。TypeScriptもちゃんとサポートされているので、これを今回は使うことにしました。マイグレーションもサポートされているので、DBのスキーマ変更後にマイグレーションのためのSQLを自動生成してくれて便利でした。SQLの書き方に少しクセがありますが、ORMとしての使い勝手としてはそこまで問題にならないかな?
一つ不満に思ったのは、1:nのリレーションがあった時にJoinした結果がフラットなデータが返ってくるところですね。素のSQLを使っているのならそれが当たり前なのですが、ORMならJoinしたテーブルのデータをネスト構造で返してくれると嬉しいのにと思ってしまいました。

ORMとしてはPrismaが一番有名ですが、D1への接続に独自のDriverを使っている関係で現状は使えません。今のところいつまでに対応されるかは不透明です。
https://github.com/prisma/prisma/issues/13310

まとめ

SQLが使えるDatabaseに無料枠があるのはエライ!

Discussion