今さらSAML2.0を理解する(1)：OpenAMとsimpleSAMLphpでSAML連携してみよう

# はじめに
SAML2.0はメジャーな認証連携のプロトコルとして長きに渡り利用されてきました。
IdPやSP、メタデータやバインディング、署名検証などそれを取り巻くキーワードもよく知られているところと思います。
エージェント方式などレガシーな連携方法と比較して、仕様が明確で連携する双方のエンドポイントでの検証方法が確立され、より安全に認証連携できる方法としてクラウド上でも広く利用されています。
もうその技術も枯れたものとして認識され、ごく一般的な連携方法として利用していますが、
実際の送受信するSAMLリクエスト・レスポンスの内容やメタデータのXMLを見てみると、
そこかしこで定義されている値が何のために利用されているのかわからなかったり、
エンドポイント間で受け渡す際のパラメータのエンコーディング方法や署名の検証方法も深く知らなかったりします。
当たり前のように扱っているけれども本当は不明なところが多いのがSAML2.0ではないでしょうか。
そこでもうすこしSAML2.0について学びなおしてみようかとこの連載を企画しました。

第1回として、まずは実際にSAML2.0の連携する環境を作成してみようと思います。
SAML2.0のIdPとしてOpenAMを利用し、SPとしてsimpleSAMLphpを利用します。

# simpleSAMLphpのインストールと初期設定
simpleSAMLphpは本記事ではAlmalinux9にインストールします。
バージョンは執筆時点の最新の2.3.5です。
OSのデフォルトではPHPのバージョンが8.0ですが、simpleSAMLphpのバージョン2.3.5を利用するときは8.1以上が必要です。
phpモジュールを以下コマンドで切り替えておきます。
```
# dnf module reset php
# dnf module enable php:8.1
```


まずは、必要なパッケージをインストールしてください。

```
# yum install -y httpd mod_ssl php
```

次にsimpleSAMLphpのパッケージをインストールします。
GitHubからダウンロードします。

```
# cd /home/osstech
# wget https://github.com/simplesamlphp/simplesamlphp/releases/download/v2.3.5/simplesamlphp-2.3.5-full.tar.gz
# tar xvf simplesamlphp-2.3.5-full.tar.gz
# mv simplesamlphp-2.3.5 /opt/
```

simpleSAMLphpのパッケージがインストール出来たら、
設定ファイルを作成します。

```
# cd /etc/httpd/conf.d
# vi simplesamlphp.conf
```

下記の内容を編集で作成してください。

```
<VirtualHost *:443>
    SSLEngine On
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

    ServerName sp1.qiita.osstech.co.jp
    DocumentRoot /var/www/html

    ErrorLog logs/ssl_error_log
    CustomLog logs/ssl_access_log combined

    SetEnv SIMPLESAMLPHP_CONFIG_DIR /opt/simplesamlphp-2.3.5/config

    Alias /simplesaml /opt/simplesamlphp-2.3.5/public

    <Directory /opt/simplesamlphp-2.3.5/public>
        <IfModule mod_authz_core.c>
          Require all granted
        </IfModule>
    </Directory>
</VirtualHost>
```

設定内容を簡単に説明します。
以下の3行はこのサーバのSSL設定です。
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

下記はsimpleSAMLphpの設定ディレクトリを指定します。
SetEnv SIMPLESAMLPHP_CONFIG_DIR /opt/simplesamlphp-2.3.5/config

下記はsimpleSAMLphpのWebフォルダをsimplesamlというコンテキスト名で指定しています。
Alias /simplesaml /opt/simplesamlphp-2.3.5/public

以下の行でsimpleSAMLphpには全てのユーザーがアクセス可能としています。
&lt;Directory /&gt;
　&lt;IfModule mod_authz_core.c&gt;
　　Require all granted
　&lt;/IfModule&gt;
&lt;/Directory&gt;

SSL通信のために自己証明書を作成します。
```
# openssl genrsa 2048 > /etc/pki/tls/private/localhost.key
# openssl req -new -key /etc/pki/tls/private/localhost.key -subj '/C=JP/ST=Tokyo/L=Shinagawa-ku/O=OSSTech/OU=IT/CN=sp1.qiita.osstech.co.jp'  > /etc/pki/tls/certs/localhost.csr
# openssl x509 -days 3650 -req -signkey /etc/pki/tls/private/localhost.key < /etc/pki/tls/certs/localhost.csr > /etc/pki/tls/certs/localhost.crt
```

