パスキー認証 - LINE FIDO2サーバーで体験(masOS & スマホ編)
概要
パスワードレス認証として話題のパスキー。
パスキー認証をまず体験しAPI通信の内容を見てみて少しずつ理解してくための手順。
実際にパスキーで認証可能なサービス
□ 実際のサービスで体験したい場合は以下のアプリで体験できる。
アカウントを登録後、アカウント設定画面からパスキーを登録しログアウト。
ログイン時にパスキー認証でログインができる。
□ TikTokのアプリ https://www.tiktok.com/ja-JP/
□ ニンテンドーアカウント https://www.nintendo.co.jp/support/nintendo_account/passkey/index.html
LINE FIDO2サーバーを体験
□ パスキーの認証がどのように実現されているか理解するために、実装イメージを確認。
□ オープンソースとして公開されているLINE FIDO2-Serverを利用し、通信の内容を確認。
□ その後にシーケンス図を確認することで理解を深める。
環境
□ macOSのPCを利用
□ スマホとPCは同じネットワークに繋がっている(例:同じwifiに繋がっている)
□ (参考)本記事で利用した環境
□ DockerDesktop: 4.26.1 (131620), Engine: 24.0.7
※ DockerDesktop利用できない場合、Rancher Desktop利用でもOK。
※ Docker Desktopは条件に該当した場合のみ無料で利用できる。
有償条件に該当する企業に所属している場合でDocker Desktopを使用したい場合は、
自己学習として自宅のPCで実行することをおすすめする。
□ PC: Mac mini(Apple M2), masOS 14.2.1
□ スマホ: 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
手順.macOSでLINE FIDO2サーバーを試す
1.レポジトリのクローン
□ 任意の名前でフォルダを作成する
□ Visual Studio Codeで作成したフォルダを開く
□ ctrlキー
と@キー
でTERMINALを開く
□ terminal上で下記を実行
git clone https://github.com/line/line-fido2-server.git
□ line-fido2-server
のフォルダをVisual Studio Codeで開く
□ Visual Studio Codeでline-fido2-server
のフォルダを開く
□ (参考)line-fido2-serverのレポジトリ
(参考)M2チップ搭載のmacOSを利用している場合に実行
□ /line-fido2-server/server/Dockerfile
の先頭行を下記に変更する
FROM --platform=linux/amd64 openjdk:8-jdk-slim
※上記変更を加えないとfido2コンテナが立ち上がらないためです。下記を参考。
2.Dockerコンテナを起動
□ terminal上で下記を順番に実行
docker build -t build-image .
docker-compose build
docker-compose up -d
※サーバーが起動するまで時間がかかる可能性あり。
サーバー起動したかはdocker-compose logs rp
やdocker-compose logs fido2
でログから分かる。
3.立ち上がった各サーバーを確認する
□ http://localhost:8080
とhttp://localhost:8081
にアクセスできるかを確認
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コード入力で確認できる。
※ 筆者の環境はUSBのYubikeyBioに登録した情報で実行している
□ 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が呼び出されていることが開発者コンソールから確認できる。
□ 認証のモーダルが表示されること
※筆者の環境はUSBのYubikeyを認証情報登録に使用している
□ 指紋などで認証をしてOKの場合、下部に成功メッセージが表示されていること
□ 認証OKの場合、/attestation/result APIが呼び出されていることが確認できる。
□ リクエストパラメーターはpayloadタブから確認できる
□ レスポンスデータはPreviewタブから確認できる
□ 青色のAuthenticateボタンを押下する (パスキー認証)
□ 認証のモーダルが表示される
□ /assertion/options APIが呼び出されていることが開発者コンソールから確認できる。
□ 指紋をかざしOKの場合、/assertion/result APIが呼び出されていることが確認できる。
□ macOSでのパスキー体験に必要な手順はここで終わりです。
※次以降の手順はhttps化やスマホからのアクセスに必要な手順であり、必要な場合に実施してください。
(参考)シーケンスを確認してみる
□ line-fido2-serverが公開しているシーケンスの配置場所
□ 補足:開発者コンソールで確認した通信部分は画像の赤枠部分である。
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 rp
やdocker-compose logs fido2
でログから分かる。
□ 再度 http://localhost:8081/h2-console へアクセス
JDBC URL:にはjdbc:h2:mem:userdb;
を入力しconnect。
下記が表示されていることを確認する。
(参考) SELECT * FROM RPなどSQLでデータを参照できる。
手順.ローカルでLINE FIDO2サーバーをhttps化する
6.ループバックアドレスのエイリアスを追加する
□ ループバックアドレスのエイリアスを追加
https化の前にrpとfido2のdockerコンテナを同じportで立ち上げるようにするためです。
sudo ifconfig lo0 alias 127.0.0.2
□ ループバックの設定が追加されているかを確認する
ifconfg
□ /etc/hostsの設定を変更する
下記を参考にドメイン名を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でもアクセスできるようになります。
PCを再起動したらこのループバックアドレスのエイリアス設定は消えます。
□ 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はmacのterminalで実行する。
オレオレ証明書(ルート証明書とサーバー証明書)を生成する手順です。
□ 自分のPCのIPアドレスを下記を参考に調べる
□ mkcertのインストール
brew install 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
# ※Sudo passwordは、macのパスワードを入力
□ キーチェーンのシステムを見ると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 rp
やdocker-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 rp
やdocker-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ができるかを確認する。
- PC内蔵の認証機器ではなく、YubiKeyなど含め外部デバイスで認証を行う場合は「On roaming (cross-platform) authenticator」を選択する。
※該当する場合のみ選択。
□ パスキー登録
※筆者の環境はUSBのYubikeyを認証情報登録に使用している
□ パスキー認証
※筆者の環境はUSBのYubikeyを認証に使用している
手順.スマホからアクセスできるようにする
前提:手順.ローカルでLINE FIDO2サーバーをhttps化するが終わっていること。
11.squidのinstall
terminalから実行
brew install squid
12.squid.confの設定を変更
/opt/homebrew/etc/squid.conf を以下のように修正する。
□ 以下を新規追加
#
# Recommended minimum configuration:
#
visible_hostname UNKNOWN # <--追加: ホスト名の秘匿
hosts_file /etc/hosts # <--追加:参照する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を起動
brew services start squid
□ (参考) squidを停止
brew services stop squid
□ (参考) squidを再起動
brew services restart squid
13.iPhoneのwifiの設定を変更する
□ wifiの設定画面を開き、「自動」になっているプロキシの構成を「手動」にする。
サーバー: 192.168.0.7など自分のPCのIPアドレスを入力する
ポート: 3128
※macでsquidが立ち上がっているport
14.スマホから動作確認を行う
□ スマホから https://exampletthoge.com/ にアクセスする。
□ スマホ側に残っているパスキーの情報を確認
スマホの設定画面を開き、パスワードで検索
exampletthoge.comの欄を押下すると、どのUser nameで登録したかがわかる。
事後処理
□ Dockerコンテナを終了する
docker compose down
□ iPhoneのwifiの設定のプロキシを構成を「自動」に戻す
□ squidを停止する
brew services stop squid
□ PCを再起動しループバックアドレスのaliasを削除する
□ 発行したルート証明書の削除
キーチェーンのシステムからmkcertで作成したルート証明書を削除する。
今回のソースコード
□ マスターのレポジトリから変更したソースコードの差分一覧は以下を参照
windows&スマホ編はこちら
Discussion