今回は、SAML認証の紹介をします。
SAML認証のフローがわかっても、実際に技術的にどういう構造になっていて、具体的にどのような仕組みになっているのかわからない...という方も多いと思います。
こちらの記事では、SAMLが実際にどのような技術仕様でやりとりがされるのかを解説します。
SAMLの認証フローに関しては、すでに理解している前提での解説になります。
「そもそもSAMLって何?」「どういう流れで認証されるの?」がまだ解消されていない方は、そちらをまず調べてみてください。
SAMLは認証プロトコルの中でもカスタマイズ性が高いことが長所でもありますので、技術仕様を理解してより高品質なプロダクトを作りましょう。
SAMLの超ざっくり概要
SAMLのフローについては知っている前提...ですが、ここで超簡単におさらいしておきましょう。
SAMLは認証プロトコルです。
SAMLの実態はXMLファイルで、主にHTTP通信に乗っかってサーバー間をやりとりします。
SAMLがよく利用されるのは、SSO(シングルサインオン)の場面です。
認証しトークンを発行するのをIdPと呼び、
トークンの要求およびトークンを持っているか確認をするのをSPと呼びます。
SAMLの代表的な認証フローは、下図の通りです。
SAMLの構成要素
SAMLの構成要素は、以下の通りです。
- Profile
- Binding
- Protocol
- Assertion
実態としては、下記のような階層構造になっています。
- Profile
- Binding
- Protocol
- Assertion
- Protocol
- Binding
ProtocolとAssertionは、まとめてCoreとも呼ばれます。
説明の都合上、逆順で内側から順番に解説します。
Assertion
Assertionは認証情報の定義となります。
Assertionを持っているかどうかによって、SPはブラウザがIdPによって認証されているのかされていないかを判別しています。
Assertionの中身はものによって様々です。
例えば、ユーザーID, グループID, 発行者, デジタル署名, 状態...などなどがあります。
一言にSAMLプロトコルといっても、Assertionが持っている要素が異なると、認証がうまくいかなかったり、思ったように情報が取り出せないなんてことになるかもしれないので注意してください。
AssertionはXMLで定義されています。
後のセクションで例も紹介していますので、そちらをご参照ください。
Protocol
ProtocolはAssertionを要求なのか応答なのかの定義になります。
言葉の通りですが、
SAML要求は、SAMLトークンを持っているかどうかを確認する要求で
SAML応答は、SAMLトークンを送ることを指します。
Assertionの要素は、SAML要求とSAML応答で変わります。
要求か応答かによってAssertionが変わるので、Protocolによって要求か応答かのどちらかを定義しているのです。
ProtocolもXMLで定義されています。
後のセクションで例も紹介していますので、そちらをご参照ください。
Binding
Bindingは、Coreを何の通信プロトコルで通信するかを定義になります。
(BindingはCoreのようにXMLで定義されていません。)
SPにCoreを送る、IdPにCoreをもらう...など、認証には通信が必ず介在します。
その際に、何の通信プロトコルにCoreを組み込むかというのをBindingで定義しているというわけです。
Bindingには以下の種類があります。
- HTTP Redirect Binding
- HTTP POST Binding
- HTTP Artifact Binding
- SAML SOAP Binding
- Reverse SOAP Binding
- SAML URI Binding
太字にした3つのプロトコルがよく使われます。
HTTP Redirect Binding
HTTPのGETリクエストのURLパラメータの文字列に直接記載する方法です。(直接といっても、文字通りそのままコピペではなく、base64のアルゴリズムによってエンコードをしてから貼っつけます)
手軽に使えるメリットがありますが、ブラウザによってはURLの長さに制限があるため長文は通信できないというデメリットもあります。
これらを踏まえて、HTTP Redirect Bindingは比較的情報が少ないSAML要求に使われるBindingです。
HTTP POST Binding
HTMLフォームに記載してHTTP POSTメソッドで送信する方法です。
(こちらもエンコードします)
HTTP Redirect Bindingに比べて多くの情報を送ることが可能になります。
これらを踏まえて、HTTP POST Bingingは比較的情報が多いSAML応答に使われるBindingです。
Profile
Profileは、BindingやCoreをどのようなシナリオで使用するのかの定義になります。
(ProfileはCoreのようにXMLで定義されていません。)
SAMLといえばSSOという印象があるのですが、実はSAMLはSSO以外のシナリオも想定されて作られたものでもあります。
以下のようなシナリオがあるみたいです。(僕もSSO以外の用途は知りませんでした...)
- WebブラウザSSO
- ECP(Enhanced Client or Proxy)
- IdPディスカバリ
- SLO(Single Logout)
- NameID管理
こちらの記事を参考にしました。
ここまでのまとめ
というわけで一旦全体を整理すると、以下のようになります。
- Profile・・・SAMLをどんなシナリオで使うのか
- Binding・・・Coreを何の通信プロトコルに乗せるのか
- Protocol・・・要求なのか応答なのか
- Assertion・・・認証情報の実態
- Protocol・・・要求なのか応答なのか
- Binding・・・Coreを何の通信プロトコルに乗せるのか
Core(ProtocolとAssertion)はXMLで定義されており、ProfileとBindingはXMLで定義されていません。
ProfileとBindingはあくまで仕様の話になります。
Coreの中身を見てみる
というわけで、最後にCoreの中身を見てみましょう。
今回は、AzureADをIdPとします。
ProfileはWebブラウザSSOで、Bindingは要求がHTTP Redirect Bindingで応答がHTTP POST Bindingとします。
認証フローは下図をイメージしてください。
AzureAD AuthnRequest
AzureAD AuthnRequestは、SAML要求です。
サンプルコードは以下です。(公式ドキュメントより引用)
<samlp:AuthnRequest
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
ID="id6c1c178c166d486687be4aaf5e482730"
Version="2.0" IssueInstant="2013-03-18T03:28:54.1839884Z"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://www.contoso.com</Issuer>
</samlp:AuthnRequest>
samlp:AuthnRequestでタグ指定されており、SAML要求であることがわかります。
パラメーターには、ID, Version, IssueInstantがありますね。
これらは必須項目とされているみたいです。
IDによってSAML要求を一意としているので、SAML応答にはおそらくこのIDをパラメータに与えて返すことが予想できますね。
AzureAD Response
AzureAD Responseは、SAML応答です。
サンプルコードは以下です。(公式ドキュメントより引用)
<samlp:Response ID="_a4958bfd-e107-4e67-b06d-0d85ade2e76a" Version="2.0" IssueInstant="2013-03-18T07:38:15.144Z" Destination="https://contoso.com/identity/inboundsso.aspx" InResponseTo="id758d0ef385634593a77bdf7e632984b6" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> https://login.microsoftonline.com/82869000-6ad1-48f0-8171-272ed18796e9/</Issuer>
<ds:Signature xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
...
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<Assertion ID="_bf9c623d-cc20-407a-9a59-c2d0aee84d12" IssueInstant="2013-03-18T07:38:15.144Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>https://login.microsoftonline.com/82869000-6ad1-48f0-8171-272ed18796e9/</Issuer>
<ds:Signature xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
...
</ds:Signature>
<Subject>
<NameID>Uz2Pqz1X7pxe4XLWxV9KJQ+n59d573SepSAkuYKSde8=</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="id758d0ef385634593a77bdf7e632984b6" NotOnOrAfter="2013-03-18T07:43:15.144Z" Recipient="https://contoso.com/identity/inboundsso.aspx" />
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2013-03-18T07:38:15.128Z" NotOnOrAfter="2013-03-18T08:48:15.128Z">
<AudienceRestriction>
<Audience>https://www.contoso.com</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>testuser@contoso.com</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
<AttributeValue>3F2504E0-4F89-11D3-9A0C-0305E82C3301</AttributeValue>
</Attribute>
...
</AttributeStatement>
<AuthnStatement AuthnInstant="2013-03-18T07:33:56.000Z" SessionIndex="_bf9c623d-cc20-407a-9a59-c2d0aee84d12">
<AuthnContext>
<AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
</samlp:Response>
Responseの方がRedirectよりも圧倒的に長文ですね。
samlp:Responseでタグ指定されているので、SAML応答であることがわかりますね。
パラメーターには、ID, Issuer, Signature, Status, Assertion ID, NameID ...などなどたくさん定義されていますね。
IDによって、どのSAML要求に対する応答なのかがわかるようになっていますし、
発行者や当人が何者であるか、認証に成功したのか失敗したのかなどの情報が記載されています。
まとめ
いかがでしたでしょうか。
SAMLは4つの要素から構成されています。
Profileは、SAMLをどんなシナリオで使うのか
Bindingは、Coreを何の通信プロトコルに乗せるのか
Protocolは、要求なのか応答なのか
Assertionは、認証情報の実態 がそれぞれ定義されています。
SAMLの認証フローに関することはネット検索で簡単に出てきて理解することができます。
一方、技術的な仕様の話になると、途端に難しくなり過ぎてしまいます。
この記事は、その間の部分で、フローを理解した上で技術使用を理解するための足掛かりとなる記事を目指して書きました。
ご参考になったならば幸いです。
ここまで読んでいただきありがとうございました。