correct way Mule OAuth2 client credentials refresh token - oauth-2.0

I am using mule to connect/consume some services. Authentication is OAuth2 client-credential.
What is best way to refresh the token?
One way could be checking http.status like
refreshTokenWhen="#[message.inboundProperties['http.status'] == 401]"
but I am not very happy with that since it should fail once to refresh the token.
Is there anyway to refresh the token based on expire time?
my sample code:
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:oauth2="http://www.mulesoft.org/schema/mule/oauth2" xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/oauth2 http://www.mulesoft.org/schema/mule/oauth2/current/mule-oauth2.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<http:request-config name="HTTP_Request_Configuration" protocol="HTTPS" host="${remote.host}" port="${remote.port}" basePath="${remote.path}" doc:name="HTTP Request Configuration">
<oauth2:client-credentials-grant-type clientId="${clientid}" clientSecret="${clientSecret}" tokenManager-ref="Token_Manager_Config">
<oauth2:token-request tokenUrl="${remote.tokenUrl}" refreshTokenWhen="#[message.inboundProperties['http.status'] == 401 ]">
<oauth2:token-response accessToken="#[json:access_token]" expiresIn="#[json:expires_in]"/>
</oauth2:token-request>
</oauth2:client-credentials-grant-type>
</http:request-config>
<oauth2:token-manager-config name="Token_Manager_Config" doc:name="Token Manager Config"/>

There is a chache scope in mule, you can keep your gettoken flow in cache scope and you can specify the expire time, till that time it will use the cached token, when ever it gets expire then it will invoke the get token flow and it will store the new token in your cache.
Sample code:
<ee:object-store-caching-strategy name="Caching_Strategy" doc:name="Caching Strategy">
<managed-store storeName="myManagedStore" maxEntries="1" entryTTL="${token.expiretime}" expirationInterval="${token.expireinterval}"/>
</ee:object-store-caching-strategy>
<ee:cache cachingStrategy-ref="Caching_Strategy" doc:name="Cache">
<flow-ref name="getTokenFlow" doc:name="getTokenFlow"/>
</ee:cache>
Check more documentation at below link:
https://docs.mulesoft.com/mule-user-guide/v/3.7/cache-scope

Related

Azure APIM : External Backend API Oauth2 authentication with Bearer token integration

