SAML認証を勉強せずに理解したい私から勉強せずに理解したい私へ

コードがないし自分向けなのでポエム枠です

# 結論

簡単に説明してくれる所はサイボウズ様が詳しい。(難しい所を読み飛ばせば)

* [SAML認証を使用したシングルサインオンを設定する | cybozu.com共通管理 ヘルプ]
* [SAML認証ができるまで - Cybozu Inside Out | サイボウズエンジニアのブログ]

動かしてみないと実感わかないかも。

難しいと思った所は実はライブラリを使うならほとんど隠して担ってくれている。

# はじめに

[突然SAML認証と仲良くしなきゃいけなくなった人へ - Qiita]
を読んで(読まずに)挫折して
[SimpleSAMLphp で開発用の SAML ID Provider を立てる - suer のブログ]
に手を出している途中の人が書いています。(SP側は[onelogin/php-saml]のdemo1です)
足首浸からないぐらいの浅学の身なので、**内容には十分ご注意ください。**

SAML認証=SSO(シングル・サインオン)程度の認識で進めています。

# 読まずに生ずる疑問

* 認証をどう複数サイトで使いまわすのか(SSO)
 * 形式は？Cookie？それぞれのサイト独自のユーザー情報形式と互換できるの？
* 自サイトでログインに成功したことが、どうして他のサイトでもログインできるといえるの？
* 自サイトは今までログイン必須だったけど、SSOならログインページ開いた途端にログインできるようにしないといけないの？



# はじめに その2

多分、入れる場所が思いつかないので冒頭に書いておきます。

