douxie9471 2016-11-21 15:43
浏览 120
已采纳

如何在PHP中检索SAML2令牌以从WSO2 APIM获取OAuth令牌

I have been looking around for a solution but can't find it.

This question is directly related to:

Here's the scenario I want to execute:

  1. authenticate to the SP using SAML2. Coded in PHP with SimpleSamlPhp.
  2. get an OAuth token from the API mgr endpoint, using the SAML2 assertion. (using URL http://api.gateway/token)
  3. call APIs over the API mgr's gateway, using the OAuth token.

I'm stuck at the instruction: get the SAML2 assertion token. Where do I find this token? In SimpleSamlPhp I can get attributes of the user, or their id, but I can't find any assertion.

I hacked SSP to get the last assertion, but don't know what to do with it. I was expecting a single value (like a token), but it's a complex structure. And one of the links above says I shouldn't be accessing it!

What do I send, encoded, to the token URL?


EDIT: adding some samples. My assert XML (edited):

<?xml version="1.0" encoding="UTF-8"?>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" ID="okdjgbm...jdbh" IssueInstant="2016-11-28T09:49:45.808Z" Version="2.0">
   <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://g...p.com:9443/samlsso</saml2:Issuer>
   <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>
         <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
         <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
         <ds:Reference URI="#okd...kejdbh">
            <ds:Transforms>
               <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
               <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>RrGcR...cktFuH0=</ds:DigestValue>
         </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>b91j/k...Z7d4=</ds:SignatureValue>
      <ds:KeyInfo>
         <ds:X509Data>
            <ds:X509Certificate>MIICNT...Wq8uHSCo=</ds:X509Certificate>
         </ds:X509Data>
      </ds:KeyInfo>
   </ds:Signature>
   <saml2:Subject>
      <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">toto@titi.com</saml2:NameID>
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
         <saml2:SubjectConfirmationData InResponseTo="_80258326a1...cd4bbd" NotOnOrAfter="2016-11-28T09:54:45.807Z" Recipient="http://1.2.3.4/simplesamlphp/www/module.php/saml/sp/saml2-acs.php/wso2-sp" />
      </saml2:SubjectConfirmation>
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
         <saml2:SubjectConfirmationData InResponseTo="_8025832...d4bbd" NotOnOrAfter="2016-11-28T09:54:45.807Z" Recipient="https://my.wso2.apim:8243/token" />
      </saml2:SubjectConfirmation>
   </saml2:Subject>
   <saml2:Conditions NotBefore="2016-11-28T09:49:45.808Z" NotOnOrAfter="2016-11-28T09:54:45.807Z">
      <saml2:AudienceRestriction>
         <saml2:Audience>mytestapp</saml2:Audience>
         <saml2:Audience>https://my.wso2.apim:8243/token</saml2:Audience>
      </saml2:AudienceRestriction>
   </saml2:Conditions>
   <saml2:AuthnStatement AuthnInstant="2016-11-28T09:49:45.815Z" SessionIndex="1f5192...b591">
      <saml2:AuthnContext>
         <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
      </saml2:AuthnContext>
   </saml2:AuthnStatement>
   <saml2:AttributeStatement />
</saml2:Assertion>

encode as base64-URL-encoded XML:

PHNhbWwyO...dGlvbj4,

using the method copied from another SO post

function base64_url_encode($input) {
 return strtr(base64_encode($input), '+/=', '-_,');
}

It's about 20 lines long (and yes, there's a comma at the end).

It doesn't work, I get the JSON result

{"error":"invalid_grant","error_description":"Provided Authorization Grant is invalid."}

In the traces:

TID: [0] [AM] [2016-11-29 11:04:50,297] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantHandler} -  SAML Token Issuer verification failed or Issuer not registered {org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantHandler}
TID: [0] [AM] [2016-11-29 11:04:50,298] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} -  Invalid Grant provided by the client, id=fkJa...Ohoa, user-name=null to application=myapp-subscriber_test_PRODUCTION {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer}
TID: [0] [AM] [2016-11-29 11:04:50,300] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} -  OAuth-Error-Code=invalid_grant client-id=fkJa...hoa grant-type=urn:ietf:params:oauth:grant-type:saml2-bearer scope=PRODUCTION {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer}

I'm asking around to the configurators of the system. Seems to me there's something missing in the link between IDS, APIM and OAuth, some declaration. (I googled this, and came up with a stackoverflow exchange to check the issuer id in the assertion, which I did, but I can't identify anything wrong there)

Thanks for the help, I will come back if I have anything new. Except of course if I have overlooked something obvious!

  • 写回答

2条回答 默认 最新

  • douzuita7325 2016-12-08 11:11
    关注

    I have succeeded, so here are some indications for others who may have the same issue.

    1. I hacked simpleSamlPhp because they do not provide the SAML2 assertion (see https://github.com/simplesamlphp/simplesamlphp/issues/220). I did not do it in a nice way, because I only wanted to make it work. It's ugly but it works. Here's my hack, I put it at line 125 of saml2-acs.php:

      // ADDED to get SAML2 assertion in SP
      if (array_key_exists('SAMLResponse', $_POST)) {
          $attributes["samlresp"] = $_POST['SAMLResponse'];
      }
      
    2. In my PHP app, I then use this code:

      $authdata_array= $as->getAuthDataArray();
      $postSaml2Assert = $authdata_array["Attributes"]["samlresp"];
      $msg = base64_decode($postSaml2Assert);
      $document = new DOMDocument();
      $document->loadXML($msg);
      $assertion = $document->getElementsByTagNameNS ("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion")->item(0);
      $saml2AssertionXml = $document->saveXML($assertion);
      
    3. I encode the assertion base64 and URL-encode. For this I used code from Passing base64 encoded strings in URL (thanks joeshmo!)

    4. in APIM / Entity Providers / list / myIdS / edit / Federated Authenticators / SAM2 web SSO... / Identity Provider entity ID I set the value to the expected IDS endpoint, https://myids:9443/samlsso. This solved my initial issue

    5. in the SP configuration (in the IDS) I added the oauth token both as audience and recipient, looks like https://myAPIM:9443/oauth2/token/. Caution, both as audience and recipient!

    6. Because I was debugging I had formatted the XML assertion, so it wasn't working, I ran into the problem detailed here WSO2 Identity Server OAuth2 Bearer SAML Assertion so I simply removed the formatting and used the XML string as-is. (I have of course removed this error from above)

    7. I had a last error easy to solve: the NotOnOrAfter flag was making trouble, because there was a delay between getting the SAML2 assertion and using it to generate a token. Lesson learned: The SAML2 assertion should be created just after logging in, not just before calling APIs.

    Hope this helps others. Thanks @Bhathiya for helping!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog