「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
汎用認証サイトにSAML2.0を実装するため作成中。
SAMLの仕様は膨大だが、使われていないものも多い。
以下の範囲に絞れば、実装は割とスリムになる。
SAMLは、Web Browser SSO Profile以外で使われていない。
IdM実験室によると...。
昔はデータサイズの問題で、Artifact Bindingを使っていたが
最近は通信速度や端末性能の向上により、使われることは減ってきているらしい。
SPとIdPの間で直接通信をさせなければならないので、
クラウドサービスと社内IdPを連携させる場合など面倒なため。
ただ、今でも稀にArtifact Bindingしか使えないSPが
存在するので、仕方なく(IdP側に)実装することがある。
なお、AD FSではArtifact Bindingをサポートしている。
Azure ADはPOST BindingのみでArtifact Bindingは使えない。
※ 外側だけ検証すればイイ気がする。
XmlDocuement? を利用する際に PreserveWhitespace? を単に true にする。
下記のsamltool.ioからアサーションを取得し、SAMLTool.comで確認するなど。
Technical Overviewから取り出したサンプル・シーケンス
https://idp.example.org/SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_1" Version="2.0" IssueInstant="2004-12-05T09:21:59Z" AssertionConsumerServiceIndex="1"> <saml:Issuer> https://sp.example.com/SAML2 </saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> </samlp:AuthnRequest>
<form method="post" action="https://sp.example.com/SAML2/SSO/POST" ...> <input type="hidden" name="SAMLResponse" value="response" /> <input type="hidden" name="RelayState" value="token" /> ... <input type="submit" value="Submit" /> </form>
POST /SAML2/SSO/POST HTTP/1.1 Host: sp.example.com Content-Type: application/x-www-form-urlencoded Content-Length: nnnn SAMLResponse=response&RelayState=token
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_2" InResponseTo="identifier_1" Version="2.0" IssueInstant="2004-12-05T09:22:05Z" Destination="https://sp.example.com/SAML2/SSO/POST"> <saml:Issuer> https://idp.example.org/SAML2 </saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_3" Version="2.0" IssueInstant="2004-12-05T09:22:05Z"> <saml:Issuer> https://idp.example.org/SAML2 </saml:Issuer> <!-- a POSTed assertion MUST be signed --> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> ... </ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"> 3f7b3dcf-1674-4ecd-92c8-1544f346baf8 </saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="identifier_1" NotOnOrAfter="2004-12-05T09:27:05Z" Recipient="https://sp.example.com/SAML2/SSO/POST"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2004-12-05T09:17:05Z" NotOnOrAfter="2004-12-05T09:27:05Z"> <saml:AudienceRestriction> <saml:Audience> https://sp.example.com/SAML2 </saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2004-12-05T09:22:00Z" SessionIndex="identifier_3"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response>
医療分野共通認証基盤整備コンソーシアムのドキュメントから取り出したサンプル・シーケンス
HTTP/1.1 302 Object Moved Date: 21 Jan 2004 07:00:49 GMT Location:https://auth.pki.med.or.jp/sso/SSORedirect/metaAlias/idp?SAMLRequest=PHNhbW xwOkxvZ291dFJlcXVlc3QgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOj IuMDpwcm90b2NvbCIgG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3Nlc nRpb24iDQogICAgSUQ9ImQyYjdjMzg4Y2VjMzZmYTdjMzljMjhmZDI5ODY0NGE4IiBJc3N 1ZUluc3RhbnQ9IjIwMDQtMDEtMjFUMTk6MDA6NDlaIiBWZXJzaW9uPSIyLjAiPg0KICA gIDxJc3N1ZXI+aHR0cHM6Ly9JZGVudGl0eVByb3ZpZGVyLmNvbS9TQU1MPC9Jc3N1ZXI +DQogICAgPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDp uYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiPjAwNWEwNmUwLWFkODItMTEwZC1hNTU 2LTAwNDAwNWIxM2EyYjwvTmFtZUlEPg0KICAgIDxzYW1scDpTZXNzaW9uSW5kZXg+ MTwvc2FtbHA6U2Vzc2lvbkluZGV4Pg0KPC9zYW1scDpMb2dvdXRSZXF1ZXN0Pg==&Rela yState=0043bfc1bc45110dae17004005b13a2b Content-Type: text/html; charset=iso-8859-1
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN“ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <body onload="document.forms[0].submit()"> <noscript> <p> <strong>Note:</strong> Since your browser does not support JavaScript、you must press the Continue button once to proceed. </p> </noscript> <form action=https://ServiceProvider.com/SAML/SLO/Browser method="post"> <div> <input type="hidden" name="RelayState“ value="0043bfc1bc45110dae17004005b13a2b"/> <input type="hidden" name="SAMLRequest“ value="PHNhbWxwOkxvZ291dFJlcXVlc3QgeG1sbnM6c2FtbHA9InVybjpvYX NpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgG1sbnM9InVybjpvYXN pczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iDQogICAgSUQ9ImQyYjdj Mzg4Y2VjMzZmYTdjMzljMjhmZDI5ODY0NGE4IiBJc3N1ZUluc3RhbnQ9IjIwM DQtMDEtMjFUMTk6MDA6NDlaIiBWZXJzaW9uPSIyLjAiPg0KICAgIDxJc3N1 ZXI+aHR0cHM6Ly9JZGVudGl0eVByb3ZpZGVyLmNvbS9TQU1MPC9Jc3N1ZXI +DQogICAgPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1 MOjIuMDpuYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiPjAwNWEwNmUwLWF kODItMTEwZC1hNTU2LTAwNDAwNWIxM2EyYjwvTmFtZUlEPg0KICAgIDxz YW1scDpTZXNzaW9uSW5kZXg+MTwvc2FtbHA6U2Vzc2lvbkluZGV4Pg0KPC9 zYW1scDpMb2dvdXRSZXF1ZXN0Pg=="/> </div> <noscript> <div> <input type="submit" value="Continue"/> </div> </noscript> </form> </body> </html>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s2cee63177ff33bcacd5263caa4af9da101837de24" Version="2.0" IssueInstant="2011-06-28T05:08:41Z" Destination="https://auth.pki.med.or.jp/sso/SSORedirect/metaAlias/idp" ForceAuthn="false" IsPassive="false" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" AssertionConsumerServiceURL="https://ServiceProvider.com/SAML/Consumer/metaAlias/sp"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> sso-sp </saml:Issuer> <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" SPNameQualifier="openam-sp" AllowCreate="true"> </samlp:NameIDPolicy> <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"> <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> urn:oasis:names:tc:SAML:2.0:ac:classes:X509 </saml:AuthnContextClassRef> </samlp:RequestedAuthnContext> </samlp:AuthnRequest>
HTTP/1.1 302 Object Moved Date: 21 Jan 2004 07:00:49 GMT Location:https://ServiceProvider.com/SAML/SLO/Browser?SAMLart=AAQAADWNEw5VT47w cO4zX%2FiEzMmFQvGknDfws2ZtqSGdkNSbsW1cmVR0bzU%3D&RelayState=0043bfc1bc45 110dae17004005b13a2b Content-Type: text/html; charset=iso-8859-1
POST /SAML/Artifact/Resolve HTTP/1.1 HOST: IdentityProvider.com Content-Type: text/xml Content-Length: nnn SOAPAction: http://www.oasis-open.org/committees/security <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <samlp:ArtifactResolve xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_6c3a4f8b9c2d" Version="2.0" IssueInstant="2004-01-21T19:00:49Z"> <Issuer>https://ServiceProvider.com/SAML/</Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...Signature...</ds:Signature> <Artifact>...artifact...</Artifact> </samlp:ArtifactResolve> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
HTTP/1.1 200 OK Date: 21 Jan 2004 07:00:49 GMT Content-Type: application/soap+xml Content-Length: nnnn <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <samlp:ArtifactResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="identifier_3" InResponseTo="identifier_2" Version="2.0" IssueInstant="2004-12-05T09:22:05Z"> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_4" InResponseTo="identifier_1" Version="2.0" IssueInstant="2004-12-05T09:22:05Z" Destination="https://ServiceProvider.com/SAML/SSO/Artifact"> <saml:Issuer> medical-doctor-sso-idp </saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ... </saml:Assertion> </samlp:Response> </samlp:ArtifactResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="s2ead62f287a9e36c31b3a693974582fdae20c5351" IssueInstant="2011-06-28T05:08:41Z"> <saml:Issuer> medical-doctor-sso-idp </saml:Issuer> <saml:Subject> <saml:NameID NameQualifier="medical-doctor-sso-idp" SPNameQualifier="sso-sp" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"> 1234567890 </saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="s2cee63177ff33bcacd5263caa4af9da101837de24" NotOnOrAfter="2011-06-28T05:18:41Z" Recipient="https://ServiceProvider.com/SAML/Consumer/metaAlias/sp"> </saml:SubjectConfirmationData> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2011-06-28T04:58:41Z" NotOnOrAfter="2011-06-28T05:18:41Z"> <saml:AudienceRestriction> <saml:Audience> sso-sp </saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2011-06-28T05:08:41Z" SessionIndex="xxxxx"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:X509 </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement> <saml:Attribute Name="HCROLE "> <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"> Medical Doctor </saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion>
<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> <NameIDPolicy Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> </samlp:AuthnRequest>
<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 ... </Assertion> </samlp:Response>
<Assertion ID="_bf9c623d-cc20-407a-9a59-c2d0aee84d12" Version="2.0" IssueInstant="2013-03-18T07:38:15.144Z" 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:AuthnRequest AssertionConsumerServiceURL="https://(sub_domain).cybozu.com/saml/acs" ID="szqd0c3d0u3vpz5jwna4p24iso42opc4" IssueInstant="2013-04-01T00:00:00Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> https://(sub_domain).cybozu.com </saml:Issuer> <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" /> </samlp:AuthnRequest>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="s2b39863179da0358f10bb499d6ac0e64062e89e1d" InResponseTo="szqd0c3d0u3vpz5jwna4p24iso42opc4" Version="2.0" IssueInstant="2013-04-01T00:30:00Z" Destination="https://(sub_domain).cybozu.com/saml/acs"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> http://(idp_host) </saml:Issuer> <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <samlp:StatusCode xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ... </saml:Assertion> </samlp:Response>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="s2822cac48e7b7ec82ff36710996423e7baec43a00" IssueInstant="2013-04-01T00:30:00Z" Version="2.0"> <saml:Issuer> https://(idp_host) </saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> ...アサーションの署名の内容... </ds:Signature> <saml:Subject> <saml:NameID NameQualifier="https://(idp_host)" SPNameQualifier="https://(sub_domain).cybozu.com" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"> watanabe </saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="szqd0c3d0u3vpz5jwna4p24iso42opc4" NotOnOrAfter="2013-04-01T00:40:00Z" Recipient="https://(sub_domain).cybozu.com/saml/acs" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2013-04-01T00:20:00Z" NotOnOrAfter="2013-04-01T00:40:00Z"> <saml:AudienceRestriction> <saml:Audience>https://(sub_domain).cybozu.com </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2013-04-01T00:29:30Z" SessionIndex="s2901e6c0e0cc0c8f1aa1075215125b2676774dd01"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion>
https://github.com/Sustainsys/Saml2/blob/master/Sustainsys.Saml2/XmlHelpers.cs#L368
https://gist.github.com/daisukenishino2/69074e571cf89c23cce6d1522abc67e5
Tags: :IT国際標準, :認証基盤, :クレームベース認証, :SAML