I need to validate a SAML assertion of this kind:
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="Assertion-uuide824d44-0134-14b1-8e70-f85c710cb043" IssueInstant="2011-12-05T13:55:47Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">MPS</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="uuide824d48-0134-18fe-b37b-f85c710cb043">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#Assertion-uuide824d44-0134-14b1-8e70-f85c710cb043">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<xc14n:InclusiveNamespaces xmlns:xc14n="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs saml xsi"></xc14n:InclusiveNamespaces>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>p02xKMDUYCR5xpppYUOQgsGBR5c=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>R9YHo8TK/wYkGkTP3QrnnM8U6TKf9vu+ElpRjDPgpg4O88oARZSb9OhlVn2sXJGEaQ5i0ORrofbKwOI+D/jFgz3Hz/g/h4yt2aqIFxLpOTFb448bDvFsHHWAoWc0DUPYf1AjW7Peu1ICSCdR3EaVLqtgdsUsVWoA7oXbWyAyVLM=</ds:SignatureValue>
<ds:KeyInfo>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>iZ0D1X6rk8+ZwNBTVZt7C85m421a8A52Ksjw40t+jNvbLYDp/W66AMMYD7rB5qgniZ5K1p9W8ivM9WbPxc2u/60tFPg0e/Q/r/fxegW1K1umnay+5MaUvN3p4XUCRrfg79OvurvXQ7GZa1/wOp5vBIdXzg6i9CVAqL29JGi6GYU=</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:ibm:names:ITFIM:5.1:accessmanager">J006068</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"></saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2011-12-05T13:45:47Z" NotOnOrAfter="2011-12-05T14:05:47Z">
<saml:AudienceRestriction>
<saml:AttributeValue xsi:type="xs:string">1030</saml>
I did not find a library on CPAN that can take the SAML as argument and can validate it.
Someone can help me with how to reach my goal?
Ok, better late than never... how to use it...
When you say 'validate' I'm not sure if you mean 'check the assertion', or 'verify the signature'.
my $assertion = Net::SAML2::Protocol::Assertion->new_from_xml(
xml => decode_base64($saml_response)
);
then you just check the validity of the Assertion object created via the accessors. I'm assuming you understand SAML semantics.
To verify the signature, you need access to the private key:
my $sig = Net::SAML2::XML::Sig->new( { key =>'/private.key' } );
$sig->verify( $xml );
See the XML::Sig perldoc for variations on the source of the key (x509, certs).
Note that Net::SAML2 doesn't cover encrypted SAML assertions () but you didn't ask about that.
The Net::SAML2 CPAN module would help you out here
http://metacpan.org/pod/Net::SAML2
Related
I tried to call EnhancedVehBookRQ API with CERT ENV
This is my request and response
REQUEST:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sec="http://schemas.xmlsoap.org/ws/2002/12/secext" >
<soapenv:Header>
<Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<BinarySecurityToken>
token
</BinarySecurityToken>
</Security>
<MessageHeader xmlns="http://www.ebxml.org/namespaces/messageHeader">
<From>
<PartyId type="urn:x12.org:IO5:01">from</PartyId>
</From>
<To>
<PartyId type="urn:x12.org:IO5:01">to</PartyId>
</To>
<CPAId>hiddendata
</CPAId>
<ConversationId>hiddendata</ConversationId>
<Action>EnhancedVehBookRQ</Action>
<MessageData>
<MessageId>1001</MessageId>
<Timestamp>2021-08-18T10:00:01</Timestamp>
<!--Optional:-->
<TimeToLive>2021-08-19T10:00:01</TimeToLive>
<!--Optional:-->
<Timeout>0</Timeout>
</MessageData>
</MessageHeader>
</soapenv:Header>
<soapenv:Body>
<EnhancedVehBookRQ xmlns="http://services.sabre.com/sp/enhanced/veh/book/v1" version="1.0.0">
<VehBook>
<BookingInfo >
<BookingKey>23accd05-4770-4d1c-a286-ab0e6f360fc5
</BookingKey>
</BookingInfo>
<Customer NameNumber="1.1">
<Address>
<CityName>DALLAS</CityName>
<CountryCode>US</CountryCode>
<PostalCode>12345</PostalCode>
<StateCountyProv StateCode="TX" />
<StreetNmbr>1234 TEST ADDRESS</StreetNmbr>
</Address>
</Customer>
<RentalPaymentPrefs>
<GuaranteePrepaid Type="GUARANTEE">
<PaymentCard>
<CardCode>DC</CardCode>
<CardNumber>311234567685619</CardNumber>
<ExpiryMonth>12</ExpiryMonth>
<ExpiryYear>2022</ExpiryYear>
<FullCardHolderName>
<LastName>Monster</LastName>
</FullCardHolderName>
</PaymentCard>
</GuaranteePrepaid>
</RentalPaymentPrefs>
<VehRentalCore Quantity="1" />
</VehBook>
</EnhancedVehBookRQ>
</soapenv:Body>
</soapenv:Envelope>
I could not move ahead with car booking, getting errors like this
<Message code="ERR.SP.INTERNAL_ERROR">TravelItineraryReadRQ: After maximum retry count it was not possible to successfully execute target service</Message>
Can anybody please confirm whether SOAP requst is proper or not or I am missing something from my side
Yes, before running EnhancedVehBookRQ API you need to run PassengerDetailsRQ with TravelIntinerary details in it. On the success of this API use the response details for the request of this API and then run it
How to tell from a SAML response if it's a SP initiated SSO or an IDP initiated SSO? Is there an attribute which tells me who initiated the SSO?
For example in this StackOverflow Question: Differences between SP initiated SSO and IDP initiated SSO they discuss the differences but they don't talk about the XML level itself...
The SAML response looks like this:
<samlp:Response xmlns:samlp ="urn:oasis:names:tc:SAML:2 .0 :protocol" Destination ="http: //my - sp . com /sso /saml" ID ="_45307c23795120" IssueInstant ="2014 -03 -07 T08:30:00Z" Version ="2.0">
<saml:Issuer xmlns:saml ="urn:oasis:names:tc:SAML:2 .0 :assertion">http: //my - idp . com </saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value ="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion ID ="ebe015e8be2a" IssueInstant="2014-03-07T08:30:00Z" Version ="2.0">
<saml:Issuer> http: //my - idp . com </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 ="# ebe015e8be2a">
<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> ... </ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue> ... </ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate> ... </ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format ="urn:oasis:names:tc:SAML:2 .0 :nameid - format:persistent" NameQualifier ="http: //my - idp . com" SPNameQualifier ="http: //my - sp . com /sso /saml"> NDSUser </saml:NameID>
<saml:SubjectConfirmation Method ="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter ="2014 -03 -07 T10:45:00Z" Recipient ="http: //my - sp . com /sso /saml"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore ="2014 -03 -07 T08:29:00Z" NotOnOrAfter="2014 -03 -07 T10:46:00Z">
<saml:AudienceRestriction>
<saml:Audience> http: //my - sp . com /sso /saml </saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014 -03 -07 T08:25:56Z" SessionIndex="f7810a8c86a6">
<saml:AuthnContext>
<saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2 .0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name ="FEDERATION_ID">
<saml:AttributeValue xmlns:xs ="http: //www . w3 . org /2001/XMLSchema" xmlns:xsi ="http: //www . w3 . org /2001/XMLSchema - instance" xsi:type ="xs:string"> NDS </saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
SAML response from SP-initiated SSO flow has 'InResponseTo' attribute.
I am using a Mongo DB connector to insert data into Mongo Instance located in mLab.
I am sure I am using the correct credentials since these credentials are working when I am using them through a Java code.
But here using the Mongo DB connector constantly throws me an error as can be seen below.
org.mule.api.ConnectionException: Couldn't connect with the given
credentials org.mule.api.ConnectionException: Couldn't connect with
the given credentials at
org.mule.module.mongo.MongoCloudConnector.getDatabase(MongoCloudConnector.java:1304)
at
org.mule.module.mongo.MongoCloudConnector.connect(MongoCloudConnector.java:1173)
at
org.mule.module.mongo.connectivity.MongoCloudConnectorConnectionFactory.makeObject(MongoCloudConnectorConnectionFactory.java:56)
at
org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:1220)
at
org.mule.module.mongo.connectivity.MongoCloudConnectorConnectionManager.acquireConnection(MongoCloudConnectorConnectionManager.java:361)
at
org.mule.module.mongo.connectivity.MongoCloudConnectorConnectionManager.test(MongoCloudConnectorConnectionManager.java:444)
at
org.mule.tooling.metadata.api.utils.ConnectionTester.internalTestConnection(ConnectionTester.java:88)
at
org.mule.tooling.metadata.api.utils.ConnectionTester.testConnectionFor(ConnectionTester.java:113)
at
Is there something that I am missing here?
Below is the XML :
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:dw="http://www.mulesoft.org/schema/mule/ee/dw" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo" 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.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/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/dw http://www.mulesoft.org/schema/mule/ee/dw/current/dw.xsd
http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/current/mule-mongo.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="developers.zomato.com" port="80" doc:name="HTTP Request Configuration"/>
<http:request-config name="HTTP_Request_Configuration1" host="api.mlab.com" port="80" doc:name="HTTP Request Configuration"/>
<mongo:config name="Mongo_DB" password="XXXXX" database="restaurant_data" host="ds241039.mlab.com" port="41039" doc:name="Mongo DB" username="XxXx"/>
<flow name="rest-webservice-applicationFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/rest" allowedMethods="GET" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="api/v2.1/search" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="entity_id" value="1"/>
<http:query-param paramName="entity_type" value="city"/>
<http:header headerName="user-key" value="XXXXXXXXX"/>
</http:request-builder>
</http:request>
<dw:transform-message doc:name="Transform Message" metadata:id="13f7b603-ac1e-45b4-9950-32c39a20ee36">
<dw:input-payload mimeType="application/json"/>
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
results_found: payload.results_found,
results_start: payload.results_start,
results_shown: payload.results_shown,
restaurants: payload.restaurants map ((restaurant , indexOfRestaurant) -> {
restaurant: {
R: restaurant.restaurant.R,
id: restaurant.restaurant.id,
name: restaurant.restaurant.name,
url: restaurant.restaurant.url,
location: restaurant.restaurant.location,
switch_to_order_menu: restaurant.restaurant.switch_to_order_menu,
cuisines: restaurant.restaurant.cuisines,
average_cost_for_two: restaurant.restaurant.average_cost_for_two,
price_range: restaurant.restaurant.price_range,
currency: restaurant.restaurant.currency,
offers: restaurant.restaurant.offers map ((offer , indexOfOffer) -> offer),
thumb: restaurant.restaurant.thumb,
user_rating: restaurant.restaurant.user_rating,
photos_url: restaurant.restaurant.photos_url,
menu_url: restaurant.restaurant.menu_url,
featured_image: restaurant.restaurant.featured_image,
has_online_delivery: restaurant.restaurant.has_online_delivery,
is_delivering_now: restaurant.restaurant.is_delivering_now,
deeplink: restaurant.restaurant.deeplink,
has_table_booking: restaurant.restaurant.has_table_booking,
events_url: restaurant.restaurant.events_url
}
})
}]]></dw:set-payload>
</dw:transform-message>
<mongo:json-to-dbobject doc:name="Mongo DB"/>
<mongo:insert-object config-ref="Mongo_DB" doc:name="Mongo DB" collection="restaurant"/>
</flow>
</mule>
The MongoDB connector uses the deprecated MONGODB-CR authentication mechanism, MLab is expecting the SCRAM-SHA-1 mechanism.
The SCRAM-SHA-1 mechanism is available in the enterprise version of Mulesoft ESB.
The connection URI configuration is available on version 4.2.0 and above. This is how you configure it:
Add the connector to pom.xml:
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-mongo-connector</artifactId>
<version>4.2.0</version>
</dependency>
Configure a connection in your flow:
<mongo:config-connection-string name="MongoDB_Config"
connectionString="mongodb://jdoe:myPass#localhost:27017?authMechanism=SCRAM-SHA-1"/>
Wildfly10
CXF 3.1.6
SOAP Webservices
WSDL configuration of security policy is:
<wsp:Policy wsu:Id="UsernameTransportPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:TextPassword />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Handler configuration is:
<jaxws-config xmlns="urn:jboss:jbossws-jaxws-config:4.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="urn:jboss:jbossws-jaxws-config:4.0 schema/jbossws-jaxws-config_4_0.xsd">
<endpoint-config>
<config-name>Custom-JAXWS-WS-SecurityEndpoint</config-name>
<property>
<property-name>ws-security.validate.token</property-name>
<property-value>true</property-value>
</property>
<property>
<property-name>ws-security.callback-handler</property-name>
<property-value>com.xxx.xxxx.security.ServerPasswordHandler
</property-value>
</property>
</endpoint-config>
</jaxws-config>
Handler code:
public class ServerPasswordHandler implements CallbackHandler
{
private static final Logger logger = Logger.getInstance(ServerPasswordHandler.class);
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException
{
logger.debug("begin handle");
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
String userId = "wsuser";
String password = "wspassword";
logger.debug("userId is["+userId+"]");
if (userId.equals(pc.getIdentifier()))
{
pc.setPassword(password);
logger.info("User ["+userId+"] is familiar.");
}
else
logger.error("Unknown user ["+userId+"]");
logger.debug("end handle");
}
}
Sending xml request as:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ser="http://service.dms.ctl.com/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soap:mustUnderstand='true'
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 wsu:Id='UsernameToken-3DAJDJSKJDHFJASDKJFKJ234JL2K3H2K3J42'>
<wsse:Username>wsuser</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>wspassword</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
.....
</soapenv:Body>
I am getting following error:
15:22:54,541 DEBUG [c.c.i.s.MessageInterceptor] handleMessage
15:22:56,684 DEBUG [c.c.i.s.ServerPasswordHandler] begin handle
15:22:56,685 DEBUG [c.c.i.s.ServerPasswordHandler] userId is[wsuser]
15:22:56,685 INFO [c.c.i.s.ServerPasswordHandler] User [wsuser] is familiar.
15:22:56,685 DEBUG [c.c.i.s.ServerPasswordHandler] end handle
15:23:18,609 SEVERE [o.a.c.w.p.PolicyVerificationInInterceptor] Inbound policy verification failed: These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}TextPassword
15:23:18,609 WARNING [o.a.c.p.PhaseInterceptorChain] Interceptor for {http://service.xxx.xxx.com/}Adapter#{http://service.dms.ctl.com/}findAvailableCustomers has thrown exception, unwinding now: org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}TextPassword
at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179)
at org.apache.cxf.ws.policy.PolicyVerificationInInterceptor.handle(PolicyVerificationInInterceptor.java:102)
at org.apache.cxf.ws.policy.AbstractPolicyInterceptor.handleMessage(AbstractPolicyInterceptor.java:44)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:254)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:108)
at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:134)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:88)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:299)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:218)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:136)
at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
Looking at the source code, i see the exception being thrown at following :
try {
//Exception here
List<List<Assertion>> usedAlternatives = aim.checkEffectivePolicy(effectivePolicy.getPolicy());
if (usedAlternatives != null && !usedAlternatives.isEmpty() && message.getExchange() != null) {
message.getExchange().put("ws-policy.validated.alternatives", usedAlternatives);
}
} catch (PolicyException ex) {
LOG.log(Level.SEVERE, "Inbound policy verification failed: " + ex.getMessage());
//To check if there is ws addressing policy violation and throw WSA specific
//exception to pass jaxws2.2 tests
if (ex.getMessage().indexOf("Addressing") > -1) {
throw new Fault("A required header representing a Message Addressing Property "
+ "is not present", LOG)
.setFaultCode(new QName("http://www.w3.org/2005/08/addressing",
"MessageAddressingHeaderRequired"));
}
throw ex;
EDIT: Fixed minor debug message
I was able to fix this with information from various websites. First off, as mentioned in oasis-open, i removed following element as passwords are mandatory.
<wsp:Policy>
<sp:TextPassword />
</wsp:Policy>
But due to a bug that was mentioned cxf issue, UsernameToken needed a policy element so workaround was to keep an empty policy under usernametoken
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
That fixed it.
"sp:TextPassword" is not a valid policy.
We have a customer trying to use ADFS to SSO on to our web application. We are using the ComponentSpace SAML 2.0 library. The assertion being sent to us looks like:
<Assertion ID="_b8a24809-ab6b-4acd-ad6a-8bcb97bb1889" IssueInstant="2012-05-24T13:30:33.917Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>http://example.com/adfs/services/trust</Issuer>
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">mail#example.com</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData NotOnOrAfter="2012-05-24T13:35:33.920Z" Recipient="https://example.com/default.aspx" />
</SubjectConfirmation>
</Subject>
<Conditions NotBefore="2012-05-24T13:30:33.907Z" NotOnOrAfter="2012-05-24T14:30:33.907Z">
<AudienceRestriction>
<Audience>https://example.com</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>mail#example.com</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2012-05-24T13:30:33.756Z" SessionIndex="_b8a24809-ab6b-4acd-ad6a-8bcb97bb1889">
<AuthnContext>
<AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
The ComponentSpace library is pulling the full SamlResponse from the HTTP post but it reports no Assertions (ie samlResponse.GetAssertions().Count == 0). If I use the ComponentSpace examples it works but I notice all of the elements I build with the ComponentSpace library are prefixed with "saml:" (as I believe it should be).
Should the ComponentSpace library be able to find the Assertion without the saml: prefix or is there a way to configure ADFS to send it correctly?
A correct SAML response should contain namespace-qualified elements
<saml2p:Response Destination="https://www.google.com/a/squaresquare.biz/acs" IssueInstant="2010-08-04T17:47:20.956Z" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" InResponseTo="djfnhepndikoonjjkeomgplmkjofobhdbdieihpa" Version="2.0" ID="_bd24b4a3514fd93800d2a43cafc98edb">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://my.ssodemo.url.demo.google.com/idp/shibboleth</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:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#_bd24b4a3514fd93800d2a43cafc98edb">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
<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="dssaml2saml2p"></ec:InclusiveNamespaces>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>m/lUCS3nvfGuSJFKAtIz+ZrfxTU=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>PLdYgU9u5KirVrMHNSwYvk6fQ401dMbpuiDXpapKf0eOKC6pN3g7tnTEzvfOaXhkDNXVmGN+lXQ6iUDppWpdO2MbvPVZabOBPU1aAO+CWI53ciC0rYsxpFzQLLMC/7x9Wk7VFFmYEecxAJV+lTWvp8ZKXvwqZbhiTO/23EC0xconGhnwSvKjJWQuLnMMaFWSjDFYyzgsp34cR7aX/eqhhJyA/rr2uFdmgEdagAl+/17ppgHgthgK+PJtX16AALtsoXonv6uybRCX/YiDRvM1VsdwusVq5tXh9V+bTMZcgi/3Eh+Em/OZp0En8pqOngvL19U4LfqG0yJZjoDGkpHuhA==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDgjCCAmqgAwIBAgIVAKgIqbzZl7+0p2qjxJFVJs3DE/jxMA0GCSqGSIb3DQEBBQUAMDAxLjAsBgNVBAMTJWh0dHA6Ly93cGgtdWJpcTI3LmhvdC5jb3JwLmdvb2dsZS5jb20wHhcNMTAwNzIxMTcxNTA5WhcNMzAwNzIxMTcxNTA5WjAwMS4wLAYDVQQDEyVodHRwOi8vd3BoLXViaXEyNy5ob3QuY29ycC5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAioQsJycRmjPjB2xlH0iSGn14lNbO/jIVgiGIlzZwlPkH1s2TTdwoTKKQBSe2s8AnJ4LliXlne/qWun3peYht0+RhejtB20L+Bw/I+iKQBGpHzgIKdkPGZnemWl9KqWQ/ZYKnY2x6qMEBmhUfYZcawzs26em5a+iaYlrTJNVEZ+QwWvg2/EOJvJNyBkSfXyxia5eAHV38Uy7xn0G5Zc9ge4ckCYj6b8a/UxpPJM61KztzY5coDwReQsDBq+DciGALJPbFk4783TW...etc.etc</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></saml2p:StatusCode>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" IssueInstant="2010-08-04T17:47:20.956Z" ID="_73fe28bcbb68e93df954d8e2f25097b1">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://my.ssodemo.url.demo.google.com/idp/shibboleth</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">my_username</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData NotOnOrAfter="2010-08-04T17:52:20.956Z" InResponseTo="djfnhepndikoonjjkeomgplmkjofobhdbdieihpa" Recipient="https://www.google.com/a/squaresquare.biz/acs" Address="172.24.6.38"></saml2:SubjectConfirmationData>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotOnOrAfter="2010-08-04T17:52:20.956Z" NotBefore="2010-08-04T17:47:20.956Z">
<saml2:AudienceRestriction>
<saml2:Audience>google.com</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement SessionIndex="f306dd2bff4e9b3ba9218bd70fbaa87404d38a4c79547ac1edc9436a9f222213" AuthnInstant="2010-08-04T17:47:20.953Z">
<saml2:SubjectLocality Address="172.24.6.38"></saml2:SubjectLocality>
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>
Namespace qualifications are optional.
It turns out that the above XML is valid (ADFS adds the namespace to the overall XML but not each element). The problem was that the ComponentSpace library has different methods for getting Signed or Encrypted Assertions and I was just calling the generic GetAssertions. ADFS was generating signed assertions and I needed to call the other function.
Here is the code we ended up with:
IList<EncryptedAssertion> encryptedAssertions = samlResponse.GetEncryptedAssertions();
if (encryptedAssertions.Count > 0 && x509Certificate != null) {
// Decrypt the assertion
EncryptedAssertion encryptedAssertion = encryptedAssertions[0];
XmlElement decryptedElement = encryptedAssertion.DecryptToXml(x509Certificate, null);
LogMessage("Decrypted assertion: " + decryptedElement.OuterXml);
// Then verify the signature.
VerifySignature(x509Certificate, decryptedElement);
samlAssertion = new SAMLAssertion(decryptedElement);
} else {
if (samlResponse.GetSignedAssertions().Count > 0) {
// Get the signed assertion and verify the signature.
XmlElement signedAssertionElement = samlResponse.GetSignedAssertions()[0];
LogMessage("Signed assertion: " + signedAssertionElement.OuterXml);
VerifySignature(x509Certificate, signedAssertionElement);
samlAssertion = new SAMLAssertion(signedAssertionElement);
} else {
// Assertion is not encrypted or signed.
if (samlResponse.GetAssertions().Count > 0) {
samlAssertion = samlResponse.GetAssertions()[0];
LogMessage("Assertion: " + samlAssertion.ToXml().OuterXml);
} else {
LogFatalError("No assertions in response");
}
}
}