見出し画像

Keycloak & TitanセキュリティキーでWebAuthnを試してみた


はじめに


こんにちは、SHIFTの田平です。

Googleのクレジットが年末に期限を迎えるため、Goolgeストアを見ていたらTitanセキュリティーがちょうど良い値段であったので購入してみました。
Googleなどのアカウントをパスキーに変更するついでに、自宅検証環境のKeyCloakにTitanセキュリティキー登録してWebAuthnを試してみました。

Keycloakとは?


シングルサインオン(SSO)、アイデンティティ管理(IDM)、アクセス管理の機能を提供するオープンソースソフトウェア。

Titanセキュリティキーとは?


Googleが販売しているセキュリティーキー。
2要素認証プロセス(2FA)用デバイスとして利用でき、パスキーを保存することが可能。

WebAuthn(Web Authentication)とは?


FIDO2(Fast Identity Online)のWebアプリ用標準規格。
生体認証、モバイル デバイス、FIDO セキュリティ キーを介してユーザーに簡単なログインを提供する。

検証環境


■IdP
・Ubuntu 22.04.3 LTS
・Keycloak 23.0.3

■SAMLクライアント(SP)
・Ubuntu 22.04.3 LTS
・Shibboleth SP 3.3.0

■PC
・Windows 11
・Microsoft Edge 120

WebAuthnの設定


最初にWebAuthnが利用できるようにKeycloakを設定します。
Adminコンソールに接続に接続し、対象レルムの設定画面を開きます。

左のメニューからAuthenticationを選択します。

Policiesタブを選択します。

WebAuthn Policyタブを選択し、設定します。

設定値は環境に合わせて設定してください。
以下は参考までに。

WebAuthn Passwordless Policyタブにも同じ設定を実施します。

フローの作成


今回は以下の処理を実現したいと思います。

  • 認証済みの場合はそのままアクセス(Cookie認証)

  • 未認証の場合はユーザー名を入力

  • ユーザーにパスキーが登録されていればWebAuthnで認証

  • ユーザーにパスキー未登録の場合はパスワードで認証

Keycloakでの処理を表形式にすると以下のような感じになります。
上から処理が実行され、それぞれ以下のような動きになります。
AlternativeはいずれかがOKであれば認証成功。
Requiredは必ず処理が要求される。
Conditionalは次の処理結果によってRequiredかDisabledになる。

AlternativeとRequiredは同じ処理階層に混ぜられないので、subフォームを使って調整しています。

上記の内容でKeycloakにフローを作成します。
Authenticationを選択します。

FlowsタブでCreate flowをクリックします。

以下を入力して作成します。

  • Name:任意のフロー名

  • Description:任意の説明

  • Flow type:Basic flowを選択

フローを作成していきます。 最初はCookie処理を追加したいのでAdd an executionでCookieを追加します。

Cookieが追加されたのでRequirementをDisabledからAlternativeに変更します。

あとは同じようにAdd stepとAdd sub-flowを使って、フローを作成してください。
今回は以下のように設定しました。

フローの適用


フローの作成が終わったら、クライアントの認証フローを変更します。
レルム全体の設定を変更する場合はフローの右上のActionからBind flowを選択して、Browser flowに割り当てます。

特定のクライアントの認証フローを変更する場合はクライアントの設定画面から変更します。

今回は検証用クライアントのフローのみを変更しますので、Clientsからフロー変更対象のクライアントを選択します。

AdvancedタブのAuthentication flow overridesでBrowser Flowを作成したフローに変更します。

パスキーの登録


Keycloakのアカウント管理画面に接続します。
検証環境は自己証明書で動かしているので、証明書の警告は無視します。

ユーザーとパスワードを入力してログインをクリック

Account SecurityのSigning inをクリック

Security keyのSet up Security keyをクリック

登録をクリック

セキュリティーキーの登録結果が無効です。とエラー

日本語表示だとエラーの詳細がわからないので、英語表示に切り替えて、再度登録を実施

Security key registration result is invalid.
NotAllowedError: WebAuthn is not supported on sites with TLS certificate errors.

WebAuthnはTLSがエラーだとダメとのこと。
まずはこれを解消します。
自己証明書を使っていることが原因だと思うので、PC側の証明機関に登録してみます。

証明書の登録はブラウザによって違いますが、Edgeでは設定のプライバシー、検索、サービス-セキュリティ-証明書の管理から登録します。

信頼されたルート証明機関を選択しインポートをクリックします。

証明書のインポートウィザードが起動するので、画面の指示に従い証明書を登録します。(以降は省略)

証明書登録後、Keycloakのアカウント管理画面に再度アクセスするとまだ警告が表示されました。

エラーの内容がNET::ERR_CERT_AUTHORITY_INVALIDから NET::ERR_CERT_COMMON_NAME_INVALIDに変わっていますがCNが違う?

調べてみるとChrome58以降ではSAN(Subject Alternative Name) を加えた自己証明書が必要とのことなので、証明書を再作成します。

まずは以下のようにSANを記載したファイルをsan.txtとして準備します。

subjectAltName = DNS:idp.example.internal

CSRを作らずに自己証明書作っていたので、秘密鍵は既存のを流用して、CSRを作成します。
Country Name等は環境に合わせて設定してください。

$ sudo openssl req -out idp.csr -key idp.key -new
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Kanagawa
Locality Name (eg, city) []:Yokohama
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:idp.example.internal
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

-extfile san.txtを指定して、SANを含める形で証明書を作成します。

$ sudo openssl x509 -req -days 3650 -signkey idp.key -in idp.csr -out idp.crt -extfile san.txt
Certificate request self-signature ok
subject=C = JP, ST = Kanagawa, L = Yokohama, CN = idp.example.internal

作成された証明書の内容を確認し、Subject Alternative Nameが設定されていることを確認します。

$ sudo openssl x509 -text -noout -in idp.crt
~省略~
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:idp.example.internal
~省略~

証明書を差し替えて、Keycloakを再起動します。
PCに登録した証明書の方も新しい証明書に更新します。

再度アクセスするとエラーなく接続できましたのでパスキーの再登録を実施していきます。

登録をクリック

パスキーの保存場所はセキュリティキーを選択します。

セットアップの内容に問題がなければOKで進めます。

セキュリティキーを要求されるので、USBポートにTitanセキュリティーを挿入します。

セキュリティキーへのタッチを要求されるので、Titanセキュリティーのチップの部分にタッチします。

パスキーが保存されます。

Keycloakのアカウントに登録する際のキー名を要求されるので、 入力します。

セキュリティーが登録されたことを確認します。

アクセステスト


他のクライアント(SP/RP)で認証してからテストSPにアクセス

何も聞かれずにアクセスできれば想定通りです。

この検証は画面のリダイレクト等もなく、問題なくアクセスできたので省略。

パスキー設定済みユーザーでテストSPにアクセス

WebAuthnでアクセスできれば想定通りです。

テストクライアントに接続します。
Keycloakの認証にリダイレクトされ、ユーザー名を求められますので、パスキー設定済みユーザーを入力して進みます。

WebAuthnのフォームが表示されたのでセキュリティキーを選択して進めます。

セキュリティキーを要求されるので、USBポートにTitanセキュリティーを挿入します。

セキュリティキーへのタッチを要求されるので、Titanセキュリティーのチップの部分にタッチします。

認証されテストクライアントに接続できました。

パスキー未設定ユーザーでテストSPにアクセス

パスワード認証でアクセスできれば想定通りです。

テストクライアントに接続します。
Keycloakの認証にリダイレクトされ、ユーザー名を求められますので、今回はパスキー未設定ユーザーを入力して進みます。

パスワード入力のフォームが表示されたので、パスワードを入力して進めます。

認証されテストクライアントに接続できました。

まとめ


これでフロー作成の時の実施したい以下の処理は実現できたと思います。

  • 認証済みの場合はそのままアクセス(Cookie認証)

  • 未認証の場合はユーザー名を入力

  • ユーザーにパスキーが登録されていればWebAuthnで認証

  • ユーザーにパスキー未登録の場合はパスワードで認証

手元にセキュリティーキーがない場合にどうするのか等、ほかにも考えることはありますが、セキュリティキーさえあれば、パスワード不要でアクセスできるのはかなり良いのではないかと思います。

参考情報


FIDO2:ウェブ認証(WebAuthn) - FIDO Alliance

Titan セキュリティ キー | Google Cloud

Keycloak

chrome58で、プライベート認証局発行のサーバ証明書が無効になる場合の対処 #Chrome - Qiita

Keycloak - Wikipedia


執筆者プロフィール:田平 隆馬
インフラSEとして約20年のキャリアを経て、2023年11月にSHIFT入社。
得意領域はActive DirectoryやLDAPなどの認証システム。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

PHOTO:UnsplashPhilipp Katzenberger