2024年1月3日水曜日

ログインさせたいユーザを指定してIdPへFederationする(SAML/OpenID Connect)

こんにちは、富士榮です。

SAMLでもOpenID ConnectでもFederation構成をしているとService Provider(SP)やRelying Party(RP)側であらかじめIdentity Provider(IdP)側で認証させたいユーザ名を指定したいケースがしばしばあります。
典型的なケースの一つは多要素認証をオンデマンドで実行させた場合で、普通のページには第1要素であるユーザ名とパスワードで認証、決済ページには追加要素で認証を要求する、というシナリオは結構あり得るシナリオです。この場合、第1要素で認証されたユーザと追加要素で認証されたユーザをSP/RP側で比較することで同じ人であることを検証することももちろん可能なのですが、できればあらかじめ追加要素で認証させたいユーザの識別子をSP/RPからIdPに渡してあげることで利用者が再度ユーザIDをIdP側で入力する必要がなくなるのでUXも向上します。
この様なシナリオは当然のことながらSAMLでもOpenID Connectでもサポートされています。

SAMLの場合

SAMLを使う場合、SPからのSAML Requestの中にSubjectを指定することができます。
OASISのSAML2.0 coreの仕様の3.4.1のAuthnRequestのエレメントの章に記載があるSubjectが該当します。
SAML 2.0 core仕様

https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf

 こんな感じのリクエストになります。

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
                    ForceAuthn="false"
                    ID="a133c62aafc8dcee7a69481de5af763c4ee370494"
                    IssueInstant="2024-01-03T03:28:40Z"
                    Destination="https://idp.example.jp/sso/login"
                    AssertionConsumerServiceURL="https://sp.example.com/acs"
                    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                    Version="2.0"
                    >
    <saml:Issuer>https://sp.example.com/sp</saml:Issuer>
    <saml:Subject>
        <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@example.jp</saml:NameID>
    </saml:Subject>
</samlp:AuthnRequest>
実際の動作は上記リクエストを受け取ったIdP側の実装に依存するので利用するIdPの仕様を確認してださい。ちなみにEntra ID(Azure AD)の場合はこの方法ではなくクエリパラメータにlogin_hint=test@example.jpという形で付加してリクエストを投げる形になります。(この辺りを参照:https://learn.microsoft.com/ja-jp/entra/identity-platform/single-sign-on-saml-protocol#subject)ただし、Entra IDが外部IdPとFederationしている時はlogin_hintではなくusername=test@example.jpという形でパラメータ名が異なるので要注意です。
また、Azure AD B2Cでは要求リゾルバという仕組みでSubjectの情報を取得することができるので、このサブジェクトに応じた処理を書けば割と自由に実装ができます。
Okta CIC(旧Auth0)はSAML RequestのSubjectをちゃんと判別してくれそうです。(この辺りを参照:https://community.auth0.com/t/pass-login-hint-to-saml-provider/92546

OpenID Connectの場合

こちらはシンプルにlogin_hint属性をクエリパラメータに付加することで実現できます。(仕様はこちらを参照;https://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html)こんな感じでAuthentication Requestにパラメータをつけるだけです。
HTTP/1.1 302 Found
  Location: https://server.example.com/authorize?
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &login_hint=test@example.jp
こちらもSAMLと同様にIdPの実装に依存するので実際の動作はIdPの仕様を確認してみてください。ちなみにAzure AD B2Cの場合はSAMLと同じく要求リゾルバで属性の取得ができます。

ちなみに他にもヒント系のパラメータは色々とあります。
また、SP/RPから認証コンテキストを指定したい場合もあるのですが、現在SAMLについてはAuthnContextClassRefというパラメータがありますが、OpenID Connectについてはacr/amrをclaimsパラメータで渡す方法はありますが、レベルの指定方法の共通化をどうするべきか?についてはPam Dingleさんを中心にIntenet Identity Workshopで議論が続けられているので今後の注目ポイントかもしれません。

0 件のコメント: