Salesforceの認証プロセスとして独自のログインフローを構築できるということで、Salesforceが公開しているパッケージを使って以下のチュートリアル(TOTPの2要素認証)に従って検証してみました。
Login-Flows – developer.force.com

ログインフローは以下のスライドも詳しいです!
7 power night2014_kanbayashi

ログインフローについて

ログインフローを利用することで、Flow Designerで作成したフローとログイン時の処理を紐付けることができ、通常の認証処理が完了した後、Flow Designerで作成したフローを走らせることができます。Flow DesignerではフローのプラグインをApexを使って作成でき、このプラグインからTOTP用のQRコード生成やバリデーションをすることが可能なので、独自の多要素認証の認証フローを作成することができます。

パッケージのインストール

まずは以下のパッケージをSalesforce環境にインストールします。
https://login.salesforce.com/packaging/installPackage.apexp?p0=04to0000000WA6J

フローの作成

設定>作成>ワークフローと承認申請>フロー でインストールしたフロー一覧が表示されるので、SF-TOTPの[オープン]をクリックします。

flowdesigner-list

こんな感じでフローが表示されます。

flowdesigner-sf-totp

TOTPPluginのクラスは以下の内容となっています。

フローのプラグインを作るにはProcess.Pluginインターフェースを実装する必要があります。実装するメソッドはdescribeとinvokeの2つで、describeメソッドはフローのプラグインの外部仕様、invokeメソッドは実際の処理の内容を定義します。
describeメソッドではProcess.PluginDescribeResultのインスタンスを返します。Process.PluginDescribeResultのインスタンスはフローエレメントの入出力のパラメータを定義することになります。
invokeメソッドではProcess.PluginRequestが引数として渡るので、当インスタンスから入力値を受け取り、Process.PluginResultで出力する値を定義します。invoke内の入出力パラメータはdescribeで定義したものになります。

サンプルのフローの説明をしていきます。
TOTP用のシークレットを発行していない状態では以下の様なフローになります。

  1. 1つ目のTOTPPluginのフローエレメントでQRコード及びTOTP用のシークレットを発行する。
  2. secretが発行されているのでRegistrationのエレメントではRegisterのフローを進む。
  3. Registration Screenの画面では取得したQRコードを表示しつつ、TOTPのテキストボックスを配置する。
    →56行目で処理されるOTP_REGISTRATION_INPUTをセット
  4. 2つ目のTOTPPluginでは入力したTOTPと1で発行したsecretからバリデーションを行う
    →86行目のAuth.SessionManagement.validateTotpTokenForKey(secret, otp)

TOTP用のシークレットが既に発行されている状態では以下の様なフローになります。

  1. 1つめのTOTPPluginのエレメントでは何もせずスルー(状態変数が変わるものの、後続に影響なし)
  2. 1でsecretを発行していないのでRegistrationのエレメントでGet TOTPのフローを進む。
  3. Get Token Screenの画面ではTOTPのテキストボックスを配置する。
    →59行目で処理されるOTP_INPUTをセット
  4. 2つ目のTOTPPluginでは入力したTOTPを使ってバリデーションを行う。
    →76行目のAuth.SessionManagement.validateTotpTokenForUser(otp)

TwoFactorInfoオブジェクトではユーザの2要素認証の共有秘密鍵を管理していて、Auth.SessionManagement.validateTotpTokenForUserではユーザに割り当てられた秘密鍵を使って入力値の検証を行っています。

ログインフローの作成

セキュリティのコントロール>ログインフローに移動します。

loginflow-list

[新規]を押下して、こんな感じでプロファイルに紐付けて作成すればOK。

loginflow-new

あと、ログインフローを利用する場合は、プロファイルの[ユーザインターフェースログインの 2 要素認証]のチェックを外した方が良いです。私が試した時に2要素認証⇔ログインフローの無限ループになりました。

フローの実行

クレデンシャルによるフォームログイン後、初回はAuth.SessionManagement.getQrCode()で取得したQRコードのURLの画像が埋め込まれたトークンの入力フォームが表示されます。

loginflow-qr-input-first

二回目以降はQRコードの画像は出ません。

loginflow-qr-input

2要素認証で作成した共有秘密鍵はTwoFactorInfoに保持されますが、こちらはdelete文で削除できません。削除するにはユーザの詳細画面で時間ベースのトークンの[削除]リンクをクリックすればOKです。

loginflow-delete-totp-token

まとめ

今回はTOTPの2要素認証のパターンでしたが、フローではメールを飛ばしたり、色んな条件分岐や画面を組み合わせることが出来るため、柔軟にカスタマイズすることが出来ます。Auth.SessionManagementクラスには組織の信頼済みIP範囲内かどうかを確認するメソッドがあったり、実行時の日時等をPlugin内のApexで取得できるので、リスクベース認証的なことも実装できそうな感じです。