「マイクロソフト系技術情報 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は使えない。
○ emailAddress ○ unspecified ☓ persistent(永続的仮名) ☓ transient(一時的仮名) ☓☓ X509SubjectName ☓☓ WindowsDomainQualifiedName ☓☓ kerberos ☓☓ entity
多くのSPでは使用していない
○ exact ☓ minimum ☓ maximum ☓ better
○ unspecified(不特定の方法で) ○ PasswordProtectedTransport(パスワード) ☓ Password(PasswordProtectedTransportとの違いが?) ☓ PreviousSession(既存のセッションを利用) ☓ X509 ☓ SecureRemotePassword ☓ TimeSyncToken ☓ Smartcard ☓ SmartcardPKI ☓ MobileOneFactorContract ☓ MobileOneFactorUnregistered ☓ MobileTwoFactorContract ☓ MobileTwoFactorUnregistered ☓ PGP ☓ SPKI ☓ XMLDSig ☓ TLSClient ☓ Kerberos ☓ Telephony ☓ NomadTelephony ☓ AuthenticatedTelephony ☓ SoftwarePKI ☓ InternetProtocol ☓ PersonalTelephony ☓ InternetProtocolPassword
下記のsamltool.ioからアサーションを取得し、SAMLTool.comで確認するなど。
※ 外側だけ検証すればイイ気がする。
 コチラが、SignedXml?によるネストしたXML署名・検証結果。
XmlDocuement? を利用する際に PreserveWhitespace? を単に true にする。
著名、IdPを使用してテストする。
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