simpleSAMLphpの設定ファイルを配備します。
```
# mv /opt/simplesamlphp-2.3.5/config/acl.php.dist /opt/simplesamlphp-2.3.5/config/acl.php
# mv /opt/simplesamlphp-2.3.5/config/authsources.php.dist /opt/simplesamlphp-2.3.5/config/authsources.php
# mv /opt/simplesamlphp-2.3.5/config/config.php.dist /opt/simplesamlphp-2.3.5/config/config.php
```

SPのエンティティIDを変更します。
```
sed -i -e "s@'entityID' => 'https://myapp.example.org/',@'entityID' => 'https://sp1.qiita.osstech.co.jp/simplesaml',@" /opt/simplesamlphp-2.3.5/config/authsources.php
```

管理者ユーザー(admin)のパスワードを変更します。
```
sed -i -e "s/'auth.adminpassword' => '123',/'auth.adminpassword' => 'password',/" /opt/simplesamlphp-2.3.5/config/config.php
```
simpleSAMLphpのキャッシュディレクトリを作成します。
```
mkdir -p /var/cache/simplesamlphp/core
chown apache:apache /var/cache/simplesamlphp/core
chmod 755 /var/cache/simplesamlphp/core
mkdir -p /var/cache/simplesamlphp/admin
chown apache:apache /var/cache/simplesamlphp/admin
chmod 755 /var/cache/simplesamlphp/admin
mkdir -p /var/cache/simplesamlphp/saml
chown apache:apache /var/cache/simplesamlphp/saml
chmod 755 /var/cache/simplesamlphp/saml
```

最後にApacheの再起動と自動起動設定をします。

```
# systemctl restart httpd
# systemctl enable httpd.service
```

ブラウザで以下のURLにアクセスして画面表示可能か確認します。
https\://sp1.qiita.osstech.co.jp/simplesaml/
![simplescreen1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/3201802e-f91a-45d6-8542-5b879649bd7a.png)

管理者画面に設定したadmin/passwordでログインします。
https\://sp1.qiita.osstech.co.jp/simplesaml/module.php/admin/
![simplescreen2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/055a95d8-49a7-45b1-b1fb-b7dda56c593f.png)

以上でsimpleSAMLphpのインストールと初期設定は完了です。

# OpenAMの設定
※弊社製品のOpenAM14.5のバージョンで設定をしています。

## SAML2 ホストアイデンティティープロバイダ設定作成

ますはじめに、OpenAM上にIdPプロバイダを作成します。
OpenAMの管理コンソールにアクセスして、ダッシュボードの[SAMLv2 プロバイダを作成]をクリックします。
![openamconfig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/3c2cf55c-76c6-40fc-b892-182dd3594ff5.png)

次に[ホストアイデンティティープロバイダの作成]をクリックします。
![openamconfig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/6d626cf7-c29e-4255-9f90-30d45ffca3e7.png)

IdPの設定画面が表示されます。
[名前]はIdPのエンティティIDとなります。
OpenAMに管理者用とユーザーアクセス用とFQDNを分けている場合は、ユーザーアクセス用のFQDNを設定してください。
[署名鍵]に「test」を選択します。
[新しいトラストサークル]に任意の名称を入力します。ここでは「qiita_cot」としています。
[ベースURL]は名前と同様にユーザーアクセス用のFQDNを設定します。
他の値はデフォルト値のままで右上の[設定]を押します。
![openamconfig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/54fe5a13-a15e-4601-aeee-9f3a624c235c.png)

設定が完了した画面が表示されるので右下の[終了]を押します。
![openamconfig4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/5912e49e-d679-498e-b3d1-2783ecca117f.png)

上部のタブから[連携]のリンクを押すと、[トラストサークル]と[エンティティープロバイダ]の欄に追加したエントリが表示されています。
![openamconfig5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/13b3b13c-4af2-4f73-9586-48636c390720.png)

[エンティティープロバイダ]欄の「https\://sso.qiita.osstech.co.jp/openam」のリンクを押すとホストIdPに関する詳細なパラメータを変更することが出来ます。
![openamconfig6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/3afb6741-37c1-4f99-a3f0-50eb09715eed.png)

ホストIdPの設定は完了です。

## SAML2 リモートサービスプロバイダ登録

OpenAMにsimpleSAMLphpをリモートサービスプロバイダとして登録します。
simpleSAMLphpの管理者画面にadmin/passwordでログインします。
https\://sp1.qiita.osstech.co.jp/simplesaml/module.php/admin/

上部の[連携]のリンクをクリックしてHosted entitiesに表示されているdefault-spの下矢印を押します。
![simplescreen3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/5888f815-6d86-4f2f-8f1c-ace801a39fea.png)

表示されたSAML MetadataのURLをクリックしてダウンロードするか下部のメタデータXMLフォーマットをコピーしてファイルとして保存してください。
![simplescreen4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/bdc488c5-e350-471c-aa2d-52036a040dff.png)

SPのメタデータが取得できたら、OpenAMの管理画面で登録作業をします。
OpenAMの管理コンソールにアクセスして、ダッシュボードの[SAMLv2 プロバイダを作成]をクリックします。
次に[リモートサービスプロバイダを登録]をクリックします。
![openamconfig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/6d626cf7-c29e-4255-9f90-30d45ffca3e7.png)

[メタデータファイルはどこに存在しますか？]で「ファイル」を選択します。
続いてその下に表示される「アップロード」を押します。
![openamconfig7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/e4a4b20b-e975-4399-82a4-f64a1bd74f61.png)

ポップアップでファイルを選択する画面が表示されるので、「参照」ボタンで先ほどダウンロードした
simpleSAMLphpのメタデータファイルを選択して、「ファイルのアップロード」ボタンを押します。
![openamconfig8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/2ac39cdf-e9b6-49d9-b0ff-88b6d0ee5eeb.png)

トラストサークルはIdPを作成したときのトラストサークルを選択して、右上の「設定」ボタンを押します。
完了画面が表示されたら「了解」ボタンを押します。
![openamconfig9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/24e0f181-a96c-4698-88fe-73d87569cf49.png)

上部のタブから[連携]のリンクを押すと、[エンティティープロバイダ]の欄に追加したSPのエントリが表示されています。
![openamconfig10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/1eb34506-4ad7-4076-a5d5-c859f84356bf.png)

[エンティティープロバイダ]欄の「https\://sp1.qiita.osstech.co.jp/simplesaml」のリンクを押すとリモートSPに関する詳細なパラメータを変更することが出来ます。
![openamconfig11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/79501d08-539d-4436-bd97-e376840ab1fc.png)

「表明コンテンツ」タブで署名アルゴリズムを変更します。
デフォルトから「http\://www.w3.org/2001/04/xmldsig-more#rsa-sha512」に変更してください。
OpenAMのデフォルト設定では「rsa-sha1」が使用されますが、simpleSAMLphpで強度の低いアルゴリズムを許可していないためSAML連携する際に失敗します。
![openamconfig13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/fc254bb8-3cb9-4bca-981c-18d8c0f09b17.png)

「表明処理」タブでリモートSPに連携する属性を設定できます。
属性マッパーの「新しい値」に以下のそれぞれ２つの項目を入力して「追加」を押します。
saml-uid=uid
saml-cn=cn
上記は[SAML属性名]＝[データストア属性名]となります。
データストア属性名はOpenAMのデータストアで取得可能な属性で、SAML属性名はSAMLレスポンスのアサーションに付与される名称になります。
「現在の値」に追加されたら、右上の「保存」ボタンを押します。
![openamconfig12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/45ff7417-2a9b-46c1-80a1-5cdfcb62ae1b.png)

これでOpenAMの設定は完了です。
今回は既にデータストアにはOpenLDAPを設定してあり、データストア認証モジュールでIDパスワード認証をしてログインします。

# simpleSAMLphpにリモートアイデンティティープロバイダの登録
simpleSAMLphpにOpenAMをリモートIdPとして登録します。

## OpenAMのIdPメタデータ取得
OpenAMのメタデータエクスポートURLにアクセスしてIdPのメタデータを取得します。
```
https://(OpenAMコンソールFQDN)/openam/saml2/jsp/exportmetadata.jsp?entityId=(IdPのエンティティID)&realm=(ユーザーアクセスレルム)
```
[OpenAMコンソールFQDN]はOpenAMに管理者用とユーザーアクセス用とFQDNを分けている場合は、管理者用のFQDNを指定してください。
[IdPのエンティティID]はホストIdPを登録したときの「名前」を指定してください。
レルムを管理者用とユーザーアクセスレルムで分けている場合はrealmパラメータを設定してください。
[ユーザーアクセスレルム]はIdPを登録している「レルム名」を指定してください。
この記事で作成している環境では以下となります。
```
https://openam1.qiita.osstech.co.jp/openam/saml2/jsp/exportmetadata.jsp?entityId=https://sso.qiita.osstech.co.jp/openam&realm=usr
```

以下のように画面にメタデータが表示されたら右クリックでページのソースを表示してファイルとして保存してください。
![spsetting1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/86633a83-0155-4861-9781-b9bfd6c1cb92.png)

## simpleSAMLphpにIdPメタデータ登録
OpenAMで取得したIdPメタデータをsimpleSAMLphpに登録します。

simpleSAMLphpの管理者画面にadmin/passwordでログインします。
https\://sp1.qiita.osstech.co.jp/simplesaml/module.php/admin/

上部の[連携]のリンクをクリックしてツールの下の「XMLをSimpleSAMLphpメタデータに変換」を押します。
![spsetting2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/255d9e76-75b6-4676-9737-a70973ceb879.png)

[XMLメタデータ]のテキストエリアに先ほど保存したIdPのメタデータをコピーペーストします。
続けて「パース」ボタンを押してください。
![spsetting3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/0d0c43ec-16f1-497d-aa31-d705367cb5c3.png)

PHPに変換されたメタデータが表示されるので、右隅のコピーボタンで保存してください。
![spsetting4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/af9a1ee0-d9d2-4602-9ffa-337a376bc258.png)

コピーしたPHPのメタデータをsimpleSAMLphpをインストールしたAlmalinux9のコンソールを開いて保存します。
先頭に「<?php」を忘れずに付加してください。
```
vi /opt/simplesamlphp-2.3.5/metadata/saml20-idp-remote.php
```
![spsetting5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/73383f40-2ed5-4b10-905c-ad08f3ff8245.png)

# いよいよ、動作確認

simpleSAMLphpの管理者画面にadmin/passwordでログインします。
https\://sp1.qiita.osstech.co.jp/simplesaml/module.php/admin/

上部の[Test]のリンクをクリックして「default-sp」のリンクを押します。
![test1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/44e7a916-f07c-403f-8510-96187a66ebc8.png)

アイデンティティープロバイダ欄にエンティティIDが表示されていることを確認して、
「選択」ボタンを押します。
もし、エンティティIDが表示されていない場合は「simpleSAMLphpにリモートアイデンティティープロバイダの登録」の章を見直してメタデータが正しくsimpleSAMLphpに登録されているか確認してください。
![test2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/c3f5d43a-6ee1-4fba-849a-a748ee82f4bd.png)

OpenAMのログイン画面にリダイレクトしたら用意したID/パスワードでログインします。
![test3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/039ea2c6-14dc-4311-bf37-351fa8f1a768.png)

以下の画面が表示されたらSAML連携に成功しています。
SPのエンティティで設定したSAML属性が渡っているか確認してください。
![test6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/9f4767c5-2cb3-472d-8969-37eb3ad5bb01.png)

## エラーが発生したら
エラーのパターンをいくつか紹介します。

以下のようなエラーメッセージが表示されたら、OpenAMとsimpleSAMLphpが稼働しているOSの現在時刻をチェックしてください。
SAMLでは連携時の時間範囲が厳密となっており設定範囲を超えるとこのようにエラーになります。
![error1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/9cc9e59e-63e6-4a4c-8b8e-f36a871172b0.png)

以下のようなエラーメッセージが表示されたら、SAMLレスポンスに含まれる署名の検証で失敗しています。
OpenAMのIdPメタデータの署名部分\<ds:X509Certificate\>･･･\</ds:X509Certificate\>がIdPとSP間で同じかどうか確認してください。
また、OpenAMのSPエンティティで設定した署名アルゴリズムが問題の際も同様なエラーが発生するので見直してみてください。
![error2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/4a9fbd4c-b036-40c3-aef4-a1cdb8659998.png)

## SAMLのリクエスト・レスポンスを見てみよう

次にSAMLリクエスト・レスポンスの内容を確認してみましょう。
ブラウザのアドオンでSAML-tracerを事前に有効にしておいてください。
既にsimpleSAMLphpにセッションがある状態ではSAMLリクエストが送信されないので、
一度ログアウトするかブラウザを閉じて開きなおしてください。

simpleSAMLphpの管理者画面にadmin/passwordでログインします。
[Test]のページに遷移して、SAML-tracerを開きます。
![test7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/c0142f97-adec-452a-ab59-be1ad57db345.png)

先ほどテストしたときと同様に「default-sp」のリンクを押して、OpenAMにログインし、
simpleSAMLphpの結果ページに遷移するところまで操作してください。
SAML-tracerを見ると以下のようにブラウザからのHTTPリクエストが表示されていると思います。
![test8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/c42c01cd-c394-45a5-8769-6330e6f9b812.png)

右側に「SAML」のマークが表示されているリクエストが２つあることに注目してください。
先頭のほうにある1番目のSAMLリクエストをクリックします。
このリクエストはSPからのSAMLリクエストをクライアントでリダイレクトしてIdPに送信しています。
下のペインの「HTTP」タブにリクエスト・レスポンスの内容が表示されます。

![test9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/c4ef9ad1-9e49-4195-8a88-10112f7e7f8f.png)

「Parameters」タブにリクエストパラメータとして、「SAMLRequest」と「RelayState」が表示されています。
![test10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/5a705838-6f03-47fe-aeb9-e53420e967eb.png)

「SAML」タブにはSAMLRequestの値がデコードされ、XMLで表示されます。
![test11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/4ee68090-b1a5-431c-a124-70f51a547f40.png)

それでは2番目のSAMLレスポンスのほうも確認してみましょう。
このリクエストはIdPからのSAMLレスポンスをクライアントからPOSTでSPに送信しています。
![test12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/010654b9-317b-47e7-8483-736b2d5a8e10.png)

「Parameters」タブにリクエストパラメータとして、「SAMLResponse」と「RelayState」が表示されています。
![test13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/81ff4c12-9ced-4277-b93d-0fe18ec0f6bb.png)

「SAML」タブにはSAMLResponseの値がデコードされ、XMLで表示されます。
![test14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/80bda3a5-38e5-4404-86d3-325c7599ac06.png)

このようにブラウザからSAMLリクエストとSAMLレスポンスの値を確認することが出来ます。
但し、SAMLリクエストとSAMLレスポンスを暗号化して送信している場合は内容を確認することができません。
そのようなときはIdPやSPにたいていはデバッグ機能が用意されているのでログから確認するようにしてください。

## デバックを有効にしてみよう
OpenAMとsimpleSAMLphpのデバックを有効にする手順を説明します。
デバックを有効にするとファイル出力が大幅に増えてディスクを圧迫するので、
テストが終わったら無効に戻すようにしてください。

OpenAMでは管理コンソール上で[デプロイメント]タブの[サーバー]リンクからサーバーを選択します。
[一般]の[デバック]タブを開き、[デバックレベル]を「メッセージ」に変更して、「変更の保存」を押します。
無効に戻すときは[デバックレベル]を「エラー」に変更して保存ください。
![test15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316107/aaf3d651-1aaf-42c5-9cb1-2c49fbcf9773.png)

デフォルトでは以下にデバックログが出力されます。
/opt/osstech/var/lib/tomcat/data/openam/openam/debug/Federation

以下のように送受信したSAMLリクエストやSAMLレスポンスも確認することが出来ます。
```
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_b871c21ff7037a3ee1b92b77484093e262004f77ef" Version="2.0" IssueInstant="2025-04-01T03:13:09Z" Destination="https://sso.qiita.osstech.co.jp/openam/SSORedirect/metaAlias/usr/idp" AssertionConsumerServiceURL="https://sp1.qiita.osstech.co.jp/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"><saml:Issuer>https://sp1.qiita.osstech.co.jp/simplesaml</saml:Issuer><samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" AllowCreate="true"/></samlp:AuthnRequest>
```
```
IDPSSOUtil.sendResponseToACS: Response is:  <samlp:Response ID="s22dc10fddda5162bf392d79e3477c8d4345c6401b" InResponseTo="_b871c21ff7037a3ee1b92b77484093e262004f77ef" Version="2.0" IssueInstant="2025-04-01T03:13:15Z" Destination="https://sp1.qiita.osstech.co.jp/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp"><saml:Issuer>https://sso.qiita.osstech.co.jp/openam</saml:Issuer><samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success">
</samlp:StatusCode>
</samlp:Status><saml:Assertion Version="2.0" ID="s2f69fedfde7bca7dcbf7a88dfce5592b3887bb6f7" IssueInstant="2025-04-01T03:13:15Z">
<saml:Issuer>https://sso.qiita.osstech.co.jp/openam</saml:Issuer><saml:Subject>
<saml:NameID NameQualifier="https://sso.qiita.osstech.co.jp/openam" SPNameQualifier="https://sp1.qiita.osstech.co.jp/simplesaml" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">aOU916csstGmxPCG8GbBJgH1ftqw</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2025-04-01T03:23:15Z" InResponseTo="_b871c21ff7037a3ee1b92b77484093e262004f77ef" Recipient="https://sp1.qiita.osstech.co.jp/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" ></saml:SubjectConfirmationData></saml:SubjectConfirmation>
</saml:Subject><saml:Conditions NotBefore="2025-04-01T03:03:15Z" NotOnOrAfter="2025-04-01T03:23:15Z">
<saml:AudienceRestriction>
<saml:Audience>https://sp1.qiita.osstech.co.jp/simplesaml</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2025-04-01T03:13:15Z" SessionIndex="s27b63ef71015cce9facfcc0b1a4836dce6f90fd01"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name="saml-uid"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">osstech1</saml:AttributeValue></saml:Attribute><saml:Attribute Name="saml-cn"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">osstech1-cn</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>
</samlp:Response>
```
simpleSAMLphpでは設定ファイルを編集してデバックを有効にします。
デフォルトではsyslogに出力されるのでファイルに切り替えます。

