sysPassってタグでサジェストされなかったのですが、あまり使っている人いないのでしょうか。
皆さんの会社ではパスワードの管理どうしていますか?
シンプルウェイでは可能な限り公開鍵認証やシングルサインオンに集約するようにしていますが、クライアントから預かるアカウントとか、どうしてもそれではまかないきれないパスワードってのが出てきてしまっています。
現在シンプルウェイではISMSの取得を目指していて、アカウント管理というのも課題の一つになっています。
そこで今回sysPassというオープンソースアプリケーションを利用することにしました。
sysPassを選んだ理由は
- 社内でアカウント情報をシェアできること
- シェアできる範囲が設定可能であること
- オープンソースであること
- シングルサインオンできること
です。
(同じようなアプリケーションではPassboltというのもあります。こちらのほうが認証がGPGでよりセキュアだったり、UIがGmailっぽかったりと、個人的にはこちらを推したいところですが、ディレクトリサービスと連携する場合は有償版になってしまうのでsysPassで妥協しました)
さて本題ですが、sysPassにはBasic認証で認証したアカウントをそのままアプリケーションの認証に使うような機能があるようです。
これを mod_auth_openidc と組み合わせたら OpenID Connect で SSO できそうだなぁと思って、試行錯誤した結果うまくできたのでまとめたいと思います。
最初に mod_auth_openidc のセットアップが必要ですが、その説明は割愛します。このあたりが参考になるでしょう。
シンプルウェイはGoogle Workspaceを使っているのでGoogleをIdPとして設定しておきました。
mod_auth_openidc で認証したら環境変数に認証情報が入ってくるので、これをつかってBasic認証に見せかけます。
変更するファイルは2つだけです。
sysPassのルートディレクトリにある index.php の define() のあとに下記のような行を追加します。
define('APP_ROOT', __DIR__);
define('APP_MODULE', 'web');
↓
define('APP_ROOT', __DIR__);
define('APP_MODULE', 'web');
if (!empty($_SERVER['OIDC_CLAIM_email']) && !empty($_SERVER['OIDC_CLAIM_sub'])) {
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic ' . base64_encode($_SERVER['OIDC_CLAIM_email'] . ':' . $_SERVER['OIDC_CLAIM_sub']);
}
OIDC_CLAIM_ の部分は mod_auth_openidc で設定するプリフィックスなので、カスタマイズしている場合は読み替えが必要です。
sysPassのBasic認証ログインはIDとパスワードをそのままローカルのユーザーテーブルに突き合わせて認証するようなので、OpenIDの認証情報からパスワードに相当するものを割り当てなければなりません。
上の例では sub を使ってしまっていますが、Googleの場合は数字で構成されているのであまりよろしくはないですね。気になる方は email・sub・ソルトを組み合わせてハッシュ値をパスワードにするなど工夫してもいいかもしれません。
続いて lib/SP/Services/User/UserService.php の createOnLogin() 関数を下記のように書き換えます。
public function createOnLogin(UserLoginRequest $userLoginRequest)
{
$userData = new UserData();
$userData->setLogin($userLoginRequest->getLogin());
$userData->setName($userLoginRequest->getName());
↓
public function createOnLogin(UserLoginRequest $userLoginRequest)
{
$userData = new UserData();
$userData->setLogin($userLoginRequest->getLogin());
$userData->setName($userLoginRequest->getLogin());
Basic認証だとユーザーテーブルのnameに相当する情報がないので、自動アカウント作成時にこれはNULLになりますが、データベースの制約でそれを許可していないのでエラーになってしまうようです。ここをログインIDをデフォルト値として使うよう変更します。
(これおそらくsysPassのバグだと思うんだよなぁ。せっかくOSSなので、時間ができたらちゃんと調べてコントリビュートとしたいところ)
最後にsysPassでBasic認証ログインと自動アカウント作成を有効にしておきます。デフォルトグループとデフォルトプロファイルも設定しておかないとエラーになるようなので、これも合わせて設定しておきます。
これらの変更を行うと
- sysPassへアクセス
- IdPにリダイレクト
- 認証して帰ってくるとsysPassのログインフォームが表示される
- ID/パスワードは入力せず、そのままログインボタンを押す
- ログイン完了
という動きになります。