🗝️

パスキー認証 - LINE FIDO2サーバーで体験(Windows&スマホ編)

2024/01/14に公開

概要

パスワードレス認証として話題のパスキー。
パスキー認証をまず体験しAPI通信の内容を見てみて少しずつ理解してくための手順。

実際にパスキーで認証可能なサービス

□ 実際のサービスで体験したい場合は以下のアプリで体験できる。
アカウントを登録後、アカウント設定画面からパスキーを登録しログアウト。
ログイン時にパスキー認証でログインができる。

□ TikTokのアプリ https://www.tiktok.com/ja-JP/

□ ニンテンドーアカウント https://www.nintendo.co.jp/support/nintendo_account/passkey/index.html

LINE FIDO2サーバーを体験

□ パスキーの認証がどのように実現されているか理解するために、実装イメージを確認。
□ オープンソースとして公開されているLINE FIDO2-Serverを利用し、通信の内容を確認。
□ その後にシーケンス図を確認することで理解を深める。

環境

□ WindowsOSのPCを利用
□ スマホとPCは同じネットワークに繋がっている(例:同じwifiに繋がっている)

□ (参考)本記事で利用した環境
 □ DockerDesktop: 4.26.1 (131620), Engine: 24.0.7
 ※ DockerDesktop利用できない場合、Rancher Desktop利用でもOK。
 ※ Docker Desktopは条件に該当した場合のみ無料で利用できる。
 有償条件に該当する企業に所属している場合でDocker Desktopを使用したい場合は、
 自己学習として自宅のPCで実行することをおすすめする。

□ PC: Windows 11 Home
 □ スマホ: iPhone(iOS17.1.2)

□ 使用するもの:LINE FIDO2-Server
オープンソースとして公開されているLINE FIDO2-Serverを利用し、パスキー認証を体験する。

LINE Security R&Dチームは、FIDO2をより広く普及し、より良いソフトウェアに成長させるため、LINE FIDO2-Serverをオープンソースとして公開することにしました。このような活動が、最終的にFIDOエコシステムの発展に貢献すると期待しています。
私たちが公開したオープンソースのGitHubリポジトリーは以下のとおりです。
https://github.com/line/line-fido2-server

https://engineering.linecorp.com/ja/blog/fido-at-line-fido2-server-opensource

手順.WindowsOSでLINE FIDO2サーバーを試す

1.レポジトリのクローン

□ 任意のディレクトリで、work_line_fidoの名前でフォルダを作成する

□ Visual Studio Codeで作成したwork_line_fidoフォルダを開く。

□ Windowsの場合に実行
ctrlキー@キーでTERMINALを開く

※Githubからpullしたファイルの改行コードが変わってしまうとDockerのコンテナを起動できない問題があるため、一時的に下記をターミナルで実行する。

git config --global core.autocrlf input

□ GiHubからクローンする
terminal上で下記を実行

git clone https://github.com/line/line-fido2-server.git

□ (参考)line-fido2-serverのレポジトリ
https://github.com/line/line-fido2-server

2.Dockerコンテナを起動

□ Visual Studio Codeでline-fido2-serverのフォルダを開く

ctrlキー@キーでTERMINALを開く
terminal上で下記を順番に実行

docker build -t build-image .
docker-compose build
docker-compose up -d

※サーバーが起動するまで時間がかかる可能性あり。
サーバー起動したかはdocker-compose logs rpやdocker-compose logs fido2でログから分かる。

※もし …省略failed to fetch anonymous token…省略みたいなエラーが出たら、以下を実行後にdocker build -t build-image .を再実行する。

# windowsの場合(Powershellの場合)
set DOCKER_BUILDKIT=0
set COMPOSE_DOCKER_CLI_BUILD=0
# docker buildの再実行
docker build -t build-image .

※それでもerrorが出る場合は、docker loginを行なう。

docker login

# その後はDocker Hub(https://hub.docker.com)に登録してあるユーザーとパスワードを入力しEnter

