AADSTS90081: An error occurred when we tried to process a WS-Federation message. The message was invalid - azure

Testing WS-Federation - Passive Requestor Profile implementation in my custom STS against a federated domain in AAD using web-browser (https://outlook.office365.com/owa).
I am able to HTTP-POST the response (RSTR) to https://login.microsoftonline.com/login.srf after successful authentication at custom STS/ IdP, but somehow following error is showing in the screen.
Sign In
Sorry, but we’re having trouble signing you in. We received a bad
request.
Additional technical information:
Correlation ID: 245b8d44-c4a5-46fc-a8c3-427c27791863
Timestamp: 2017-06-14 06:19:26Z
AADSTS90081: An error occurred when we tried to process a WS-Federation message. The message was invalid.
Please refer posted RSTR below.
Also I couldn't see any audit logs corresponding to this message invalid error in https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Audit.
Any idea what I am missing here? or Is there a way to see federated domain's error logs in Azure AD admin portal?
Please advice.
wsresult = <t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:wp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
<t:RequestedSecurityToken>
<saml:Assertion AssertionID="id-HwkRp-evkRNQDektd-zMdRKZ74LuDuuWhec-J9Lt" IssueInstant="2017-06-14T03:07:07Z" Issuer="urn:fed:mySts" MajorVersion="1" MinorVersion="1">
<dsig:Signature>
<dsig:SignedInfo>
<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<dsig:Reference URI="#id-HwkRp-evkRNQDektd-zMdRKZ74LuDuuWhec-J9Lt">
<dsig:Transforms>
<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<dsig:DigestValue>D5DvtVT9y/tvKKK1+CmmMRL95Ogg+9lZUkGB9crTC/w=</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
<dsig:SignatureValue>YEUp7GuC5qwEYUw4iKxrkezBKd8TetLiKkx63JTt6oizAzSQsLahDTlo3Pl/Na0tJEApLVMICsriZotNRQLrM9MuqI2cmYLqHGaK1LWs3euRwkT1hq6tHKuSkl7yGew4PYB/ZOVSAqHxDx1G2A3AkbYXu/IgHoeBnghdwszbYbs=</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509Certificate>MIICUDCCAbmgAwIBAgIELfGcX...</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
</dsig:Signature>
<saml:Conditions NotBefore="2017-06-14T03:06:37Z" NotOnOrAfter="2017-06-14T03:12:37Z">
<saml:AudienceRestrictionCondition>
<saml:Audience>urn:federation:MicrosoftOnline</saml:Audience>
</saml:AudienceRestrictionCondition>
</saml:Conditions>
<saml:AuthenticationStatement AuthenticationInstant="2017-06-14T03:07:07Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password">
<saml:Subject>
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">4JRuZcPlfk+syK/x5WMgbA=</saml:NameIdentifier>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
</saml:SubjectConfirmation>
</saml:Subject>
</saml:AuthenticationStatement>
<saml:AttributeStatement>
<saml:Subject>
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">4JRuZcPlfk+syK/x5WMgbA=</saml:NameIdentifier>
<saml:SubjectConfirmation>
<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Attribute AttributeName="UPN" AttributeNamespace="http://schemas.xmlsoap.org/claims">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">xyz#abc.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute AttributeName="ImmutableID" AttributeNamespace="http://schemas.microsoft.com/LiveID/Federation/2008/05">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">4JRuZcPlfk+syK/x5WMgbA=</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute AttributeName="objectGUID" AttributeNamespace="http://tempuri.com">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">4JRuZcPlfk+syK/x5WMgbA=</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</t:RequestedSecurityToken>
<wp:AppliesTo>
<wsa:EndpointReference>
<wsa:Address>urn:federation:MicrosoftOnline</wsa:Address>
</wsa:EndpointReference>
</wp:AppliesTo>
<t:Lifetime>
<Created>2017-06-14T03:06:37Z</Created>
<Expires>2017-06-14T03:12:37Z</Expires>
</t:Lifetime>
</t:RequestSecurityTokenResponse>

Related

Azure API Management WSDL Import Failing on SOAP Encoding's Array Type

I'm trying to create an API from a WSDL and currently getting this error back from Azure APIM during the import step:
Error: Parsing error : Line 17, position 22: Unable to import API from WSDL: Undefined
complexType 'http://schemas.xmlsoap.org/soap/encoding/:Array' is used as a base for
complex type restriction.
I'm gathering that the Array type is not WSI-compliant, but would love insight as to how I can tinker with the WSDL to make it work? I don't own the service which generated the WSDL, but the WSDL hasn't changed since it was incepted and the provider has said it's okay for us to mess with it to get the Azure APIM import step to work. Just meaning, since Azure APIM's a passthrough what can I slice out of the WSDL which would still (a) let Azure APIM import it, and (b) allow the calls to successfully flow through Azure APIM at runtime?
I slimmed down the WSDL to this, but let me know if anything looks off as the original WSDL is ~5,500 lines:
<?xml version="1.0"?>
<definitions
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="urn:ChestersCopperpotsServiceSoap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:atls="http://tempuri.org/vc/atl/server/"
targetNamespace="urn:ChestersCopperpotsServiceSoap"
xmlns="http://schemas.xmlsoap.org/wsdl/"
>
<types>
<s:schema targetNamespace="urn:ChestersCopperpotsServiceSoap" attributeFormDefault="qualified" elementFormDefault="qualified">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<s:complexType name="CMessage">
<s:sequence>
<s:element name="Code" type="s:int"/>
<s:element name="Text" type="s:string"/>
</s:sequence>
</s:complexType>
<s:complexType name="GetMessages_return_Array">
<s:complexContent>
<s:restriction base="soapenc:Array">
<s:attribute ref="soapenc:arrayType" wsdl:arrayType="s0:CMessage[]"/>
</s:restriction>
</s:complexContent>
</s:complexType>
<s:complexType name="MyHeader">
<s:sequence>
<s:element name="m_SessionID" type="s:string"/>
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="GetMessagesIn">
</message>
<message name="GetMessagesOut">
<part name="return" type="s0:GetMessages_return_Array"/>
</message>
<message name="m_Header">
<part name="m_Header" type="s0:MyHeader"/>
</message>
<portType name="ChestersCopperpotsServiceSoap">
<operation name="GetMessages">
<input message="s0:GetMessagesIn"/>
<output message="s0:GetMessagesOut"/>
</operation>
</portType>
<binding name="ChestersCopperpotsServiceSoap" type="s0:ChestersCopperpotsServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="GetMessages">
<soap:operation soapAction="#GetMessages" style="rpc"/>
<input>
<soap:body use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header message="s0:m_Header" part="m_Header" use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header message="s0:m_Header" part="m_Header" use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="ChestersCopperpotsService">
<port name="ChestersCopperpotsServiceSoap" binding="s0:ChestersCopperpotsServiceSoap">
<soap:address location="http://localhost:80/ChestersCopperpots/ccSOAP.dll?Handler=Default"/>
</port>
</service>
</definitions>
Full message stack from Azure APIM is:
Informational: ParsingXMLStarted : Started parsing XML
Informational: ParsingXMLComplete : Completed parsing XML
Verbose: WsdlImportRuleVerifyWadl11Schema : WSDL validated against XML Schema
Informational: WsdlPrecheckComplete : Completed WSDL verification. WSDL is considered valid.
Informational: WsdlParsingStarted : Service : Endpoint :
Informational: WsdlIdentification : WsdlVersion: 'Wsdl11' TargetNamespace: 'urn:ChestersCopperpotsServiceSoap'.
Informational: LoadedSchema : Target Namespace: 'urn:ChestersCopperpotsServiceSoap'.
Informational: LoadedSchemas : Loaded '1' schemas.
Informational: LoadedTypes : Loaded '0' types.
Informational: LoadedMessages : Loaded '3' messages.
Informational: LoadedInterfaces : Loaded '1' interfaces.
Informational: LoadedBindings : Loaded '1' bindings.
Informational: LoadedServices : Loaded '1' services.
Informational: WsdlParsingComplete : Parsed 1 operations and 3 messages
Informational: ApiType : Creating SOAP Passthrough API
Informational: APICreated : Name : chesterscopperpotsservice Service Url: http://localhost:80/ChestersCopperpots/ccSOAP.dll?Handler=Default
Informational: XsdParsing : Starting to parse urn:ChestersCopperpotsServiceSoap
Error: Parsing error : Line 17, position 22: Unable to import API from WSDL: Undefined complexType 'http://schemas.xmlsoap.org/soap/encoding/:Array' is used as a base for complex type restriction.
my money is on this part (which in lack of row #, I suspect this is where the error get's triggered). The SOAP-to-REST transformation in APIM only supports "embedded" arrays, whereas yours is referring to another definition ("s0.CMessage" above). Try replacing that bit with
<s:complexType name="GetMessages_return_Array">
<sequence>
<element name="ArrayOfCMessages" type="CMessage" minOccurs="1" maxOccurs="1"/>
</sequence>
</s:complexType>

PYTHON REQUESTS ERROR: ('Connection aborted.', OSError("(10054, 'WSAECONNRESET')"))

I am trying to get data from a web service,working with soap. Until now, I was able to get successfull responses but now my code throws this error. Any ideas on why a working code a day before throws this error now?
Note that this is not a public API, your IP needed to be in whitelist to retrieve data.
edit for code:
import requests
headers = {'x-ibm-client-id': "MY KEY",
'content-type': 'application/soap+xml',
'accept':'application/xml'}
url="https://api.epias.com.tr/epias/exchange/electricity/balancingMarket"
login="""<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>string</wsse:Username>
<wsse:Password>string</wsse:Password>
<wsse:Nonce EncodingType="string">string</wsse:Nonce>
<wsu:Created>string</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp wsu:Id="string">
<wsu:Created>string</wsu:Created>
<wsu:Expires>string</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<dgp:login xmlns:dgp="http://ws.dgpys.deloitte.com"><!-- mandatory -->
<loginMessage>
<Password v="MYPASSWORD"></Password>
<UserName v="MYUSERNAME"></UserName>
</loginMessage>
</dgp:login>
</soapenv:Body>
"""
s=requests.Session()
s.get(url)
res=s.post(url,data=login,headers=headers)
keep the above code ,you should handle the proxy setting.
import urlparse,urllib2
s=requests.Session()
opener=urllib2.build_opener()
if proxy:
proxy_params={urlparse.urlparse(url).scheme : proxy}
opener.add_handler(urllib2.ProxyHandler(proxy_params))
s.get(url)
res=s.post(url,data=login,headers=headers)
if your code used to work, the site might have blocked your IP or don't like your header settings.

Mule - JMS (ActiveMQ) Reconnection

This is my mule flow 1:
HTTP > Payload String > Logger > JMS /normalqueue
The first flow has an error handling:
File (Write a file per message handled)
Flow 2:
JMS /normalqueue > Logger
Recovery flow (Invoked with a groovy script):
File (Read file) > File to String > Flow reference (To First Flow again)
This is the XML from Mule:
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://192.168.198.131:61616" validateConnections="true" doc:name="Active MQ" persistentDelivery="true">
<reconnect blocking="false" frequency="6000"/>
</jms:activemq-connector>
<file:connector name="File" writeToDirectory="C:\errors" autoDelete="true" streaming="true" validateConnections="true" doc:name="File"/>
<flow name="lab-file-catchFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-payload value="#[message.payloadAs(java.lang.String)]" doc:name="Set Payload"/>
<logger message="Started message: #[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint queue="activemq" connector-ref="Active_MQ" doc:name="JMS">
<jms:transaction action="ALWAYS_BEGIN"/>
</jms:outbound-endpoint>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<file:outbound-endpoint path="C:\errors" connector-ref="File" responseTimeout="10000" doc:name="File"/>
</catch-exception-strategy>
</flow>
<flow name="flow-recovery" initialState="stopped" processingStrategy="synchronous">
<file:inbound-endpoint path="C:\errors" connector-ref="File" responseTimeout="10000" doc:name="File"/>
<file:file-to-string-transformer doc:name="File to String"/>
<logger message=" Recovery message: #[message.payloadAs(java.lang.String)]" level="ERROR" doc:name="Logger"/>
<flow-ref name="lab-file-catchFlow" doc:name="Flow Reference"/>
</flow>
<flow name="lab-file-catchFlow2" processingStrategy="synchronous">
<jms:inbound-endpoint queue="activemq" connector-ref="Active_MQ" doc:name="JMS"/>
<logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="lab-file-catchFlow1" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/modify" doc:name="HTTP"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[ if(muleContext.registry.lookupFlowConstruct('flow-recovery').isStopped())
{
muleContext.registry.lookupFlowConstruct('flow-recovery').start();
return 'Started';
} else
{
muleContext.registry.lookupFlowConstruct('flow-recovery').stop();
return 'Stopped';
}]]></scripting:script>
</scripting:component>
<set-payload value="#[message.payloadAs(java.lang.String)]" doc:name="Set Payload"/>
<logger message="#[message.payloadAs(java.lang.String)]" level="INFO" doc:name="Logger"/>
</flow>
I stop service from ActiveMQ, it store a file with the messages from the error handling and I receive the typical error:
Cannot process event as "Active_MQ" is stopped
Then, I run the ActiveMQ service again and start the recovery flow with a groovy script. That flow recover all messages, converts to string and return to the first flow to requeue.
The problem is that mule doesn't detect when service is running again, I need to restart the mule project to detect it.
Is there any way auto detect when the activeMQ is running again with Mule?
By <reconnect-forever/>, Mule will keep re-trying to connect to ActiveMQ
<jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://192.168.198.131:61616" validateConnections="true" doc:name="Active MQ" persistentDelivery="true">
<reconnect-forever/>
</jms:activemq-connector>

How do I correctly digitally sign a SAML2.0 AuthnRequest?

I have a working SAML2.0 Single Sign On system built in coffeescript on express / nodejs.
I use SSOCircle to test my SSO and can successfully authenticate there with either HTTP-POST or HTTP-REDIRECT binding. So far so good.
Now I need to digitally sign my authentication request.
To do this I have used the nodejs xml-crytpo library. This results in SAML that looks like this:
<?xml version="1.0"?>
<samlp:AuthnRequest Version="2.0" ID="_1C8A2EFA-2644-4330-9A36-2B45547ECFAF" IssueInstant="2014-10-14T16:06:27.769Z" Destination="https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" />
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_1C8A2EFA-2644-4330-9A36-2B45547ECFAF">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>m4qHiXM82TuxY31l6+QSECHEHc0=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>fps0I0Rp02qDK0BPTK7Lh+ ...</SignatureValue>
<KeyInfo>
<X509Data>MIICuDCCAaCgAwIBAgIQEVFtJk ...</X509Data>
</KeyInfo>
</Signature>
</samlp:AuthnRequest>
The certificate information contained in the digital signature has been removed for brevity but it comes from a pem file I generated locally (self-signed).
I also updated my Service Provider metadata supplied to SSOCircle to include the SAML attributes AuthnRequestsSigned and WantAssertionsSigned, like this:
<md:EntityDescriptor entityID="http://app.localhost" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
...
</md:SPSSODescriptor>
</md:EntityDescriptor>
Sending my AuthnRequest without the digital signature works fine. When I include the digital signature it fails with a statuscode of 500 and a generic 'Invalid Request' message.
How do I correctly digitally sign my AuthnRequest so it works against SSOCircle?
Thanks.
Edit 1 - Add Cert Key to the SP Metadata
Following suggestions in the comments I have now added the appropriate KeyDescriptor attributes to my sp-metadata to include my self-signed certificate's public-key.
<md:EntityDescriptor entityID="http://app.localhost" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="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:X509SubjectName>CN=app.localhost</ds:X509SubjectName>
<ds:X509Certificate>MIICu ... wg==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIICu ... wg==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
...
</md:EntityDescriptor>
I have included two KeyDescriptor elements, one specifying the use = signing and the other specifying the use = encryption, although I think the latter is redundant (as I am running over TLS) and will be ignored by the IdP.
This does not work and I get the same error:
Reason: The SAML Request is invalid.
Edit 2 - Self Signed Cerificates
Theory: I cannot use a self-signed certificate. Instead I must use a certificate that is known to and trusted by SSOCircle
Result: This was disproved. You can use a self-signed cert just as long as the correct public key is included in the sp-metadata.
Edit 3 - Added Correct Transform Algorithm
I have now updated my signature to specify the #enveloped-signature transformation algorithm.
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
Also I found that the correct structure for the included x509 certificate public key was the following (note the inner X509Certificate element):
<KeyInfo>
<X509Data>
<X509Certificate>MIID...MMxZ</X509Certificate>
</X509Data>
</KeyInfo>
I am now using the TestShib site to run against as this allows access to the IdP logs which provides more detailed and useful information.
Edit 4 - Swapping the SAML Element Order to Match Schema
According to answer given by #Hos (see below) the order of the SAML elements must match the Schema. Therefore the signature element must appear directly after the issuer element, like this:
<samlp:AuthnRequest Version="2.0" ID="_782F6F1E-1B80-4D7D-B26C-AC85030D9300" IssueInstant="2014-10-28T11:45:49.412Z" Destination="https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>http://app.localhost9de83841</saml:Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#_782F6F1E-1B80-4D7D-B26C-AC85030D9300">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>pjXEtbAFMJA3hWhD/f6lxJTshTg=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>FY1...Qg==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIID...MMxZ</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
This still fails SSOCircle with an opaque 500 error. However TestShib shows the following log:
11:02:37.292 - DEBUG [edu.internet2.middleware.shibboleth.common.security.MetadataPKIXValidationInformationResolver:631] - Write lock over cache acquired
11:02:37.292 - DEBUG [edu.internet2.middleware.shibboleth.common.security.MetadataPKIXValidationInformationResolver:634] - Added new PKIX info to entity cache with key: [http://app.localhost9de83841,{urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor,urn:oasis:names:tc:SAML:2.0:protocol,SIGNING]
11:02:37.292 - DEBUG [edu.internet2.middleware.shibboleth.common.security.MetadataPKIXValidationInformationResolver:637] - Write lock over cache released
11:02:37.293 - WARN [edu.internet2.middleware.shibboleth.idp.profile.saml2.SSOProfileHandler:406] - Message did not meet security requirements
org.opensaml.ws.security.SecurityPolicyException: **Validation of protocol message signature failed**
As I read this, the public key used to validate the signature has been extracted from the sp-metadata:
Added new PKIX info to entity cache with key: [http://app.localhost9de83841,{urn:oasis:names:tc:SAML:2.0:metadata}SPSSODescriptor,urn:oasis:names:tc:SAML:2.0:protocol,SIGNING]
However the actual validation has failed, presumably because the digest values do not match. Which means the digest being calculated by xmlcrypto is different from the digest calculated by ShibTest. This can surely only be for one of two reasons:
The algorithms used by xmlcrypto and TestShib to generate the digest are somehow different
The public keys do not match.
A minute examination of the keys show they are the same. So here is my code in case you can spot anything.
Note: This code relies on the nodejs xmlbuilder and xml-crytpo libraries)
getSamlRequest:(idpUrl, requestId, next)->
request = #xmlbuilder.create
'samlp:AuthnRequest':
'#xmlns:samlp':'urn:oasis:names:tc:SAML:2.0:protocol'
'#xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion'
'#Version': '2.0'
'#ID': requestId
'#IssueInstant': (new Date()).toISOString()
'#Destination': idpUrl
'saml:Issuer': '##spEntityId'
,null
,headless: true
request.comment 'insert-signature'
request.element 'samlp:NameIDPolicy':
'#AllowCreate': 'true'
saml = request.end()
#Your self-signed pem file that contains both public and private keys.
#The public key must also be included in your sp-metadata
certFilePath = "certs/sp-certificate.pem"
#fs.readFile certFilePath, (err, certificate)=>
signer = new #xmlcrypto.SignedXml()
signer.signingKey = certificate
signer.addReference "//*[local-name(.)='AuthnRequest']", ['http://www.w3.org/2000/09/xmldsig#enveloped-signature']
signer.keyInfoProvider = new =>
getKeyInfo: (key)=>
public_key = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec(key)[1].replace /[\r\n|\n]/g, ''
"<X509Data><X509Certificate>#{public_key}</X509Certificate></X509Data>"
signer.computeSignature saml
signature = signer.getSignatureXml()
signed = saml.replace '<!-- insert-signature -->', signature
return next null, signed
Edit 5 - Trace of Requests
Below is a trace of the requests made during the SAML handshake with SSOCircle. The output was generated by the nodejs request module in conjunction with the request-debug module.
I have included some clarification notes below this trace output.
{ request:
{ debugId: 17,
uri: 'http://localhost:8082/security/sso/subscription/dev2/096b75a2-4a55-4eec-83c8-d2509e948b07',
method: 'GET',
headers: { host: 'localhost:8082' } } }
{ response:
{ debugId: 17,
headers:
{ 'transfer-encoding': 'chunked',
'content-type': 'application/json; charset=utf-8',
server: 'Microsoft-HTTPAPI/2.0',
'access-control-allow-origin': '*',
'access-control-allow-headers': 'origin, x-requested-with, accept, content-type',
'access-control-allow-methods': 'GET, POST, PATCH, PUT, DELETE',
date: 'Wed, 05 Nov 2014 16:55:49 GMT' },
statusCode: 200,
body: '{"RequestId":"_F7DDDD24-32C6-420E-A550-95872D30033B","SubscriptionName":"Develop-2","SubscriptionURL":"dev2","IdentityProviderCertificateFile":"ssocircle.cer","IdentityProviderDestinationUrl":"https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle","SAMLBinding":"HttpPost"}' } }
{ request:
{ debugId: 18,
uri: 'https://idp.ssocircle.com:443/sso/SSOPOST/metaAlias/ssocircle',
method: 'POST',
headers:
{ host: 'idp.ssocircle.com:443',
'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
'content-length': 3492 },
body: 'SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBWZXJzaW9uPSIyLjAiIElEPSJfRjdEREREMjQtMzJDNi00MjBFLUE1NTAtOTU4NzJEMzAwMzNCIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMTEtMDVUMTY6NTU6NDkuODkwWiIgRGVzdGluYXRpb249Imh0dHBzOi8vaWRwLnNzb2NpcmNsZS5jb206NDQzL3Nzby9TU09QT1NUL21ldGFBbGlhcy9zc29jaXJjbGUiPjxzYW1sOklzc3Vlcj5odHRwOi8vYXBwLmxvY2FsaG9zdDlkZTgzODQxPC9zYW1sOklzc3Vlcj48U2lnbmF0dXJlIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48U2lnbmVkSW5mbz48Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgLz48U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIiAvPjxSZWZlcmVuY2UgVVJJPSIjX0Y3RERERDI0LTMyQzYtNDIwRS1BNTUwLTk1ODcyRDMwMDMzQiI%2BPFRyYW5zZm9ybXM%2BPFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIiAvPjwvVHJhbnNmb3Jtcz48RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiIC8%2BPERpZ2VzdFZhbHVlPjBLdUtNVG1Zc29Wb1BlTXhtdDhuNml2M3RxZz08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU%2BY1htVFJPWVBSWFZPNHpWSkxURXBBSWd0RTd1c2NsSG1QS0NFdTB0NXNzcmVYSjd1a0M4dWdGd2c4Zm1yWDZDenhib3FHNVl1enJkb2RWVVNsbU12bHZXMGpiaWtsQVBXMmtPNTcralB4TWV3UTdFdzJZdTJuRTZ2QkFhMUwxWGpsa0g0a1UrdlVWVEpFQnlsdXhOYjRQN0xoZnJTdnVrZDhWejJwbk5QTnJtY0tJZVp1LzFlZU8wWmRyRVZrdEY1REhVaFV0MEs5aFBhRXB5Z0xsYjVKYWhNZEttei9uQWk4OU04aTEyUTdrQ2hwb1UrcmhjYTQzaDBXdGk2SWI1N1lWRzgyMzE5MlNsdGR5UkZPdXl2bEJRL0FMSkdpN0hNYzRMRXVkQktOL3pxaUFpK1NZYm1ONVNuN0NucFJWbW13U3NJUElncWxCbmlrU2pIQzRQS1VBPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSURnRENDQW1pZ0F3SUJBZ0lESUFTeE1BMEdDU3FHU0liM0RRRUJCUVVBTUM0eEN6QUpCZ05WQkFZVEFrUkZNUkl3RUFZRFZRUUtFd2xUVTA5RGFYSmpiR1V4Q3pBSkJnTlZCQU1UQWtOQk1CNFhEVEUwTVRBeE5qRTBOVFl3TlZvWERURTFNVEF4TmpFME5UWXdOVm93TmpFTE1Ba0dBMVVFQmhNQ1JFVXhFakFRQmdOVkJBb1RDVk5UVDBOcGNtTnNaVEVUTUJFR0ExVUVBeE1LWW1sdlpuSmhZM1JoYkRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS0Y0dDhzWVZNdHRVZkZ3eTZneFpQVjVWbWtCMDZwNXNqck5vUjUxUXZISmZFMkgyTnVTa0Nxa2paVmFwb1FRMStUVTNlelloMmxNVGNYSjU1Y0t2d0lUTlEvQWlLckxjaG4wdGxYZXFIRXhIdXBvazRGd1hqc20xSitpZTBvOUc1UDlRNTFXelRjRXYxSFRBV2Rkak9OK3Zsd3d0YndTaWRtNFBkN3hxZDdvQkhXTjJJSExQNlpGVHRPVWNpdzI1K0xtRk90V3dHdU41c1pNWDV6RDNUc216Y3ZNMFQwUzF0SVlHamhpaWNnM2UrbmhkWXhjSVNvZ1B1NjNlSWswKzM2OFU1TkhnYlJ5SVRnR2tPMFdtTU9PNDhpbFlFcWlPR1E3d3FxeTdrMzZzRGNxZXdiV1lvejFnQzBieGJBeXI1d3ZZUDdnaEVHYktSVXRWeDExZzdVQ0F3RUFBYU9CbmpDQm16QUpCZ05WSFJNRUFqQUFNQ3dHQ1dDR1NBR0crRUlCRFFRZkZoMVBjR1Z1VTFOTUlFZGxibVZ5WVhSbFpDQkRaWEowYVdacFkyRjBaVEFkQmdOVkhRNEVGZ1FVcTFyMnltMkRXb1NoYWgyRm11ekxJOWZjdDdZd1FRWURWUjBqQkRvd09LRXlwREF3TGpFTE1Ba0dBMVVFQmhNQ1JFVXhFakFRQmdOVkJBb1RDVk5UVDBOcGNtTnNaVEVMTUFrR0ExVUVBeE1DUTBHQ0FncVlNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUFIRW5xTlVKN2VaYkkvNmozZTNmK2tFY3BQQUs2L3dXS0hSL1k2TWt1TGZpZERPREJ4eDRPTThQL1MrNFV4QkZSYWtBNFRkWkRNbjdJT2dTZ2Z3elQ0RjFxS1cvTkJKMzRtcjdndi9Yc0gxTDdHMlBEZFdUdmdGN1N5aFpCck9rbVYyZy9KYWg2U2pBREdabGdPWGJuTTlHUjlNN1NpVDBUcmFkay90dU9Zc2pxd2NJaE40eTVwSU9MNnZlemJKQThIeWZUY1lpMGFZVXFyMGl4Qkw1WWh5VDA1Qk13SUhkdFFNNGhqNjdyRDV4ME9QcmVrcTg0MjRkL0RGWmV5QTRBNG04Z3BOL0VDTFF0NzN3ajlqMVRudjBLdmlLRGZOcWJ4NngvL1o3MnN6VVhpWldETWJrNnhvdHVOZTV6Yy9xcXdhSWxLZ2lnWDJvcGRvbU9nTU14WjwvWDUwOUNlcnRpZmljYXRlPjwvWDUwOURhdGE%2BPC9LZXlJbmZvPjwvU2lnbmF0dXJlPjxzYW1scDpOYW1lSURQb2xpY3kgQWxsb3dDcmVhdGU9InRydWUiLz48L3NhbWxwOkF1dGhuUmVxdWVzdD4%3D' } }
{ response:
{ debugId: 18,
headers:
{ server: '"SSOCircle Web Server"',
date: 'Wed, 05 Nov 2014 16:55:48 GMT',
'content-type': 'text/html;charset=UTF-8',
connection: 'close',
'set-cookie': [Object],
'transfer-encoding': 'chunked' },
statusCode: 500,
body: '\n\n\n\n<html><head><title>\n Error Page\n \n </title>\n <link href="/css/bx.css" rel="stylesheet" type="text/css" /></head>\n <body>\n <div id="myheader">\n <h1><img src="/logo.png" alt="IDPee - Put your LOGO here" height="65" width="180"> </h1>\n </div>\n <div id="mycontent">\n <div id="mynav">\n <ul>\n \n </ul>\n </div>\n <div id="mybox">\n <p>\n \n <h2>Error occurred</h2>\n<p>\nReason: Invalid signature in Request.\n</p>\n\n \n </p>\n </div>\n \n </div>\n <div id="myfooter">\n \n Copyright © SSOCircle/IDPee.com\n \n \n </div>\n </body>\n</html>\n\n\n\n' } }
error: message=Something went wrong whilst trying to automatically log you in. Please try again., name=SSOFailure, message=An error occurred whilst processing the SSO Request., name=SSORequestFailure, message=The IdP failed to successfully process the SAMLRequest and returned an statuscode of 500., name=SamlRequestInvalid, url=http://app.localhost/security/saml2/request
Request debugId= 17: This is the call made by my client into my nodejs proxy server that kicks of the SAML handshake.
ResponsedebugId= 17: A 200 OK response from the proxy server back to the client. The client now waits to be redirected once the SAML handshake concludes.
Request debugId= 18: The SAMLRequest is POSTed to the SSOCircle SAML endpoint
ResponsedebugId= 18: A 500 Internal Server Error response from SSOCircle plus an HTML error page payload.
Concerning Edit2: A self signed certificate is sufficient for SSOCircle as long as it was included into the service provider's metadata.
Concerning Edit3: Please move the signature element right after the issuer element. The request must comply to the schema:
<sequence>
<element ref="saml:Issuer" minOccurs="0"/>
<element ref="ds:Signature" minOccurs="0"/>
<element ref="samlp:Extensions" minOccurs="0"/>
</sequence>

Azure: Failed to send bytes to XContainer wad-tracefiles

For some reason I get errors while using Diagnostics in Azure. The code of my (WCF) WebRole is:
public override bool OnStart()
{
// To enable the AzureLocalStorageTraceListner, uncomment relevent section in the web.config
DiagnosticMonitorConfiguration diagnosticConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();
diagnosticConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);
diagnosticConfig.Directories.DataSources.Add(AzureLocalStorageTraceListener.GetLogDirectory());
diagnosticConfig.Directories.BufferQuotaInMB = 256;
// Start diagnostics
DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", diagnosticConfig);
// Write trace line
Trace.WriteLine("CUSTUM TRACE MESSAGE");
// Start instance
return base.OnStart();
}
My Web.config file looks like this:
<?xml version="1.0"?>
<configuration>
<configSections>
</configSections>
<system.diagnostics>
<sharedListeners>
<add name="AzureLocalStorage" type="WCFServiceWebRole1.AzureLocalStorageTraceListener, WCFServiceWebRole1"/>
</sharedListeners>
<sources>
<source name="System.ServiceModel" switchValue="Verbose, ActivityTracing">
<listeners>
<add name="AzureLocalStorage"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
<listeners>
<add name="AzureLocalStorage"/>
</listeners>
</source>
</sources>
<trace autoflush="true">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
</listeners>
</trace>
</system.diagnostics>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
In the Compute Emulator I see the following error:
[MonAgentHost] Output: Monitoring Agent Started
[Diagnostics]: Starting configuration channel polling
[MonAgentHost] Error: MA EVENT: 2012-06-06T10:01:20.111Z
[MonAgentHost] Error: 2
[MonAgentHost] Error: 6396
[MonAgentHost] Error: 6624
[MonAgentHost] Error: NetTransport
[MonAgentHost] Error: 0
[MonAgentHost] Error: x:\btsdx\215\services\monitoring\shared\nettransport\src\xblobconnection.cpp
[MonAgentHost] Error: XBlobConnection::PutBytesXBlob
[MonAgentHost] Error: 1621
[MonAgentHost] Error: ffffffff80050023
[MonAgentHost] Error: 0
[MonAgentHost] Error:
[MonAgentHost] Error: Failed to send bytes to XContainer wad-tracefiles
This error repeats several times. The "wad-tracefiles" container is added by the following code in the AzureLocalStorageTraceListener class:
public static DirectoryConfiguration GetLogDirectory()
{
DirectoryConfiguration directory = new DirectoryConfiguration();
directory.Container = "wad-tracefiles";
directory.DirectoryQuotaInMB = 10;
directory.Path = RoleEnvironment.GetLocalResource("WCFServiceWebRole1.svclog").RootPath;
return directory;
}
Why does writing trace messages fails in this scenario? When I look in my Storage with the Azure Storage Explorer the only table I see is the WADDirectoriesTable and not the the WADLogsTable. The "wad-tracefiles" blob does get created but that is not the place where I should find the Trace messages from my code.
Anyone, any idea? Any help is appreciated!
Your first problem is that you haven't used SetCurrentConfiguration() with your GetDefaultInitialConfiguration() to finally save the transfer time and log level. You must use the set of these API as below:
GetDefaultInitialConfiguration()
SetCurrentConfiguration()
OR
GetCurrentConfiguration()
SetCurrentConfiguration()
Because of it the following line based configuration will not be saved in Diagnostics configuration:
diagnosticConfig.Directories.DataSources.Add(AzureLocalStorageTraceListener.GetLogDirectory());
Use above suggestion and then see what happens.
I would also suggest to just create a very simple web or worker role hello world sample and add general TRACE Message by enabling Azure Diagnostics to see if that give you any error. This will prove if you have any issue with your SDK installation or Azure Storage Emulator or not as well.
Thank you for your reply! The project I am using is a really simple WebRole with only one trace message so I can not strip any code out.
I tried your suggestion and you are right, I do not get any error messages anymore with the following code:
public override bool OnStart()
{
setDiagnostics();
Trace.WriteLine("CUSTUM TRACE MESSAGE");
// Start instance
return base.OnStart();
}
private void setDiagnostics()
{
// Get diagnostics connectionstring
string wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(wadConnectionString));
// Get the diagnostics configuration of the deployment and its role instances that are currently running
DeploymentDiagnosticManager deploymentDiagnosticManager = new DeploymentDiagnosticManager(cloudStorageAccount, RoleEnvironment.DeploymentId);
RoleInstanceDiagnosticManager roleInstanceDiagnosticManager = cloudStorageAccount.CreateRoleInstanceDiagnosticManager(
RoleEnvironment.DeploymentId,
RoleEnvironment.CurrentRoleInstance.Role.Name,
RoleEnvironment.CurrentRoleInstance.Id);
// Load diagnostics configuration
DiagnosticMonitorConfiguration diagConfig = roleInstanceDiagnosticManager.GetCurrentConfiguration();
// Get the default value if there is no config yet
if (diagConfig == null)
diagConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();
// Enable EventLogs
diagConfig.WindowsEventLog.DataSources.Add("Application!*");
diagConfig.WindowsEventLog.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);
diagConfig.WindowsEventLog.BufferQuotaInMB = 128;
// Failed Request Logs
diagConfig.Directories.DataSources.Add(AzureLocalStorageTraceListener.GetLogDirectory());
diagConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);
diagConfig.Directories.BufferQuotaInMB = 128;
// Crash Dumps
CrashDumps.EnableCollection(true);
// Set new configuration
roleInstanceDiagnosticManager.SetCurrentConfiguration(diagConfig);
// Start the DiagnosticMonitor
DiagnosticMonitor.Start(wadConnectionString, diagConfig);
}
When I look in which tables are present in the Azure Storage Explorer I only see the "WADDirectoriesTable" and the "WADWindowsEventLogsTable". Trace messages should come in the "WADLogsTable" right? So I see the Trace message in the Compute Emulator but I do not see them in my storage... any ideas why?

Resources