まずはじめにログディレクトリを作成します。
```
mkdir /var/log/simplesaml
chown apache:apache /var/log/simplesaml
```
次にconfig.phpを編集します。
```
vi /opt/simplesamlphp-2.3.5/config/config.php
```

[loggingdir]を/var/logから/var/log/simplesamlに変更します。
```
    'loggingdir' => '/var/log/simplesaml',
```

debug内容の[saml]をfalseからtrueに変更します。
```
    'debug' => [
        'saml' => true, 
        'backtraces' => true,
        'validatexml' => false,
    ],
```

[logging.level]をNOTICEからDEBUGに変更します。
[logging.handler]をsyslogからfileに変更します。
```
    'logging.level' => SimpleSAML\Logger::DEBUG,
    'logging.handler' => 'file',
```

[logging.logfile]の値はそのままです。
```
    'logging.logfile' => 'simplesamlphp.log',
```
config.phpの編集は完了です。
無効に戻すときは[logging.level]をDEBUGからNOTICEに変更して保存します。

ログファイルは以下に出力されます。
/var/log/simplesaml/simplesamlphp.log

以下のように送受信したSAMLリクエストやSAMLレスポンスも確認することが出来ます。
```
Apr 1 04:23:58 simplesamlphp DEBUG [6cddf00d1d] Sending message:
Apr 1 04:23:58 simplesamlphp DEBUG [6cddf00d1d] <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_14d886ccb94da9af5d5073db1848c627a1e75ae74f" Version="2.0" IssueInstant="2025-04-01T04:23:58Z" Destination="https://sso.qiita.osstech.co.jp/openam/SSORedirect/metaAlias/usr/idp" AssertionConsumerServiceURL="https://sp1.qiita.osstech.co.jp/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
Apr 1 04:23:58 simplesamlphp DEBUG [6cddf00d1d]   <saml:Issuer>https://sp1.qiita.osstech.co.jp/simplesaml</saml:Issuer>
Apr 1 04:23:58 simplesamlphp DEBUG [6cddf00d1d]   <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" AllowCreate="true"/>
Apr 1 04:23:58 simplesamlphp DEBUG [6cddf00d1d] </samlp:AuthnRequest>
```

```
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d] <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s2d5dc78d279cc5a109ed9d87bad78eeac26aa1698" InResponseTo="_14d886ccb94da9af5d5073db1848c627a1e75ae74f" Version="2.0" IssueInstant="2025-04-01T04:24:04Z" Destination="https://sp1.qiita.osstech.co.jp/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp">
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]   <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sso.qiita.osstech.co.jp/openam</saml:Issuer>
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]   <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]     <samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]   </samlp:Status>
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]   <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="s2840d3decdaf28dc0dcda98a3d6ed273828c434ed" IssueInstant="2025-04-01T04:24:04Z" Version="2.0">
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]     <saml:Issuer>https://sso.qiita.osstech.co.jp/openam</saml:Issuer>
Apr 1 04:24:04 simplesamlphp DEBUG [6cddf00d1d]     <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
```

# おわりに
今回はOpenAMをIdPとして利用して、simpleSAMLphpをSPとしてSAML連携の環境構築と実際にテストを実施してみました。
基本的にはIdPとSP間でこのようなメタデータを交換して、お互いの連携方法やエンドポイントや証明書を事前に知ることでSAMLプロトコルで連携することを実現しています。
実装しているソフトウェアによる設定部分は異なりますが、カスタムで作成するインタフェースと違いプロトコルで既定された連携方法を利用しているので、
SAMLに対応してるならつながるよね～という安心感があるのはこの連携方法のおおきな魅力でもあります。