# ログインできたら、docker buildの再実行
docker build -t build-image .

3.立ち上がった各サーバーを確認する

URL 説明 用途 API仕様書
http://localhost:8080 FIDO2 RP SERVER REST API RP側のサーバー(クライアントがアクセスするサーバー) http://localhost:8080/swagger-ui.html#/
http://localhost:8081 FIDO2 SERVER REST API 署名を検証するサーバー http://localhost:8081/swagger-ui.html#/

4.RPサーバーにアクセスしてみる

※ 指紋認証などが無いPCの場合でもPINコード入力で確認できる。

http://localhost:8080/ にアクセスする

xxxxxx@gmail.comなど任意の値をUser NameとDisplayNameに入力する。

□ PC内蔵の認証機器ではなく、YubiKeyなど含め外部デバイスで認証を行う場合は「On roaming (cross-platform) authenticator」を選択する。
※該当する場合のみ選択。

□ 通信の状態を確認するため、fnキーとF12キーを押して、開発者コンソールを開く。
□ Networkタブを選択し、Preserve Logのチェックボックスにチェックを入れる。
□ ALLが選択されていることを確認する。

□ Registerタブを押下する (パスキー登録)
 □ /attestation/options APIが呼び出されていることが開発者コンソールから確認できる。

□ 認証のモーダルが表示されること

□ 指紋をかざしOKの場合モーダルが表示される

□ モーダルのOKボタンを押下すると、/attestation/result APIが呼び出されていることが確認できる。
 □ リクエストパラメーターはpayloadタブから確認できる
 □ レスポンスデータはPreviewタブから確認できる

□ 青色のAuthenticateボタンを押下する (パスキー認証)
 □ パスキーを使用してサインインするかを聞かれる
 □ /assertion/options APIが呼び出されていることが開発者コンソールから確認できる。

□ リストから認証したいユーザーを選択し「次へ」ボタンを押下

□ 指紋をかざしOKの場合、/assertion/result APIが呼び出されていることが確認できる。



□ WindowsOSでのパスキー体験に必要な手順はここで終わりです。
※ 手順5以降はhttps化やスマホからのアクセスに必要な手順であり、必要な場合に実施してください。

(参考)シーケンスを確認してみる

□ line-fido2-serverが公開しているシーケンスの配置場所
https://github.com/line/line-fido2-server/wiki/Sequence-diagrams

□ 補足:開発者コンソールで確認した通信部分は画像の赤枠部分である。

5.h2-consoleへアクセスできるかを確認

h2-consoleはH2インメモリデータベースで簡易的にサーバーが立ち上がっている間だけデータを保存しておける。

http://localhost:8081/h2-console へアクセス
JDBC URL:にはjdbc:h2:mem:userdb;を入力しconnect。

□ No suitable driver foundエラーになるため、コードを修正する。
https://github.com/line/line-fido2-server のREADME.mdの記載を参考に、implementation('org.zalando:logbook-spring-boot-starter:1.8.1') をコメントアウトする。
<修正対象ファイル>

  • /line-fido2-server/spring-boot-starter/line-fido2-spring-boot-demo/build.gradle

  • /line-fido2-server/server/build.gradle

// implementation('org.zalando:logbook-spring-boot-starter:1.8.1')

□ 下記を順番に実行

docker-compose down
docker build -t build-image .
docker-compose build
docker-compose up -d

※サーバーが起動するまで時間がかかる可能性あり。
サーバー起動したかはdocker-compose logs rpdocker-compose logs fido2でログから分かる。

□ 再度 http://localhost:8081/h2-console へアクセス
JDBC URL:にはjdbc:h2:mem:userdb;を入力しconnect。

下記が表示されていることを確認する。

(参考) SELECT * FROM RPなどSQLでデータを参照できる。

手順.ローカルでLINE FIDO2サーバーをhttps化する

6.ループバックアドレスのエイリアスを追加する

□ powershellを管理者として実行する