>![saml_settings_ja_01.png](https://qiita-image-store.s3.amazonaws.com/0/62354/82ad579b-cef4-5b69-de0e-5496b27ccaf6.png)


こういったSAML認証のやり取りを見て、未だチンプンカンプンの身でも、こう思います。
「ユーザーが中継しちゃったら改ざん余裕じゃね？」

SAML認証の通信のセキュリティは(おそらく)**公開鍵暗号方式**で担保されています。
公開鍵暗号方式…はなんとなく知っているものとします。
知っていれば、「じゃあ大丈夫なんだろう」となるんじゃないのか。

# 登場人物

>
・SAML Authority (SAML権限)
    Assertionを出すシステム実体で、下記に記載するAttribute Authority（属性権限）、Authentication Authority（証明権限）、PDP(Policy decision point)があります。
・Attribute Authority
    Attribute Assertion (属性アサーション)を作るシステム実体
・ Authentication Authority
    Authentication Authority(証明権限)を作るシステム実体
・Principal
    その同一性が確認できるシステム実体
・Subject
    セキュリティドメインにおける認証/承認の対象となる実体。SAML assertionは、Subjectに関する宣言を行ないます。Subjectの代表的な例は、メールアドレスを持っているユーザです。
・Assertion (アサーション)
    Subjectを認証した行為、Subjectに関する属性情報、特定のResource(資源)にSubjectがアクセスすることの認可に関してSAML権限が作るデータ
・Resource
    (a) 情報システムに含まれているデータ(例えばファイルやメモリにある情報)
    (b) システムによって提供されるサービス
    (c) システム設備の各アイテム(例えば、ハードウェア、ファームウェア、ソフトウェアあるいはドキュメンテーションのようなシステム・コンポーネント)
    (d) システム・オペレーションおよび設備を収容する施設 [RFC2828]
    SAMLでは(a), (b)の意味で使用します。またSAMLがResource を参照するときは、URIを用います。
・PDP (Policy decision point)
    ポリシーに基づいて、要求者の要求が対象となる資源に関して権限が与えられるかどうかを、判断する機能を持つところ
・PEP (Policy enforcement point)
    ポリシーに基づいて、アクセス制御を実施する機能を持つところ。要求者から要求を受け付けて、アクセス制御ポリシーに適合した応答を要求者に返します。

全然分からないので無視します。
難しいことは動かせるようになってから考えることにします。
ので、以下のようにします。
**(この記事が終わっても、上記の意味の理解の助けにはなりません。)**

![saml.png](https://qiita-image-store.s3.amazonaws.com/0/62354/b0321f86-7509-fddf-868c-f43256393144.png)

ユーザーと蔵と元締めのアイデップです。
また、しばらく前準備が必要なのでユーザーにはおやすみして頂きます。

# ユーザー準備

元締めはどでかい存在で、音楽もつくりますが、他にも色々します。
モトジメくんはユーザー名簿を沢山持っています。
IDとパスワードの組み合わせと、そのユーザーが持つ属性一覧です。
このユーザーは個々の蔵サービスのユーザーとは直接紐付いてはいません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/62354/dbbd8434-24e4-37d4-56f3-7ac06ef145cb.png)


ユーザーとそのユーザーの属性の組み合わせと言われれば、ただのユーザーマスタと言えますし、ご存知ならLDAPサーバーも同じものだと思いつくと思います。
げんに、SAML認証でもユーザーデータはLDAPが管理するのも変な話ではないようです。

# 連携

あるところに、蔵という男が、天下第一のサービスになろうと志を立てた。
己の認証元と頼むべき人物を物色するに、当今ユーザーデータにおいてはIdPに及ぶものがあろうとは思われぬ。蔵は遥々IdPをたずねてその門に入った。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62354/d3c6f4c7-9cc7-2e43-2690-050375a86b6b.png" width="64" height="64"></img>「舎弟にしてください！」
すでに舎である。

さて、連携の儀式は、漢字の当て字をつけ、紋付きを着、酒を酌み交わすという宇宙一般的な方法です。**ハッピーになれそうですね。**

<img src="https://qiita-image-store.s3.amazonaws.com/0/62354/d3c6f4c7-9cc7-2e43-2690-050375a86b6b.png" width="64" height="64"></img>「苦雷庵斗」

儀式はそれでいいとして、実務はもうちょっと複雑で、連絡先交換を行います。
連携先を知らなければ連携のしようがないですからね。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62354/b08a0fc7-6273-261d-b61e-7dbef342a210.jpeg" width="64" height="64"></img>「君のことをてるみくらぶ」


![image.png](https://qiita-image-store.s3.amazonaws.com/0/62354/0fd30eae-8898-9f9d-545e-c20301082f74.png)

これで、蔵側から元締め側、元締め側から蔵側へのルートが決まりました。公開鍵を渡したので道中のやり取りは暗号化されます。

(このやり取りはIdP側は入力フォームで簡易化されたり、直接**メタデータ**という実際に使う形式のxmlをやり取りして人が設定します)

# SSOの流れはこんな感じ

では実際にSSOしたいユーザーの流れを見ます。

## クライアントへアクセス

![image.png](https://qiita-image-store.s3.amazonaws.com/0/62354/9d9f1be8-dfa0-c36c-65b4-d7c1cfd5af87.png)

SSOしたがっているユーザーが来ました。
ここではユーザーがすでにSSO認証済みかどうかは問いません。
蔵側は、ユーザーに何をするでもなく、超事務的に元締めへリダイレクトしてしまいます。

(どのページにアクセスしてもSSOするのか、SSO開始専用のURLを用意するのかは作り方によると思います。既存処理が、非ログインならログインページへ飛ばすという実装なら、SSO専用ログインURLを用意するのが簡易なのかも)

(実際にはライブラリを使ってログイン(リダイレクト)するので、何もしないというのはライブラリが全部よしなにしてくれているの意です)

![saml2.png](https://qiita-image-store.s3.amazonaws.com/0/62354/d83f3be7-3a98-ee9a-b979-c7bc757672d0.png)
(リダイレクトは、SPから一度ユーザーに戻って、ユーザーからIdPへの通信と表現されますが、省略しています)

## ユーザーのログイン(=サインオン)

ユーザーと元締めの関係はごく普通のユーザーとログインが必要なサイトのそれです。
つまり、サイトに訪れた時、セッションなどですでにログインされていると判定されればログイン後の処理へ。
そうでなければログインが必要になります。



(ここで、SP側にログインフォームを設けて、IdPとのログイン操作を代行して、見かけ上自サービスにログインするだけでSSOできるように見せかけるのか(IdPの存在を隠すのか)、全てのサービスで必ずIdPでログインするように誘導するのかは不明です。動かしたデモではIdPでのログインを促しており、ここではそう書いています)

## ログイン後の処理

ログインに成功した、あるいはすでにログイン済みであった場合、元締めは何をするか？
Hello Worldを見せる？No。
元締めは偉いので、顔の確認はしますが、後は下々の部下任せです。
**手元にあるIdPにログインしたユーザー属性情報を付加したうえ、**蔵の連携先にリダイレクトします。ユーザーはたらい回しのようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/62354/827fd9cc-463d-8d2e-af83-efc5438a9aca.png)

ここは、「"ここ"からリダイレクトして来たら"あそこ"にリダイレクトしかえそう」と連携時に約束しました。(先の連携図にはありませんが、"ここ"はentryIdと言う値を使うので、正しくはリダイレクト元URLではありません。蔵からのリダイレクト時に「このentryIdの設定でお願いします」と値が来るはずです)
(ここもユーザー経由のリダイレクトを省略)

## 蔵のログイン処理

最後に個々の蔵は、そのままログイン後画面を見せたり、元締めから降りてきた情報を使って、蔵用のアカウントを新規で作ってやったりしてサービスを利用可能な状態でログインさせてやります。
ログインフォームの入力値≒IdPからのユーザー属性情報
と考えれば、ユーザーさえ用意すれば、ログインの入り口が違うだけで一般ユーザーとして振る舞えることが可能…なはず。

## その後、別の蔵にアクセスしたら？

やはり元締めにリダイレクトされ、**すでに元締めとはログイン済みなので、ログインフォームへの入力はありません。**
なので、すぐさままた蔵側にリダイレクトされ、ユーザーにIdPの姿が見えぬまま、蔵側のログイン処理が完了します。

どうでしょうか。複数サイトのSSO、合点していただけましたでしょうか。

そんな感じの流れが、

>![fig4.png](https://qiita-image-store.s3.amazonaws.com/0/62354/21f8e568-fc3d-7b8e-7481-0e1146c098b7.png)

みたいに表現されているのではないかと愚考しております。

# つまり

3つのロールが絡まり合うように見えて、実は

* ユーザー対SP(一般ユーザーとほぼおなじ)
* ユーザー対IdP(一般的なログインとほぼおなじ)
* SP対IdP(一般的なパラメーター駆動のAPI連携とほぼおなじ)

に分割して考えることが可能だと思われます。
とくに注力すべきはSP対IdPで、ユーザー側はSSOだからといって特殊な値をSPに渡すことはない…と考えています。

そして自SPでのローカルなログイン/ユーザー作成は他SPにはなーんの関係もなくて、重要なのはIdPに対する認証の可否であることが伺えると思います。

あとは連携設定や画面やログイン処理をどのようにつくるかは、設計しだいかなーというしだいです。


# 参考

* [SimpleSAMLphp で開発用の SAML ID Provider を立てる - suer のブログ]
* [SAML認証を使用したシングルサインオンを設定する | cybozu.com共通管理 ヘルプ]
* [Apache + OpenSSL CSR生成手順 (新規)ジオトラスト]
* [SAMLとは ｜クラウド型シングルサインオン・アクセスコントロール（IDaaS） OneLogin - サイバネット]
* [OSSTech OpenSSO社内勉強会資料 - osstech-opensso-study-02-saml.pdf]
* [クラウド時代のシングルサインオン hbstudy-20110416-sso.pdf]

***

シングルサインアウトはそのままSSOの逆で、自サービスからログアウトするだけでなく、ユーザーをIdPからログアウトさせるようにIdPのログアウト画面へユーザーをリダイレクトさせてやるようです。

***

[onelogin/php-saml]
を使う場合、こちらが持つべき設定は一見IdP側の設定のみで良さそうなのですが、IdP側に渡すSP設定も持っていないとインスタンスが生成できないので、ちょっと不便な気がします。
ただ、設定しておくとメタデータのXMLも自動で出力してくれるので、無駄ではないです。

***

[突然SAML認証と仲良くしなきゃいけなくなった人へ - Qiita]:http://qiita.com/tani1987/items/f8069cfc75e21f7f6f50


[SimpleSAMLphp で開発用の SAML ID Provider を立てる - suer のブログ]:http://suer.hatenablog.com/entry/2015/11/20/141941


[SAML認証を使用したシングルサインオンを設定する | cybozu.com共通管理 ヘルプ]:https://help.cybozu.com/ja/general/admin/saml_settings.html


[Apache + OpenSSL CSR生成手順 (新規)ジオトラスト]:https://www.geotrust.co.jp/support/ssl/csr/apache_openssl_new.html

[SAMLとは ｜クラウド型シングルサインオン・アクセスコントロール（IDaaS） OneLogin - サイバネット]:http://www.cybernet.co.jp/onelogin/function/saml.html

[OSSTech OpenSSO社内勉強会資料 - osstech-opensso-study-02-saml.pdf]:https://www.osstech.co.jp/_media/techinfo/opensso/osstech-opensso-study-02-saml.pdf

[クラウド時代のシングルサインオン hbstudy-20110416-sso.pdf]:https://www.osstech.co.jp/_media/techinfo/seminar/hbstudy-20110416-sso.pdf

[onelogin/php-saml]:https://github.com/onelogin/php-saml

[SAML認証を使用したシングルサインオンを設定する | cybozu.com共通管理 ヘルプ]:https://jp.cybozu.help/general/ja/admin/list_externalservices/list_saml/saml_settings.html

[SAML認証ができるまで - Cybozu Inside Out | サイボウズエンジニアのブログ]:http://blog.cybozu.io/entry/4224