CentOS7でのSimpleSAMLphp環境構築(後編)

# はじめに
https://qiita.com/come340/items/2019846f84950f5b46fc
で、続きは今度書くと言ったまま更新していませんでした…。
前記事でSimpleSAMLphp設定ページの表示までできたと思うので次はSP(サービス・プロバイダ)とIdP(アイデンティティ・プロバイダ)を構築します。それぞれ1個ずつサーバを立てておきましょう。(どちらかだけ作るときは1個でいいです)

下記のサイトを参考にさせて頂いております。
https://qiita.com/haya43/items/c74d2710cd9b57d2cbb4
# 環境
・CentOS Linux release 7.5.1804 (Core)
・Apache/2.4.6
・PHP 5.6.40 ※後述
・SimpleSAMLphp 1.17.2

# SP・IdP共通の作業
## 管理者でログインする
1．adminユーザパスワードを設定
config.phpを編集します

```
# vi /var/www/simplesaml/config/config.php
```

```config.php
'auth.adminpassword' => '（任意のパスワード）',
```

2． secretsalt設定
下記コマンドでランダム文字列を生成

```
# tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo
```

エラーが出たらこっちを試してみてください。

```
# LC_CTYPE=C tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo
```

生成されたランダム文字列をコピーして再びconfig.phpを編集

```php:config.php
'secretsalt' => '(生成したランダム文字列)',
```

3．管理者でログイン
SimpleSAMLの設定ページを見ると、右上に"管理者でログイン"と表示されていると思います。
<img width="724" alt="スクリーンショット 2019-06-20 17.31.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/9391f67f-a81a-ae4f-0610-7e0be564ff0a.png">

ここをクリックするとログイン画面に遷移し、ユーザ名とパスワードを要求されます。ユーザ名はadmin、パスワードは先程設定したものを入力しましょう。

<img width="731" alt="スクリーンショット 2019-06-20 17.40.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/498021be-0611-25ed-2872-0b0d38742ce3.png">

4．うまくログインできないとき
ここでうまくログインできない場合があります。いろいろ調べてみるとPHPのバージョンが良くないことが原因らしいので確認します。前記事でインストールしたPHPのバージョンは5.4.~(ちゃんと覚えていないですが…)だったので、要求されているバージョン(5.5.0以上)に合致していないことがよろしくなかったようです。ので、バージョンアップします。

https://blog.s-giken.net/369.html を見ながらバージョンアップしました。5.6.40です。これで再び管理者ログインを試みるとうまくいきました。
なにかうまくいかなかったときは設定タブの"Sanity check of your SimpleSAMLphp setup"をクリックしてみてバージョンが合っているかなど確認するといいかもしれないですね。

# IdPの設定
1．saml20-idpを有効化する
config.phpを編集

```
# vi /var/www/simplesaml/config/config.php
```

```php:config.php
 'enable.saml20-idp' => true, # falseからtrueに変更
```

これでIdPとしての機能が有効化されます。
SimpleSAMLの設定ページで設定タブを開いて、左上の欄を確認すると以下のようになっていると思います。
<img width="139" alt="スクリーンショット 2019-06-27 13.17.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/26a932a6-c089-e00e-1585-d3b2be2d29ae.png">

2．自己証明書作成

```
# cd /var/www/simplesaml
# openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -subj "/C=JP/ST=Tokyo/CN=idp1.local" -out cert/idp1.local.crt -keyout cert/idp1.local.pem
```

CN=idp1.localとしていますがこれは自分のホスト名を、idp1.local.crtとidp1.local.pemは自分でわかるように適当な名前をつけます。

saml20-idp-hosted.phpを編集しておきます。(crtとpemのファイル名をserver.crtとserver.pemとした場合はこの手順は不要です)

```
# vi /var/www/simplesaml/metadata/saml20-idp-hosted.php
```

```php:saml20-idp-hosted.php
    'privatekey' => '(設定した名称).pem',
    'certificate' => '(設定した名称).crt',
```


# SPの設定
1．自己証明書作成

```
# cd /var/www/simplesaml
# openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -subj "/C=JP/ST=Tokyo/CN=sp1.local" -out cert/sp1.local.crt -keyout cert/sp1.local.pem
```

だいたいIdPと同じ要領です。

2．default-spの設定
authsources.phpを編集

```
# vi /var/www/simplesaml/config/authsources.php
```

```php:authsources.php
    'default-sp' => [
        'saml:SP',

        'privatekey' => 'sp1.local.pem',  # opensslコマンドで設定したファイル名
        'certificate' => 'sp1.local.crt', # opensslコマンドで設定したファイル名

        // The entity ID of this SP.
        // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
        'entityID' => 'http://sp1.local/', # 自ホストのURL

        // The entity ID of the IdP this SP should contact.
        // Can be NULL/unset, in which case the user will be shown a list of available IdPs.
        'idp' => null,
```

ここでidpをnullにしていますが、連携するidpが一つである場合はidpのエンティティIDを入力します。エンティティIDは自分で構築したIdPを用いる場合、SimpleSAMLの設定ページから確認できます。IdPの設定ページで連携タブ>SAML 2.0 IdPメタデータの欄に記載されています。

<img width="415" alt="スクリーンショット 2019-06-27 13.08.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/e1fe66c0-a696-fe9b-98c7-f2a97eb40f30.png">