□ ループバックアドレスのエイリアスを追加
https化の前にrpとfido2のdockerコンテナを同じportで立ち上げるようにするためです。

netsh interface ip add address name="Loopback Pseudo-Interface 1" addr=127.0.0.2 mask=255.255.255.255

□ ループバックの設定が追加されているかを確認する

netsh interface ip show addresses

□ ファイルC:\Windows\System32\drivers\etc\の設定を変更する
下記を参考にドメイン名を127.0.0.1と127.0.0.2に指定してください

127.0.0.1	localhost
127.0.0.2	localhost

127.0.0.1	fido2.exampletthoge.com # fido2サーバー用
127.0.0.2	exampletthoge.com # rpサーバー用

これでlocalhostに127.0.0.2でもアクセスできるようになります。

□ (参考) ループバックの追加設定の削除は以下を実行

netsh interface ip delete address "Loopback Pseudo-Interface 1" addr=127.0.0.2

□ docker-compose.ymlを変更

/line-fido2-server/docker-compose.ymlのportsを下記に変更し、docker-compose up -dを実行。

~略~
      ports:
        - "127.0.0.2:8080:8080"
~略~	
     ports:
        - "127.0.0.1:8080:8081"	

変更後の全体は以下。

version : "3.8"
services:
    build:
      container_name: build-image
      image: build-image:latest
      build:
        context: .
        dockerfile: ./Dockerfile
    rp:
      container_name: rp-server
      image: rp:latest
      build:
        context: .
        dockerfile: ./rpserver/Dockerfile
      ports:
        - "127.0.0.2:8080:8080"
      restart: always
    fido2:
      container_name: fido2-server
      image: fido2:latest
      build:
        context: .
        dockerfile: ./server/Dockerfile
      ports:
        - "127.0.0.1:8080:8081"
      restart: always

□ httpとドメインでアクセスできるかを確認する。
※この時点ではhttpsではなく、まだhttpです。

http://exampletthoge.com:8080

http://fido2.exampletthoge.com:8080

※ DockerDesktopではなくRancher Desktop環境を利用している場合http://fido2.exampletthoge.com:8080のみアクセスができることを確認できればOK。
Rancher Desktop環境の場合は127.0.0.2:8080にホスト環境のブラウザから接続が上手く行かない。

Rancher Desktop環境でも後続のhttps化を行なえRPサーバーにアクセスできるので、http://fido2.exampletthoge.com:8080にアクセスできることを確認できたら次に進む。

7.HTTPS化のためのオレオレ証明書を生成する

この手順7はpowershellで実行する。
オレオレ証明書(ルート証明書とサーバー証明書)を生成する手順です。

□ 自分のPCのIPアドレスを下記を参考に調べる
windowsの設定画面の「ネットワークとインターネット」から接続しているネットワークをクリック。
IPv4アドレスの値を確認する。

□ Chocolateyをinstallする
Chocolateyはnpmのように簡単にWindowsにソフトを入れられるツール。
Chocolateyでmkcertをinstallするために利用する。

powershellを管理者として実行して下記を貼り付け。

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

このコマンドは https://chocolatey.org/install の下記画像のコマンドをCopyしたものです。

□ インストールの確認
choco -vコマンドを実行し、バージョンが表示されればOK

□ mkcertのインストール
powershellを管理者として実行して下記を貼り付け。

choco install mkcert

(参考)
https://github.com/FiloSottile/mkcert

□ ローカル認証局(CA)のインストール

# ローカル認証局用のディレクトリを任意の場所で作成  ※作成は必須ではありません。
cd
mkdir mkcert
cd mkcert
# ローカル認証局のインストール(mkcert install)
mkcert install

□ サーバー証明書と秘密鍵を作成

# ※サーバー証明書, 秘密鍵用のディレクトリを作成  ※作成は必須ではありません。
mkdir mkcert/ssl
cd mkcert/ssl
# サーバー証明書と秘密鍵を作成1(mkcert rpドメイン名 自分のPCのIPアドレス ループバックアドレスを指定)
# ※自分のPCのIPアドレスに置き換えて実行すること
mkcert exampletthoge.com 192.168.0.7 127.0.0.2
# サーバー証明書と秘密鍵を作成2(mkcert fido2ドメイン名 自分のPCのIPアドレス ループバックアドレスを指定)
# ※自分のPCのIPアドレスに置き換えて実行すること
mkcert fido2.exampletthoge.com 192.168.0.7 127.0.0.1

□ トラストストアにローカル認証局(CA)をインストール(mkcert -install)

mkcert -install

□ モーダルが表示されるので「はい」をクリックする。

□ インストールされたルート証明書を確認する。
 □ タスクバーから検索してユーザー証明書を開く。
 
 □ 信頼されたルート証明機関を開く。
 
 □ 発行先が「mkcert」始まりの証明書があることを確認する。
 もし見つからない場合は、一度ユーザー証明書を閉じてもう一度開き直して確認する。

8.rpとfido2サーバーのhttps化

まず/line-fido2-server/docker-compose.ymlを変更する。

□ nginxコンテナの定義をdocker-compose.ymlに追加する。

~略~
    nginx:
      image: nginx:alpine
      restart: always
      volumes: # ローカルPCのディレクトリ:コンテナの中のディレクトリ
        - ./nginx:/etc/nginx   
        - ./selfcert:/etc/cert/
      ports:
            - 80:80
            - 443:443
      extra_hosts:
        - "host.docker.internal:host-gateway"
      networks:
        app_net:
          ipv4_address: 172.30.0.4     
~略~

□ networksの定義をdocker-compose.ymlに追加

~略~
networks:
  app_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.30.0.0/24 # コンテナのIPアドレスを指定するために設定
~略~

□ rpとfido2にnetworkとIPアドレスの指定をdocker-compose.ymlに追加

~略~
      networks:
        app_net:
          ipv4_address: 172.30.0.2 # コンテナのIPアドレスを指定する
~略~
      networks:
        app_net:
          ipv4_address: 172.30.0.3 # コンテナのIPアドレスを指定する



□ 変更後の全体は以下となる。

# /line-fido2-server/docker-compose.yml
version : "3.8"
services:
    build:
      container_name: build-image
      image: build-image:latest
      build:
        context: .
        dockerfile: ./Dockerfile
    rp:
      container_name: rp-server
      image: rp:latest
      build:
        context: .
        dockerfile: ./rpserver/Dockerfile
      ports:
        - "127.0.0.2:8080:8080"
      restart: always
      networks:
        app_net:
          ipv4_address: 172.30.0.2 # コンテナのIPアドレスを指定する

    fido2:
      container_name: fido2-server
      image: fido2:latest
      build:
        context: .
        dockerfile: ./server/Dockerfile
      ports:
        - "127.0.0.1:8080:8081"
      restart: always
      networks:
        app_net:
          ipv4_address: 172.30.0.3 # コンテナのIPアドレスを指定する    

    nginx:
      image: nginx:alpine
      restart: always
      volumes: # ローカルPCのディレクトリ:コンテナの中のディレクトリ
        - ./nginx:/etc/nginx   
        - ./selfcert:/etc/cert/
      ports:
            - 80:80
            - 443:443
      extra_hosts:
        - "host.docker.internal:host-gateway"
      networks:
        app_net:
          ipv4_address: 172.30.0.4        

networks:
  app_net:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.30.0.0/24 # コンテナのIPアドレスを指定するために設定

□ 手順7で作成したサーバー証明書と秘密鍵を配置する用のselfcertフォルダを作成
/line-fido2-server/selfcert/

□ 手順7で作成したmkcert/sslフォルダ内のサーバー証明書と秘密鍵をコピーして/line-fido2-server/selfcert/に配置する

□ nginxフォルダを作成
/line-fido2-server/nginx/

□ nginxフォルダの中にnginx.confファイルを空ファイルで作成する。
/line-fido2-server/nginx/nginx.conf

