AEM開発者ブログ by YAMATO

アドビ社のデリバリーパートナー大和株式会社のAEM開発者ブログです。

Publish環境でSFDCをIDPとしたSSOを実装する

AEM Developerの皆様、こんにちは! 大和株式会社の熊井です。

今回は「Publish環境でSalesforceをIDPとしたSSOを実装する」為にはどのようなステップを踏めばいいかをご紹介します。

前提

環境は以下の構成になっているものとします

  • CDNにはCloudFrontを使用
  • Dispatcher(Apache), Publisher各1台の構成

大きな流れ

【1】AEMキーペアの作成
【2】IDPの設定
【3】AEMの設定
【4】Apache Dispatcherの設定
【5】Cloud Frontの設定
【6】グループの同期

【1】AEMキーペアの作成

後の手順でAEM及びIDP側に登録するための秘密鍵及び証明書を作成します。
秘密鍵はPKCS8のフォーマットで作成する必要があるため、下記手順で作成を進めます。
今回はopensslを使用した方法をご紹介しますが、要件に合わせて変更してください。
1.RSA秘密鍵と公開鍵 + 証明書の作成

$ openssl req -x509 -sha256 -days 365 -newkey rsa:4096 -keyout aem.key -out aem.crt

pass: <password>
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

2.DERフォーマットへ変換

openssl rsa -in aem.key -outform der -out aem.der

3.変換したDERファイルの確認

openssl rsa -in aem.der -inform der -text -noout

4.PKCS8フォーマットへ変換(nocryptオプションをつける必要あり)

openssl pkcs8 -topk8 -inform der -nocrypt -in aem.der -outform der -out aem-pkcs8.der

ここまでの作業で下記がそろえば完了です。

aem-pkcs8.der
aem.crt
aem.der
aem.key

【2】IDPの設定

この部分はIDP管理担当者が実装をする部分となるので、AEM側からどのような情報を提供することになるか、どういった情報を受け取ればいいかという観点で記載します。
1. 開始URL:
 Salesforceのポータルから接続しに行くURL。
 主に検証時に使用するものであり、通常の認証フローの中には関わってこないため任意の場所で問題ありません。
2. エンティティID:
 任意の文字列。後ほどAEMのOSGi設定に同じ文字列を設定します。
3. ACS URL:
 IDPでの認証成功後、AEMにランディングする際のURL。任意のパス(通常は認証をかけるパス) + /saml_loginとします。
 https://blog.yamato-ltd.com/sso 配下に対し認証をかける場合はhttps://blog.yamato-ltd.com/sso/saml_login とするのが一般的です。
4. シングルログアウトURL:
 Salesforceのポータルからユーザがログアウトした際に、SPに通知されるべき、LogoutRequests / LogoutResponses を受け取るURL。シングルログアウトを実装する際にのみ使用します。
5. シングルログアウトバインド:
 シングルログアウトをHTTPリダイレクトで実施するかPOSTで実施するかを選択します。
6. 取引責任者メール:
 管理者となる方のメールアドレス
7. 証明書:
 【1】で作成したaem.crtをIDPに登録します。IDPにおける署名のアルゴリズムはRSA-SHA256を選択します。

以上をAEMから提供の上、IDPでの設定が完了したら下記情報を受け取ります。
1. Name Id Format(例:urn:oasis:names:tc:SAML2.0:nameid-format:persistent):
 IDPで設定しているものと同じものをAEMで設定する必要があります。
2. IDP証明書:
 AEMのTrust Storeに登録が必要です。
3. IDP-initのログインURLまたはSP-initのPostエンドポイントやSP-initのRedirectエンドポイント:
 認証をかけたパスに対してリクエストが来た際、IDP URLとしてこのいずれかに遷移を行わせます。
4. シングルログアウトエンドポイント:
 AEM側でログアウト処理を行った際、AEMに設定したこの値の場所へリクエストを転送します。
5. カスタム属性 (ユーザーがログインする際に引き渡される属性):
 要件に依りますが、姓名、メールアドレスなどIDPからAEMへ同期をする情報を受け取ります。

【3】AEMの設定

1.Trust Storeの設定:
 IDP証明書をPublishのTrust Storeに登録します。https://AEM_PUBLISH_INSTANCE/libs/granite/security/content/truststore.html または Tools -> Security -> Trust Store に遷移し「Add Certificate from CER file」を選択してIDP証明書をアップロードしSubmitします。Submit完了後、「Alias」に表示される文字列(例:certalias___111111111111)をコピーしておきます。これは後の手順で使用します。
2.Authentication serviceユーザーにKeyStoreを設定:
  https://{AEM_PUBLISH_INSTANCE}/security/users.html に行き、「authentication-service」を見つけます。「authentication-service」を選択したら新しいKeyStoreを作成します。この際設定したパスワードは後ほど使用するため保存しておきます。Aliasに任意の文字列(例:aem-test-alias)を入力し、Private Key Fileに【1】で作成した「aem-pkcs8.der」を、Certificate Chain Filesにaem.crtをアップロードしSubmitします。
3.OSGi設定の追加:
  以下4つのOSGi設定を追加します(設定値はdefaultから変更する可能性のあるもののみ記載)
3-1.Adobe Granite SAML 2.0 Authentication Handler:
・assertionConsumerServiceURL:
 IDPに登録したACS URL
・defaultGroups:
  IDPで認証を受けたユーザーがAEM内に同期された際、自動的に追加されるAEMグループ(例:sfdc_group)
・defaultRedirectUrl:
 遷移元が不明であった場合の/saml_loginへランディング後のリダイレクト先。(例:/)
・idpCertAlias:
 「Trust Storeの設定」で取得した「Alias」に表示されている文字列(例:certalias___111111111111)
・idpUrl:
 IDP-initのログインURL。要件によってはSP-initのPostエンドポイントやSP-initのRedirectエンドポイントにすることもあり得ます。
・keyStorePassword:
 「Authentication serviceユーザーにKeyStoreを設定」で設定したKeyStoreのパスワード。一般的にはcrypto化したものを設定します。
・logoutUrl:
 IDPのシングルログアウトエンドポイント(シングルログアウトを使用しない場合は不要)
・nameIdFormat:
 IDPのName Id Format(例:urn:oasis:names:tc:SAML2.0:nameid-format:persistent)
・path:
 認証を行うパス(例:/content/sso)
・serviceProviderEntityId:
  IDPに設定したエンティティID
・spPrivateKeyAlias:
 「Authentication serviceユーザーにKeyStoreを設定」で設定したAlias(例:aem-test-alias)
・storeSAMLRespons:
 暗号化されたSAMLレスポンスをユーザーノードにプロパティとして保持するか否か。それらを用いて後続処理を行う場合はTrue。
・synchronizeAttributes:
 SAMLレスポンスに含まれる情報をユーザーノードに同期する際の定義(例:[FirstName=profile/familyName,LastName=profile/givenName])
・userIntermediatePath:
  同期したユーザーをどのパス配下に作成をするか(例:/sfdc -> /home/users/sfdc配下にユーザーが作成される)
3-2.Apache Sling Referrer Filter:
・allow.empty:
 trueに設定
・allow.hosts:
 IDPのホストを設定
・allow.hosts.regexp:
 ホストの正規表現を設定
3-3.Sling Authenticator:
・sling.auth.requirements:
 認証をかけるパスを追加(例:[/libs/granite/oauth/content/authorization,/content/sso])
3-4.Token Authentication Handler:
・token.encapsulated:
 trueに設定

【4】Apache Dispatcherの設定

1.apache rewriteの追加:
 多くの場合、apacheのリダイレクト、リライトを用いてURLの正規化を行っていると思います。SAML認証の要件においては/saml_loginできたリクエストはそのままの形(拡張子をつけたりせず)でPublishへ通す必要があるため、それ用のリライト設定を追加します。

    RewriteRule ^/sso/saml_login$ /content/sso/saml_login [NC,PT]

2.dispatcher filterの設定:
 /saml_loginへはPOSTで通信が来るためその部分を許可します。

    /1018 {​​​​​​ /type "allow" /method "POST" /path "/content/sso/saml_login"}​​​​​​

3.apache vhost, dispatcher farms, dispatcher vhost:
 SAML認証用にサブドメインを追加する場合などは対応が必要になります。

【5】Cloud Frontの設定

cache behaviorの設定が必要です
1.Forward Cookies:
 「whitelist : login_token, saml_request_path」を設定する。ここを行わずdefault(none)のままの場合、AEMがlogin-tokenを使用できずAEM -> IDPの無限ループが発生します。
2.headers:
 「user-agent」を追加する。これを行わない場合、Sling AuthenticatorがBasic認証として処理してしまいSAML認証のフローに入れません。

【6】グループの同期

SFDCで管理されているユーザー情報は初回ログイン時にAEMに同期されます。その際、SFDC側で設定しているグループ情報も同期したいというケースがあります。
1.Adobe Granite SAML 2.0 Authentication Handlerの修正:
 「groupMembershipAttribute」を指定します。後述の例の場合は"Group"
2.グループの作成:
 下準備としてAEM内にグループを作成しておく必要があります。SFDCからのログイン時に送られてくるSAML Responseを後述の形式にしておくことで、AEM内に作成済みの同名のグループへユーザーを属させることが出来ます。
3.SAML Responseのセットアップ:
 SAML Responseを以下の形式にセットします。これによってAttributeValueに指定されているグループと同名のAEM内のグループへユーザーが同期されます。

<AttributeStatement>
    <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn">
        <AttributeValue>メールアドレス</AttributeValue>
    </Attribute>
    <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
        <AttributeValue>Last Name</AttributeValue>
    </Attribute>
    <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
        <AttributeValue>First Name</AttributeValue>
    </Attribute>
    <Attribute Name="Group">
        <AttributeValue>groupA</AttributeValue>
        <AttributeValue>groupB</AttributeValue>
        <AttributeValue>groupC</AttributeValue>
    </Attribute>
</AttributeStatement>

最後に

いかがでしたでしょうか。Publishが1台構成の場合は上記手順によりSSOの実装が完了します。
Publishが2台以上の構成の場合は
・hmac keyの同期
・Publish間のユーザー情報の同期
・sticky cookieの実装
などが加わるためもう少し必要なステップが追加されます。
またIDPにSales ForceではなくOktaを使用する、などといったケースもあると思いますが、その際も基本的には同じ手順で実装が可能です。
PublishにおけるSSOの実装は必ずしもメジャーではありませんが、会員専用サイトの構築を行う為には必須の知識となりますので是非触れてみてください。

最後までお読みいただき、ありがとうございました。