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 C# 调用Bartender打印机打印
  • ¥100 华为ensp只要2-9实验运行结果能做的来加我QQ
  • ¥15 我这个代码哪里有问题 acm 平台上显示错误 90%,我自己运行好像没什么问题
  • ¥50 C#编程中使用printDocument类实现文字排版打印问题
  • ¥15 找会编程的帅哥美女 可以用MATLAB里面的simulink编程,用Keil5编也可以。
  • ¥15 已知隐函数其中一个变量τ的具体值,求另一个变量
  • ¥15 r语言Hurst指数
  • ¥15 Acrn IVSHMEM doorbell问题
  • ¥15 yolov5中的val测试集训练时数量变小问题
  • ¥15 MPLS/VPN实验中MPLS的配置问题