これはIdPの設定を終えてからしか表示されないので先にIdPの設定を行ってください。また、連携したいIdPが複数ある場合はnullにしておくと、実際にIdPログインを行う際にIdPを選択できるようになります。

# SP・IdPの連携
## IdPのメタデータをSPに登録
### IdPメタデータXMLファイルを取ってくる
IdP側の設定ページで連携タブ>SAML2.0IdPメタデータ欄>メタデータを表示
で以下の画面に。
<img width="737" alt="スクリーンショット 2019-06-27 13.28.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/6469a90e-76da-5328-b525-6527bbd16654.png">

メタデータをコピーします。(右上のボタンを押すとクリップボードにコピーされます)

### XMLフォーマットをパース
次にSPの設定ページに行き、連携タブ>ツール欄>メタデータをXMLに変換(これはIdPの設定ページでもできるような気がするが検証していないです…たぶんできます)
XMLメタデータパーサの入力欄に先程コピーしたIｄPのメタデータを貼り付け、パース。XMLフォーマットがSimpleSAMLphpのメタデータフォーマットに変換されるので再びコピーします。

### メタデータをSPに登録

SPのサーバで

```
# vi /var/www/simplesaml/metadata/saml20-idp-remote.php
```

先程コピーした変換されたフォーマットをファイルの最後にペースト

```php:saml20-idp-remote.php
<?php
/**
 * SAML 2.0 remote IdP metadata for SimpleSAMLphp.
 *
 * Remember to remove the IdPs you don't use from this file.
 *
 * See: https://simplesamlphp.org/docs/stable/simplesamlphp-reference-idp-remote
 */
$metadata['http://idp1.local/simplesaml/saml2/idp/metadata.php'] = array (
  'entityid' => 'http://idp1.local/simplesaml/saml2/idp/metadata.php',
  'contacts' =>
  array (
  ),
  'metadata-set' => 'saml20-idp-remote',
  'SingleSignOnService' =>
  array (
    0 =>
    array (
      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
      'Location' => 'http://idp1.local/simplesaml/saml2/idp/SSOService.php',
    ),
  ),

(以下略)
```

## SPのメタデータをIdPに登録
だいたいの流れはIdPの時と同じです。
① 連携タブからXMLフォーマットのSPメタデータを取ってくる
※IdPではsaml20-idpメタデータ欄からメタデータを取ってきましたが、SPではsaml2.0SPメタデータ欄から取ってきます。
② XMLフォーマットをメタデータパーサで変換
③IdPに登録(以下記載)

### メタデータをIdPに登録

IdPのサーバで

```
# vi /var/www/simplesaml/metadata/saml20-sp-remote.php
```

このファイルは元々いろいろ書いてあるので全部消して先程コピーしたメタデータフォーマットを貼り付けます。不安な人はバックアップファイルを作っておくとよいでしょう。
また、全部消して貼り付けただけだとphpタグがないので<?phpを一行目に書いておくことを忘れずに。

```php:saml20-sp-remote.php
<?php
$metadata['http://sp1.local/'] = array (
  'entityid' => 'http://sp1.local/',
  'contacts' =>
  array (
  ),
  'metadata-set' => 'saml20-sp-remote',
  'AssertionConsumerService' =>
  array (
    0 =>
    array (
      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
      'Location' => 'http://sp1.local/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
      'index' => 0,
    ),

(以下略)
```

### 認証モジュールの設定
IdP側の設定では認証モジュールの設定もします。詳しくは公式文書を読みましょう。
https://simplesamlphp.org/docs/stable/simplesamlphp-idp
3番の項目を読むといいです。

今回はexampleauthモジュールを使ってみます。

```
# cd /var/www/simplesaml
# touch modules/exampleauth/enable
# vi /var/www/simplesaml/config/authsources.php
```
example-userpassの項目の前後からコメントアウト(/*, */)を消去します。

```php:authsources.php
'example-userpass' => [
        'exampleauth:UserPass',

        // Give the user an option to save their username for future login attempts
        // And when enabled, what should the default be, to save the username or not
        //'remember.username.enabled' => false,
        //'remember.username.checked' => false,

        'student:studentpass' => [
            'uid' => ['test'],
            'eduPersonAffiliation' => ['member', 'student'],
        ],
        'employee:employeepass' => [
            'uid' => ['employee'],
            'eduPersonAffiliation' => ['member', 'employee'],
        ],
    ],
```

IdPにユーザ設定ができたので、ユーザ名='student'、パスワード='studentpass'でstudentユーザとしてログインできるようになるといった具合です。

# 接続テスト
SP側の設定ページで認証タブ>設定されている認証元をテスト>default-sp>(IdPを複数登録している場合は選択)>IdP側のログイン画面でユーザ名とパスワードを入力してログイン(student/studentpassなど)

<img width="694" alt="スクリーンショット 2019-06-27 13.58.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404657/86db64d3-ac30-55d6-4d1d-2ffd47c78d04.png">

IdPでログインできました。やったね！
ちなみに同じ設定をしたSPをもう一つ作っておくと、このログイン作業を一回終えた後にもう一つのSPでもログインしようとしたらすでにログインが終わっている状態になっています。(これがシングルサインオン)