□ nginx.confの中身を下記のように記載する

events {
    worker_connections  16;
}
http {
    server {
        listen 443 ssl;
    	ssl_certificate     /etc/cert/exampletthoge.com+2.pem;
    	ssl_certificate_key /etc/cert/exampletthoge.com+2-key.pem;
        server_name  exampletthoge.com;
        location / {
            proxy_pass http://172.30.0.2:8080/; # rpコンテナのipアドレス:port
            proxy_redirect off;
        }
    }

    server {
        listen 443 ssl;
    	ssl_certificate     /etc/cert/fido2.exampletthoge.com+2.pem;
    	ssl_certificate_key /etc/cert/fido2.exampletthoge.com+2-key.pem;
        server_name  fido2.exampletthoge.com;
        location / {
            proxy_pass http://172.30.0.3:8081/; # fido2コンテナのipアドレス:port
            proxy_redirect off;
        }
    }
}

□ 一旦httpsで起動が成功するかを確認する。
下記を順番に実行。

docker-compose down
docker build -t build-image .
docker-compose build
docker-compose up -d

※サーバーが起動するまで時間がかかる可能性あり。
サーバー起動したかはdocker-compose logs rpdocker-compose logs fido2でログから分かる。

https://exampletthoge.com にアクセスアクセスできることを確認

https://fido2.exampletthoge.com にアクセスできることを確認

※ この時点ではhttpsで起動はするがRPサーバーの設定の変更をしていないのでパスキー登録ができない。

9.RPサーバーの設定変更

□ application-docker.ymlをドメイン名に変更
ファイル: /line-fido2-server/rpserver/src/main/resources/application-docker.yml

rp.id, rp.origin, rp.port, conformance.urlの値を下記のように変更する。

# /line-fido2-server/rpserver/src/main/resources/application-docker.yml
# 変更後
spring:
  profiles:
    active: docker
  resources:
    chain:
      cache: false
fido2:
  rp:
    id: exampletthoge.com
    origin: exampletthoge.com
    port: 443
conformance:
  url: https://exampletthoge.com
logging:
  level:
    org.springframework.web: DEBUG
    org.hibernate: DEBUG
    com.linecorp.line: DEBUG
fido2-server:
  host: fido2

□ rpサーバーのAdapterController.javaを変更
※これはローカルでスマホを繋げてパスキー体験してみるための変更です。本来はチェック処理をコメントアウトすべきではないです。

ファイルパス:
/line-fido2-server/rpserver/src/main/java/com/linecorp/line/auth/fido/fido2/rpserver/controller/AdapterController.java

・ append(scheme)の記述をappend("https")に変更
AdapterController.java内の2箇所とも変更する。

        StringBuilder builder = new StringBuilder()
-                .append(scheme)
+                .append("https")

・ rpPortのチェックをコメント化する
AdapterController.java内の2箇所とも変更する。

-        if (!StringUtils.isEmpty(rpPort)) {
-            builder.append(":")
-                   .append(rpPort);
-        }

+        // if (!StringUtils.isEmpty(rpPort)) {
+        //     builder.append(":")
+        //            .append(rpPort);
+        // }

□  AuthenticatorTransport.javaにhybridを追加する。
ファイルパス:
/line-fido2-server/common/src/main/java/com/linecorp/line/auth/fido/fido2/common/AuthenticatorTransport.java

-    INTERNAL("internal");
+    INTERNAL("internal"),
+    HYBRID("hybrid");

□ dockerを起動する。
・ 下記を実行。

docker-compose down
docker build -t build-image .
docker-compose build
docker-compose up -d

※サーバーが起動するまで時間がかかる可能性あり。
サーバー起動したかはdocker-compose logs rpdocker-compose logs fido2でログから分かる。

10.RP IDの登録

□  http://fido2.exampletthoge.com:8080/h2-console へアクセス
JDBC URL:にはjdbc:h2:mem:userdb;を入力しconnect。

□  入っている値を確認する
SELECT * FROM RP

