SuiteCRM v8.7.0でのEntraID SSO認証の設定

最近、社内でCRMを活用しようという話が出てきて、その中でオープンソースかつ無料で利用できるSuiteCRMに目をつけていました。
ただ、SuiteCRMを社内に導入するにあたり、EntraIDによるSSOは必須要件だったのですが、[公式ドキュメント](https://docs.suitecrm.com/8.x/admin/configuration/saml/8.7.0-saml-configuration/)にEntraIDを用いたSSOについてほとんど記載がなかったので、かなり苦労しました...

コミュニティを見てもEntraIDの設定方法をまとめているものはなかったので、覚書としてまとめておこうと思います。

# 使用するツール
- [SuiteCRM v8.7.0](https://suitecrm.com/)
- [Azure EntraID Enterprise Application](https://learn.microsoft.com/ja-jp/entra/identity/enterprise-apps/add-application-portal)


# 前提条件
- SuiteCRMがSAML認証なしですでに起動できる状態になっていること。起動方法は以下のページを参照してください。
https://docs.suitecrm.com/8.x/admin/installation-guide/downloading-installing/
- SuiteCRM内に、EntraIDでログインしたいユーザーがすでに作成されていること (自動作成もできますが、そちらは[公式ドキュメント](https://docs.suitecrm.com/8.x/admin/configuration/saml/8.7.0-saml-configuration/#_6_user_auto_creation_configuration_reference)を参照してください)

# 手順
## 1. SAML認証に使用するEnterprise Applicationを作成する
SAML認証を行うにあたり、**Enterprise Application**を作成する必要があります。作成方法は以下を参考にしてください。

https://docs.suitecrm.com/admin/administration-panel/sso/azure-saml/

ただ、上記はv7を前提にしているので、そのまま手順に従ってもうまくいきません。
`1.2. Configure the new Application`の部分を、以下のように読み替えてください。

``` bash
SuiteCRM uses the same value for Entity ID, ACS URL and Sign On URL.

The value should be your SuiteCRM URL in the following format:

{CRM URL}/index.php?action=Login&module=Users #この行を
{CRM URL} #この行に読み替える

```

`/index.php?action=Login&module=Users`の部分がいらなくなった感じですね。

## 2. SuiteCRMの.env.localの設定
v7ではSAML認証の設定はAdminメニューから行っていたのが、v8.7.0では、.env.localで指定するようになったんですね。
これ自体は設定項目の幅が広がったのでいいことっぽいんですが、ドキュメント通りにやっても全くうまくいかない...

ということで、EntraIDでSAML認証するには最低限以下の設定が必要でした。

```.env.local
###> SAML CONFIG ###
AUTH_TYPE=saml

# User mapping options
SAML_USERNAME_ATTRIBUTE=http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
SAML_USE_ATTRIBUTE_FRIENDLY_NAME=false

# Connection options
SAML_IDP_ENTITY_ID=https://sts.windows.net/{tenantId}/
SAML_IDP_SSO_URL=https://login.microsoftonline.com/{tenantId}/saml2
SAML_IDP_SLO_URL=https://login.microsoftonline.com/{tenantId}/saml2
SAML_IDP_X509CERT='-----BEGIN CERTIFICATE-----
{証明書の本体}
-----END CERTIFICATE-----'

# Compression
SAML_COMPRESS_REQUESTS=true
```
ポイントとしては、以下の通りです
#### SAML_USERNAME_ATTRIBUTE
SSOでログインする際のユーザー名をどこからとってくるかを設定するプロパティです。
ここで指定している`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name`をどこから持ってきたかというと、`Enterprise Application -> Single Sign-on -> SAML Certificate -> Federation Metadata XML`でダウンロードした中に記載されています。

どうやらこのXMLはSAML認証時に返されるレスポンスが定義されているようで、`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name`を指定すると、Displaynameが**Name**となっている値が取得できるみたいです。

これらの値がどこで定義されているかというと、同じく`Enterprise Application->Single sign-on->Attribute & Claim`に定義されているようです。
この場合のNameは私のアプリでは`user.userprincipalname`となっていました。

#### SAML_USE_ATTRIBUTE_FRIENDLY_NAME
これはSAMLレスポンスのUriの代わりにFrindlyNameを使用するかを指定するプロパティです。
このプロパティはデフォルトで**true**になっているのですが、EntraIDはこの「FRIENDLY_NAME」とやらに対応していません。
対応していると先ほどのXMLファイルに「FriendlyName」という属性が付与されているみたいです。

なので、このプロパティは**false**にする必要があります。
(これに気付くのに数日かかった...)

#### SAML_COMPRESS_REQUESTS
SAML認証のリクエストを圧縮するかを指定するプロパティです。SAML認証のリクエストは二段階で加工することができて、一段階目はBase64でエンコード、二段階目はdeflateで圧縮です。

このプロパティはデフォルトで**false**になっていますが、EntraIDはこれを**true**にしないと以下のエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776102/18a57f87-4637-0c62-3406-6975514a7fcd.png)

## 3. 変更内容の反映
.env.localの編集が完了したら、`./bin/console cache:clear`を実行して設定内容の反映を行ってください。

# まとめ
上記の設定が完了後にブラウザからSuiteCRMを開くと、EntraIDでのログインが行われるはずです。
認証後すぐにログアウト画面が表示される場合は、`SAML_USERNAME_ATTRIBUTE`や`SAML_USE_ATTRIBUTE_FRIENDLY_NAME`あたりの設定がうまくいっていない可能性が高いので、見直してみてください。



EntraIDのSSO認証は需要が多いはずなので、公式ドキュメントで設定例としてあげておいてもらえると助かるんですけどね...