これはなに?
PAM モジュールを作りログイン認証をカスタマイズした物語
スマホへのプッシュ通知を利用してパスワードレスログインを実現しました
(ちなみに PAM は Pluggable Authentication Modules らしいので PAM モジュールという書き方はおかしい)
やったこと
- プッシュ通知を送るための PWA 化したページを用意
- PAM モジュール作成
- PAM の設定ファイル修正
シーケンス図
くわしく
それでは一つずつ見ていきましょう
プッシュ通知を送るための PWA 化したページを用意
やったこと
とりあえずプッシュ通知を送るための PWA を用意しました
今回は自分の PC のログインを行うのと同一 LAN 内にサーバーを立てたので、雑にログインユーザーの登録をするフォームを作り、 service worker をそのページで読み込むようにしました
docker-compose で Node.js のバックエンドサーバー、MySQL のデータベースサーバー、Valkey の KVS サーバーを用意しました
ホスト側にインストールした Nginx で Node.js のバックエンドサーバーにリバースプロキシしました
出来たウェブページにスマホでアクセスし、プッシュ通知の登録をしておくことを忘れずに
ログインしたいコンピューターからこのサーバーへプッシュ通知のリクエストを送ることでプッシュ通知が送信されます
PAM モジュール作成
やったこと
C を利用して PAM モジュールを作成しました
Rustを使ってみようと思いましたが PAM 周りのクレートがよくわからなかったので諦めました
多分クレート使わずに自力でも実装できると思うので今後の課題
C を利用したのでプッシュ通知を送信するための処理はシェルスクリプトの呼び出しで行うようにしました
久々に C を触りましたがやはり文字列操作は面倒なので極力やりたくないですねぇ……
PAM の設定ファイル修正
やったこと
まずファイルの全体像です
#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
# ログインプッシュ通知
auth [success=3 default=ignore] pam_push_auth.so
# here are the per-package modules (the "Primary" block)
auth [success=2 default=ignore] pam_unix.so nullok
auth [success=1 default=ignore] pam_sss.so use_first_pass
# here's the fallback if no module succeeds
auth requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth required pam_permit.so
# and here are more per-package modules (the "Additional" block)
auth optional pam_cap.so
# end of pam-auth-update config
下記の箇所を追記しました
# ログインプッシュ通知 auth [success=3 default=ignore] pam_push_auth.so
パスワード認証が pam_unix.so によって行われるようで、その前にプッシュ通知での認証を行いたい
また、プッシュ通知での認証が通ればログインに成功したい
という要件のため auth sufficient
としました
さいごに
これでログイン時にユーザー名を選択した際にスマホにプッシュ通知が飛んできて、通知のログインボタンを押すことでパスワードレスでログインできるようになりました
プッシュ通知を送るサーバーへアクセスできない場合は通常のパスワード認証に進むのでプッシュ通知サーバーが死んでいてもログインできなくなるようなことはありません
今回プッシュ通知のユーザー登録を手動でやっていますが、ユーザー ID の情報を組み込んだQRコードを表示し、手動でユーザー ID を入力せずにプッシュ通知の登録画面を用意できるとよりユーザーフレンドリーかもしれません
(たとえばクエリストリングに付与しておき、プッシュ通知登録処理の際にクエリストリングからユーザー ID を取得するなど)
このアイデアは Web システムにも組み込めるとは思いますが、 Web システムでやるならパスキーを利用したほうが良いと思われます
それでは良い Linux ライフを