□  RPのドメインをRP IDとして登録する。
INSERT INTO RP(ID, NAME, ICON)VALUES('exampletthoge.com', 'example1', null);

□ 動作確認する (https://exampletthoge.com/)
User nameとDisplay nameを入力してRegsiter、Authenticateができるかを確認する。
 □ パスキー登録



 □ パスキー認証

手順.スマホからアクセスできるようにする

前提:手順.ローカルでLINE FIDO2サーバーをhttps化するが終わっていること。

11.squidのinstall

□ squidのdownload
サイト(https://squid.diladele.com/)より「SQUID FOR WINDOWS」をクリックしてdownload

□ 参考: 公式サイト(http://www.squid-cache.org/Versions/)
公式サイトより、上記ダウンロードサイトに飛べます。
binary package of Squidをクリック > windowsを選択すると上記ダウンロードサイトへのURLの記載がある

□ squidのinsatall
ヴィザードに従ってinstallする。

□ タスクバー検索またはデスクトップから「Squid Server Tray」をクリックする

□ タスクトレーにSquidアプリが表示される

□ アイコンクリックでstartやstopの選択モーダルを表示できる

12.squid.confの設定を変更

C:\Squid\etc\squid\squid.confをVisualStudioCodeで開く。

□  以下を新規追加

#
# Recommended minimum configuration:
#
visible_hostname UNKNOWN # <--追加: ホスト名の秘匿
hosts_file C:/Windows/System32/drivers/etc/hosts # <--追加:参照するhostsファイル

C:\Windows\System32\drivers\etc\ではなくC:/Windows/System32/drivers/etc/hostsを記載する。

□  acl lan srcの行を追加

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 0.0.0.1-0.255.255.255	# RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8		# RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10		# RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 	# RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12		# RFC 1918 local private network (LAN)
acl localnet src 192.168.0.0/16		# RFC 1918 local private network (LAN)
acl localnet src fc00::/7       	# RFC 4193 local private network range
acl localnet src fe80::/10      	# RFC 4291 link-local (directly plugged) machines

acl lan src exampletthoge.com  # <--追加: RPのドメイン名
acl lan src 192.168.0.7 # <--追加:自分のPCのIPアドレス

□  http_access deny to_localhostをコメント化する。

# http_access deny to_localhost # <-- コメント化

□ タスクバーよりsquidを起動

13.iPhoneのwifiの設定を変更する

□ wifiの設定画面を開き、「自動」になっているプロキシの構成を「手動」にする。
サーバー: 192.168.0.7など自分のPCのIPアドレスを入力する
ポート: 3128
※windowsでsquidが立ち上がっているport

14.スマホから動作確認を行う

□ スマホから https://exampletthoge.com/ にアクセスする。

□ スマホ側に残っているパスキーの情報を確認
スマホの設定画面を開き、パスワードで検索

exampletthoge.comの欄を押下すると、どのUser nameで登録したかがわかる。

事後処理

□ Dockerコンテナを終了する

docker compose down

□ Gitの設定を戻しておく
Gitの改行コードの取り扱いの設定です。手順1でデフォルトのtrueからinputに変更していた。
inputのままがよければ実行しなくてもOK。

□ terminal上で下記を実行。

git config --global core.autocrlf true

□ squidを停止する(利用した場合)

□ iPhoneのwifiの設定のプロキシを構成を「自動」に戻す

□ ループバックアドレスを追加していた場合、削除する。

netsh interface ip delete address "Loopback Pseudo-Interface 1" addr=127.0.0.2

□ 発行したルート証明書の削除
ユーザー証明書管理の「信頼されたルート証明機関」から発行先が「mkcert」始まりの証明書を削除する。

今回のソースコード

□ マスターのレポジトリから変更したソースコードの差分一覧は以下を参照
https://github.com/sktaz/rp-fido2-sv/pull/1

macOS&スマホ編はこちら

https://zenn.dev/ringo_to/articles/aab252ea75c537

Discussion