🗝️

ログインヒントで実現する“安全でスマートな”ログインUX改善

に公開

こんにちは、ログラスでフロントエンドエンジニアをしております、浅井 (@mixplace) です。

今回は、シングルサインオン認証時におけるアプリケーションのログイン体験を改善できる、ログインヒント login_hint のお話をしたいと思います。

はじめに

SaaSやWebアプリケーションを開発している中で、ユーザーから次のようなご相談をいただくことはないでしょうか。

「毎回ログイン画面でメールアドレスを入力するのが面倒なのです。」

「社内ポータルのリンクから、クリックひとつでログイン後の画面に遷移できるようになりませんか」

メールアドレスログインの場合は、パスワードマネージャーを利用してログインするケースが一般的になってきておりますが、BtoB SaaSを利用する際は、シングルサインオン(SAML SSO)を用いて企業のIdPでSAML SSO認証したい場合も一定あるかと思います。

SAML SSOでは、お客様のIdPからクリックひとつでログインを完了できる仕組みとして「IdP-Initiated SSO」が知られていますが、
セキュリティ事情(CSRFリスクなど)を鑑みると、より安全なアプリケーションのログイン画面を起点とした「SP-Initiated SSO」で運用したいケースもあります。

参考解説: SP-Initiated SSO と IdP-Initiated SSO の概要と違い

SP Initiated SSO(SPスタート型)

利用したいサービスプロバイダ(例:Gmail)に直接アクセスすると、自動的にログイン画面(Google)に遷移する方式です。サービス側からログインのプロセスが始まる、一般的なパターンです。

IdP Initiated SSO(IdPスタート型)

最初に会社の認証システムなどにログインし、ログイン後に表示される「マイアプリ一覧」から使いたいサービスをクリックして使い始める方式です。
認証システム側からログインのプロセスが始まることが特徴です。

今回はまさに「SP-Initiated SSO でアプリケーションを利用しながらも、メールアドレスの入力手間を減らしたい」というニーズでした。
「ログインの操作は、少しでも手間を減らしたい」というニーズが、想像している以上にあることを知りました。

では、安全性を保ちつつユーザーの入力の手間を極限まで減らすにはどうすればよいでしょうか。
今回は、OIDC(OpenID Connect)の標準仕様である login_hint を活用した、安全かつスマートな解決策を紹介します。

課題解決の術を探している中で見つけた「login_hint」

今回のきっかけは「社内ポータルサイトからリンクをクリックしたら、IdPを経由してログインを行い、プロダクトにログインできるようにしたい。」という、要望でした。

まず最初に思いつくのは、IdP(Identity Provider)側を起点としてログインを開始する IdP-Initiated SSO の存在です。
これを使えば、ユーザーはIdP上の「マイアプリ ポータル画面」などでアプリのアイコンをクリックするだけで、各アプリケーション(SAML認証の世界ではService Providerと呼称されます)に遷移できます。

一方で、IdP-Initiated SSO には、その仕組み上 CSRF(クロスサイトリクエストフォージェリ)攻撃のリスクを完全に排除することが難しく、「SP-Initiated SSO で運用したい」お話をいただくこともございます。

つまりのところ、「ログインフォームでメールアドレスを入力する処理を省略できる機構」を作ることができれば、シンプルに課題は解決できます。
しかし、ログインフォームに対してパラメーター受け付けて入力済みの状態にするのは、セキュリティリスクを増やし、メンテナンスコストも上げてしまうことに懸念を感じていました。

もっとシンプルな解決策はないものかと、Auth0の公式ドキュメントを読みながら見つけたのが login_hint でした。

今回のケースでは、ポータルサイトからの遷移URLリンクにメールアドレス等の情報をパラメーターとして持たせ、アプリ側でそれを受け取り、IdPへの認証リクエスト(login_hint)に引き継ぐことで実現できます。

ログインヒント(Login Hint)とは

ログインヒント(Login Hint)とは、OpenID Connect (OIDC) の仕様の一部として定義されている標準的なリクエストパラメーターです。

IdP(認証プロバイダ)に対して認証リクエストを送る際、あらかじめ「このユーザーがログインしようとしています」というヒント情報(メールアドレスやユーザー名 等)を渡すことができます。
これを受け取ったIdP側は、ログイン画面のユーザー名入力欄を事前に埋めた状態で表示したり、適切なログインオプションを提示したりすることが可能になります。

主な活用例としては、以下が挙げられます。

  1. アカウント選択の簡略化
    ユーザーが複数のアカウントを持っている場合、特定のアカウントを事前に示唆する

  2. フォームの事前入力
    ログインフォームにメールアドレスやユーザー名を自動的に入力された状態にする

  3. シームレスなSSO体験
    アプリケーション間でユーザーのコンテキストを維持する

主要なIdPは軒並みサポートしている

login_hint の素晴らしい点は、OIDCの標準仕様に基づいているため、多くの主要なIdPで login_hint パラメーターをサポートされていることです。

  • Auth0
  • Okta
  • Google Identity Platform
  • Microsoft Entra ID (旧 Azure AD)

対応方法

login_hint パラメーターを活用すると、実装は驚くほどシンプルになります。
アプリケーション(SP)からIdPへ遷移する際の認可リクエストURL(/authorize)に、クエリパラメーターとして login_hint={メールアドレス} を追加するだけとなります。

また、SaaS アプリケーション側の認証基盤として Auth0 や Okta を採用していて、認証基盤が提供するログインフォームを利用している場合は、login_hint に対応させることが可能です。
具体的には、アプリケーションのフロントエンド側で Auth0.js や NextAuth.js のような認証ライブラリを活用している場合は、追加のパラメーターとして login_hint を渡すだけで対応できます。

https://auth0.com/docs/authenticate/login/auth0-universal-login/universal-login-vs-classic-login/universal-experience#login
https://next-auth.js.org/getting-started/client#additional-parameters

おわりに

今回ログインヒント機能を活用することで、もともとの課題であった「社内ポータルサイトからリンクをクリックしたら、IdPを経由してログインを行い、プロダクトにログインできるようにしたい。」が解決できました。

今回の改修にあたって変更を加えたコードはわずか数行。
DOM操作を行う実装を加えることもなく、公式にサポートされた方法でログイン体験を大幅に向上させることができました。

私にとって、今回の一連の対応で得た気付きは、「公式ドキュメントや標準仕様(OIDC)を読み解いてみる」 という、まさに基本に立ち返る行動の重要さでした。

本記事が「ログイン体験の改善」の1つのケースとして参考となれば幸いです。

それでは、明日からのアドベントカレンダーもお楽しみください!

株式会社ログラス テックブログ

Discussion