We have the current situation:
In Azure API manager we build some APIs based on a Swagger definition.
The provider of the APIs provided us with a client id and secret.
Some of these API calls need to be authenticated with a bearer token which is generated on the provider's API infrastructure with a /token endpoint mentioned above and we want to integrate the authentication flow for these API calls in APIM (since the frontend will be authenticated in another way (CORS probably))
We tried various approaches using all kinds of variations in "OAuth2.0" service configurations in the APIM setting and apply them to the API definitions by We kept getting Unauthorized 401.
As starting point we used https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-protect-backend-with-aad, but most of the the explanations we found concerned using AD, which we don't need as far as we understand.
We tried to implement the following OAuth 2.0 Postman Authorization configuration into APIM (which actually works in Postman).
Is there a simple and straight forward way to tell APIM to do a call to the token URL with a given ClientId and secret and add the authorization header with a bearer token to the backend API?
Thanks to Gary for pointing me in the right direction. I'm quiet new to the topic, so my approach might be far from perfect but it works.
I ended up in modifying the inbound policies of the API call and added the following (replace xxxx's with the appropriate settings)
<policies>
<inbound>
//....
<send-request mode="new" response-variable-name="tokenstate" timeout="20" ignore-error="true">
<set-url>https://xxxxxxxxxx.azurewebsites.net/connect/token</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/x-www-form-urlencoded</value>
</set-header>
<set-header name="Accept" exists-action="override">
<value>*.*</value>
</set-header>
<set-body>
#("grant_type=client_credentials&scope=xxxxxx&client_id=xxxxxxxx&client_secret=xx")
</set-body>
</send-request>
<set-variable name="bearerToken" value="#(((IResponse)context.Variables["tokenstate"]).Body.As<JObject>()["access_token"].ToString())" />
<set-header name="Authorization" exists-action="override">
<value>#("Bearer " + (string)context.Variables["bearerToken"])</value>
</set-header>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-header name="Accept" exists-action="override">
<value>*/*</value>
</set-header>
</inbound>
Short explanantion
A new request is initaited which response will be stored in the variable (token state)
The method is defined as POST
Headers for the request are set (Centent-Type & Accept)
The body of the request is defined
Since the response of the token request (stored in tokenstate) is JSON formatted, the response of the request is cast to a JObject and the "access_token" is stored in the "bearerToken" variable (alternatively you could do without assigning the variable and put this line immediately in the next step.
Set the "Autorization" header with the value "Bearer " + [bearerToken]
the additional steps (Set header Content-Type & Accept) I needed to be able to debug, but in normal cases they will be added by the requesting client of the API.
Yes - you can do this and here is a Curity resource that follows a similar process:
Make an OAuth request to get a JWT based on an incoming credential
Forward it to the downstream API
Cache the result for subsequent requests with the same incoming credential
Your case is a little different but uses the same building blocks. You just need to adapt the OAuth message to use the Client Credentials flow.

Error: ExchangeImpersonation SOAP header must be present for this type of oauth token

I am trying to use Exchange Web Services (EWS) with application and OAuth2 authentication.
What I did:
registered on Azure portal application, granted all required permissions (even full_access_as_app for Exchange); accepted these permissions as an admin;
prepared correct OAuth2 Bearer token (with scope https://outlook.office365.com/.default);
prepared SOAP request with SOAP UI. As basis for this request I use this one: https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/getattachment-operation . Additionally I've added HTTP Authorization header with Bearer token, X-AnchorMailbox with target mailbox.
As a result I get this one: "ExchangeImpersonation SOAP header must be present for this type of OAuth token". I cannot understand what should I do to fix it.
Even tried with ExchangeImpersonate and SmtpAddress with the same mailbox address as above but in this way I get another error "Mailbox not found". But mailbox is! (tested on several mailboxes).
My questions is: what am I doing wrong with EWS?
Request:
POST https://outlook.office365.com/ews/Exchange.asmx
Authorization: Bearer <token>
X-AnchorMailbox: mailbox#something.onmicrosoft.com
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Header>
        <t:RequestServerVersion Version="Exchange2016"/>
        <t:ExchangeImpersonation>
            <t:ConnectingSID>
                <t:PrimarySmtpAddress>
                    mailbox#something.onmicrosoft.com
                </t:PrimarySmtpAddress>
            </t:ConnectingSID>
        </t:ExchangeImpersonation>
  </soap:Header>
  <soap:Body>
    <GetAttachment xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <AttachmentShape/>
      <AttachmentIds>
        <t:AttachmentId Id="AAMkADAwNzdjNTg3LTc4M2ItNDE0Yi05MTk4LTQxZDBlYTc1NmMxZgBGAAAAAAAiixtLGariQY7rf5pAKRZZBwBVk8babsuEQ4s2Znfj9fB5AAAAAAEMAABVk8babsuEQ4s2Znfj9fB5AADq3B14AAABEgAQAKZOAcjZCBxHpqvY6XmXp5w="/>
      </AttachmentIds>
    </GetAttachment>
  </soap:Body>
</soap:Envelope>
Response:
ErrorNonExistentMailbox The SMTP address has no mailbox associated with it.
This fixed it for me.
_exchangeService.ImpersonatedUserId =
new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userEmailAddress);
You would need to instantiate impersonation as below:
var ews = new Rebex.net.Ews();
ews.Connect(outlook.office365.com);
ews.Settings.Impersonation = new EwsImpersonation();
ews.Settings.Impersonation.SmtpAddress = <mailbox address>;

Get OAuth2 Token in XML format from Mule OAuth2 provider; currently it returns it as JSON

I have implemented OAuth2 provider using Mule Password grant type flow as shown on https://developer.mulesoft.com/docs/display/current/Creating+an+OAuth+2.0a+Web+Service+Provider. But it is returning token response in JSON format; I want it in XML format how can I do that ?
<spring:beans>
<ss:authentication-manager id="resourceOwnerAuthenticationManager">
<ss:authentication-provider>
<ss:user-service id="resourceOwnerUserService">
<ss:user name="user" password="password" authorities="RESOURCE_OWNER" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
<mule-ss:security-manager>
<mule-ss:delegate-security-provider
name="resourceOwnerSecurityProvider"
delegate-ref="resourceOwnerAuthenticationManager" />
</mule-ss:security-manager>
<oauth2-provider:config
        name="oauth2Provider"
        providerName="SampleAPI"
        supportedGrantTypes="RESOURCE_OWNER_PASSWORD_CREDENTIALS"
        port="8083"
        authorizationEndpointPath="sampleapi/api/authorize"
        accessTokenEndpointPath="sampleapi/api/token"
        resourceOwnerSecurityProvider-ref="resourceOwnerSecurityProvider"
        scopes="READ_RESOURCE POST_RESOURCE" doc:name="OAuth provider module">
            <oauth2-provider:clients>
                <oauth2-provider:client clientId="myclientid3" secret="myclientsecret"
                                        type="CONFIDENTIAL" clientName="Mule Bookstore" description="Mule-powered On-line Bookstore">
                    <oauth2-provider:redirect-uris>
                        <oauth2-provider:redirect-uri>http://localhost*</oauth2-provider:redirect-uri>
                    </oauth2-provider:redirect-uris>
                    <oauth2-provider:authorized-grant-types>
                        <oauth2-provider:authorized-grant-type>PASSWORD</oauth2-provider:authorized-grant-type>
                    </oauth2-provider:authorized-grant-types>
                    <oauth2-provider:scopes>
                        <oauth2-provider:scope>READ_RESOURCE</oauth2-provider:scope>
                        <oauth2-provider:scope>POST_RESOURCE</oauth2-provider:scope>
                    </oauth2-provider:scopes>
                </oauth2-provider:client>
            </oauth2-provider:clients>
    </oauth2-provider:config>
I think if you want to do this you need create a choice at the end of the flow, and then if the 'Accept' header is equal 'application/xml' you put a custom transformer from json to xml. Because the OAuth2 Spec says the token returned should be a json. I did it with spring security oauth2 but this is a customization.
You might want to create a new http mule flow which invokes the oauth2-provider token endpoint and convert its response to xml.
create a new mule configuration file:
<flow name="token-json-to-xmlFlow">
<http:listener> <-- new token endpoint
<http:request> <-- invoke the oauth2 provider token
<transform-message> <-- json to xml transformer
</flow>
hope this helps.

Spring SAML integration with WSO2 Identity server, SAML Message ID not reconised

I have taken the Spring SAML example (see section 4.2 in this guide) which works with the Open source login page SSO, and tried to add support to use WSO2 Identity Server as an additional IDP service.
To do this I changed the spring SAML sample project by adding a metadata xml file for IS, and added an entry for the IS metadata to the securityContext.xml.
On running the spring application I now get presented with an option to login using IS, and I can successfully login in on WSO2 when I'm redirected to it. However the spring application throws an exception on the IS SAML response about it not matching the InResponseToField.
2015-01-05 09:54:12,845 line="org.springframework.security.saml.log.SAMLDefaultLogger.log(SAMLDefaultLogger.java:127)" thread="http-nio-8080-exec-4" class="org.springframework.security.saml.log.SAMLDefaultLogger" AuthNResponse;FAILURE;0:0:0:0:0:0:0:1;com:vdenotaris:spring:sp;localhost;;;org.opensaml.common.SAMLException: InResponseToField of the Response doesn't correspond to sent message ae2dab0fb8b0g8e49971b91a73e91i
From debugging the application it appears the response message is not recognised as belonging to the same session as the request message. I say that from these 2 log messages, 1st is logged when sending the AuthRequest and the 2nd is when the response is received:
2015-01-05 09:53:20,867 line="org.springframework.security.saml.storage.HttpSessionStorage.storeMessage(HttpSessionStorage.java:93)" thread="http-nio-8080-exec-1" class="org.springframework.security.saml.storage.HttpSessionStorage" Storing message ae2dab0fb8b0g8e49971b91a73e91i to session 26D3B7D9E33F26A7A5092BF6909B9D13
...
2015-01-05 09:54:10,731 line="org.springframework.security.saml.storage.HttpSessionStorage.retrieveMessage(HttpSessionStorage.java:117)" thread="http-nio-8080-exec-4" class="org.springframework.security.saml.storage.HttpSessionStorage" Message ae2dab0fb8b0g8e49971b91a73e91i not found in session BBF256F284F55D774E6997600E9B3388
The IS SAML response is:
<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://localhost:8080/saml/SSO" ID="adlbklpnldoanfphalcaahhacooinnldcejjjioe" InResponseTo="ae2dab0fb8b0g8e49971b91a73e91i" IssueInstant="2015-01-05T09:53:38.063Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">localhost</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="ebhfkdhlgbhclcklefjigfddoikklhjlanlbolel" IssueInstant="2015-01-05T09:53:38.065Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">localhost</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">smit005</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="ae2dab0fb8b0g8e49971b91a73e91i" NotOnOrAfter="2015-01-05T09:58:38.063Z" Recipient="http://localhost:8080/saml/SSO"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2015-01-05T09:53:38.065Z" NotOnOrAfter="2015-01-05T09:58:38.063Z">
<saml2:AudienceRestriction>
<saml2:Audience>com:vdenotaris:spring:sp</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2015-01-05T09:53:38.068Z" SessionIndex="406d4530-6fcf-4edf-b876-a68de4b4ea79">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement/>
</saml2:Assertion>
</saml2p:Response>
For reference I attach the metadata xml file I added for WSO2 IS (I had to give it an entityID of 'localhost' as this was what WSO2 IS insists on returning (it uses the host name by default)).
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="localhost"
validUntil="2023-09-23T06:57:15.396Z">
<md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" >
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIICNTCCAZ6gAwIBAgIES343gjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzELMAkGA1UE
CAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxDTALBgNVBAoMBFdTTzIxEjAQBgNVBAMMCWxv
Y2FsaG9zdDAeFw0xMDAyMTkwNzAyMjZaFw0zNTAyMTMwNzAyMjZaMFUxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzENMAsGA1UECgwEV1NPMjESMBAGA1UE
AwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUp/oV1vWc8/TkQSiAvTou
sMzOM4asB2iltr2QKozni5aVFu818MpOLZIr8LMnTzWllJvvaA5RAAdpbECb+48FjbBe0hseUdN5
HpwvnH/DW8ZccGvk53I6Orq7hLCv1ZHtuOCokghz/ATrhyPq+QktMfXnRS4HrKGJTzxaCcU7OQID
AQABoxIwEDAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEAW5wPR7cr1LAdq+IrR44i
QlRG5ITCZXY9hI0PygLP2rHANh+PYfTmxbuOnykNGyhM6FjFLbW2uZHQTY1jMrPprjOrmyK5sjJR
O4d1DeGHT/YnIjs9JogRKv4XHECwLtIVdAbIdWHEtVZJyMSktcyysFcvuhPQK8Qc/E/Wq8uHSCo=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://localhost:9443/samlsso" ResponseLocation="https://localhost:9443/samlsso"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://localhost:9443/samlsso"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://localhost:9443/samlsso"/>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
As requested I've saved a log of the browser HTTP messages on dropbox.
Both Spring SAML and your IDP WSO2 server are deployed on the same domain - localhost. This is what happens:
Spring SAML creates an HTTP session (JSESSIONID - 82F3ECD1A1E4F9B7DB0134F3129267A5) and initializes single sign-on
WSO2 accepts the request and authenticates the user, but creates its own session (JSESSIONID -C34B21931C53080487B5B9BA6EB490D2) and redirects user back to Spring SAML
container running Spring SAML receives the cookie with JSESSIONID (C34B21931C53080487B5B9BA6EB490D2), but as it doesn't recognize such session it creates a new one (E712A8422009613F6FD3901327690726)
Spring SAML tries to verify received SAML message based on the original request, but it cannot be found because the original session is now gone
The easiest way to fix this is to change session cookie name for Spring SAML or WSO2. You could also deploy your applications on different domains (for example by giving your localhost an alias in the hosts file - /etc/hosts or %systemroot%\system32\drivers\etc\hosts)

How to get SAML2 Bearer Assertion profile for OAuth within WSO2 API Manager to work?

I have problems getting work "SAML2 Bearer Assertion profile for Oauth" within WSO2 API Manager. I'm trying to apply "Johann's Wall" How-to on API Manager (ver. 1.5) but running in the following error.
[2013-11-08 17:44:35,930] DEBUG - SAML2BearerGrantTypeHandler SAML Assertion Audience Restriction validation failed
[2013-11-08 17:44:36,024] DEBUG - AccessTokenIssuer Invalid Grant provided by the client, id=enfKWsilmCxdIwhYiINcoA2JKwka, user-name=admin to application=MyFlowChart
[2013-11-08 17:44:36,025] DEBUG - AccessTokenIssuer OAuth-Error-Code=invalid_grant client-id=enfKWsilmCxdIwhYiINcoA2JKwka grant-type=urn:ietf:params:oauth:grant-type:saml2-bearer scope=
Checking the code of org.wso2.carbon.identity.oauth2.token.handlers.grant.saml.SAML2BearerGrantTypeHandler this error should only come up if none of the "Identity Provider Audience" entries in the configured "Trusted Identity Provider" matches the <saml:Audience> values within SAML assertion. But comparing the configuration and the SAML assertion (see below) for me everthing looks good.
Hopefully someone can help me out or give me hint want's going wrong...
Setup / Configuration
1.) Setup "Trusted Identity Providers" in API Manager (see screenshot)
2.) Creating a SAML2 Assertion via SAML2AssertionCreator.jar
<?xml version="1.0" encoding="UTF-8"?>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="mkfeiofmkjmjpicmdllnaapcmjlimjmajdiejiip" IssueInstant="2013-11-08T16:43:41.877Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">OAuthPlayground</saml: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="#mkfeiofmkjmjpicmdllnaapcmjlimjmajdiejiip">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>bNaQFYpcakb07xbUpUdVuSidvuA=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>gUe0mXTRPD79HTz7[...]</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIFrDCCBJSgAwIBA[...]</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="0" NotOnOrAfter="2013-11-08T16:48:41.877Z" Recipient="https://sl02502.apps.eon.com:9443/oauth2endpoints/token"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2013-11-08T16:43:41.877Z" NotOnOrAfter="2013-11-08T16:48:41.877Z">
<saml:AudienceRestriction>
<saml:Audience>restriction</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2013-11-08T16:43:41.945Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute>
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">a</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
3.) Running "curl" with base64 encoded SAML assertion against OAuth endpoint of API Manager
curl -k -X POST -u "enfKWsilmCxdIwhYiINcoA2JKwka:eEfmtoFRFyl3JIhMH1jM0bbXbkMa" -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer&assertion=PD94bWwgdm[...]0aW9uPg%3D%3D" https://sl02502.apps.eon.com:9445/oauth2/token
The problem is in your SAML2 Assertion. You cannot find a Audience element which has the OAuth2 token endpoint as an audience. The only audience you have is "restriction". For the saml2-bearer grant type to work you need to have the OAuth2 token endpoint as an audience for the assertion.
What you need to do is when generating the SAML2 assertion using "SAML2AssertionCreator.jar" you need to specify multiple audiences using comma separated values.
E.g. https://sl02502.apps.eon.com:9445/oauth2/token,restriction
In fact the only audience you need to get saml2-bearer grant type working is the token endpoint. I.e. you don't need to specify any audience at all in the 'Trusted Identity Provider' configuration. If you do specify any audience here, then you need to make sure those audiences are coming in the SAML2 Assertion. This is useful in scenarios where this SAML2 Assertion will be used by other relying parties in addition to the token endpoint. In your case if you don't have such requirement you could remove the audience called 'restriction' from both the 'Trusted Identity Provider' configuration and the assertion or if you need such an audience you must have it in both places.

Resources