ADFS 2.0 claim rules for consuming SAML2 assertions - saml-2.0

I am using ADFS 2.0 as a service provider and Shibboleth as an IDP which issues SAML2 attributes in the form of:
<saml2:AttributeStatement>
<saml2:Attribute FriendlyName="nameidentifier" Name="nameidentifier" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">testuser</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
does anyone know how to setup a claim rule to consume this attribute?
I have tried the following but it didn't work:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] == "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"] => issue(claim = c);
What am I doing wrong?
Thanks

Should just be
c:[Type == "nameidentifier"]
=> issue(claims = c)
The FriendlyName and NameFormat are accessible from properties, like you have in your rule. You don't need to include them though unless you want to narrow the scope of your rule (in which case, please update your question with that requirement).
HTH!

Related

SAML error "SignatureStatus: NOT_PRESENT"

UPDATE
I found that if I add a trusted cert to SPOptions.ServiceCertificates and set SPOptions.AuthenticateRequestSigningBehavior = Sustainsys.Saml2.Configuration.SigningBehavior.IfIdpWantAuthnRequestsSigned; and set IdentityProvider.WantAuthnRequestsSigned = true, the signature element is included.
Original Question:
Having troubles connecting to an IDP with the following AuthnRequest:
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="idf299bf8aa08542d193e022cb047e5ecc" Version="2.0" IssueInstant="2019-07-23T00:10:13Z" Destination="https://example-idp.com" AssertionConsumerServiceURL="https://example-sp.com/Acs">
<saml2:Issuer>https://example-sp.com</saml2:Issuer>
</saml2p:AuthnRequest>
The IDP says: "SignatureStatus: NOT_PRESENT". I'm guessing that means that the authnrequest should have a <ds:Signature section? If so, how do I configure Sustainsys.Saml2.AspNetCore2 to include it?
The metadata xml I received from the idp contains a <ds:Signature section, but looking at the source code for Sustainsys.Saml2.AspNetCore2, it looks like that part of the metadata gets ignored when deserializing?
I'm not very familiar with the internals of SAML, so sorry if this is a silly question.
You'll want to generate a self-signed .pfx file that contains both your public cert and private key. We use azure key vault, but you could also use openssl. Lots of resources that explain how to generate one of those and load it into a c# X509Certificate2 instance.
Once you have an instance of X509Certificate2, set options.SPOptions.AuthenticateRequestSigningBehavior = Sustainsys.Saml2.Configuration.SigningBehavior.IfIdpWantAuthnRequestsSigned;
And set IdentityProvider.WantAuthnRequestsSigned = true.
And then add the X509Certificate2 instance like so: options.SPOptions.ServiceCertificates.Add(myX509Certificate2);
Then run your app and start the SAML SSO process. You can use hookbin or the like to see what it sends in the AuthnRequest for SAMLRequest. You can extract the xml from that by url decoding it and then base64 decoding it like so in javascript, for instance to confirm signature xml is set and correct: atob(decodeURIComponent(samlRequestValue))

How to do CAS 5.3.2 authenticate with AD using userPassword

I have a Active Directory storage which hold password in field userPassword.
I used CAS 5.3.2 to do authenticate with AD, here's my configs:
# Interesting part for Active Directory:
cas.authn.ldap[0].type=AD
cas.authn.ldap[0].ldapUrl=ldap://85.2.58.119:389
cas.authn.ldap[0].useSsl=false
cas.authn.ldap[0].useStartTls=false
cas.authn.ldap[0].connectTimeout=5000
cas.authn.ldap[0].baseDn=OU=User Account,OU=CAS,DC=liferayadmin,DC=net
cas.authn.ldap[0].userFilter=cn={user}
cas.authn.ldap[0].subtreeSearch=true
# AD manager user like someone#company.com
cas.authn.ldap[0].bindDn=cn=casAdmin,OU=User Account,OU=CAS,cn=users,dc=liferayadmin,dc=net
cas.authn.ldap[0].bindCredential=password
cas.authn.ldap[0].dnFormat=%s#liferayadmin.net
cas.authn.ldap[0].principalAttributeId=cn
cas.authn.ldap[0].principalAttributePassword=
cas.authn.ldap[0].principalAttributeList=sAMAccountName,sn,cn,givenName,displayName
cas.authn.ldap[0].failFast=false
# Default values:
cas.authn.ldap[0].minPoolSize=3
cas.authn.ldap[0].maxPoolSize=10
cas.authn.ldap[0].validateOnCheckout=true
cas.authn.ldap[0].validatePeriodically=true
cas.authn.ldap[0].validatePeriod=600
cas.authn.ldap[0].idleTime=5000
cas.authn.ldap[0].prunePeriod=5000
cas.authn.ldap[0].blockWaitTime=5000
It return failed authentication. Someone said that AD use another field to check password, but I can use this field 'userPassword' only.
How can I authenticate with AD using this field?
How can I check what is root cause of fail autheticate?(cannot connect AD / wrong bindCredential / other exceptions ...).
And if possible, pls look at my configs and find if I have some mistake.
Thanks!

Getting Claims from ADFS 3.0 and Displaying To Shibboleth 2.6 Service Provider (SP) in SAML 2.0

I'm trying to configure Windows Server 2012 r2 ADFS 3.0 to send the NameID to Shibboleth 2.6 SAML 2.0 SP, but I keep on getting these errors:
2016-11-15 10:07:07 WARN Shibboleth.AttributeResolver.Query [1]: can't attempt attribute query, either no NameID or no metadata to use
2016-11-15 10:07:07 INFO Shibboleth.SessionCache [1]: new session created: ID (_7e425978e43bc32c86393f518b26eb3e) IdP (https://c-adfs01.contoso.com/FederationMetadata/2007-06/FederationMetadata.xml) Protocol(urn:oasis:names:tc:SAML:2.0:protocol) Address (192.168.50.131)
I understand that this has something to do about passing the NameID attribute from the ADFS IDP and displaying the nameID in Shibboleth SAML 2.0 SP.
I've also read that you need to set a rule in ADFS IDP to pass the Email Address, and transform the Email address to become a NameID. I have done that, and have these rules:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
However, I have observed that the configuration seems compatible only with SAML 1.0, but not 2.0 (maybe).
So, I went on by adding the name attributes. I tried transient, persistent, and emailAddress, and trying both SAML 1.0 and SAML 2.0 configurations.
<Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" id="NameID"/>
<Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" id="NameID"/>
<Attribute name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" id="NameID"/>
Question:
So, what is the proper way of configuring ADFS IDP to send the NameID to the Shibboleth SP and display the Session attribute when going to my application Session page?
Specifically, what is the proper output for Claim Rules that I should expect? and how should the XML configuration for Shibboleth attribute-map.xml look like?
https://c-app01.contoso.com/Shibboleth.sso/Session
Solution:
The solution is to create two rules inside "Issuance Transform Rules" tab in the Relying Party. Here are the Rules to be set:
Add a Rule to Send LDAP Attributes as Claims
Add a Rule to Transform an Incoming Claim
Also, make sure that Permit Access to All Users is inside Issuance Authorization Rules tab.
Instructions:
Add a Rule to Send LDAP Attributes as Claims:
Claim Rule Name: Email
Attribute Store: Active Directory
Mapping of LDAP: E-mail-Address to E-mail Address
This will map the Email address.
Add a rule to Transform An Incoming Claim:
Claim rule name: EmailToNameID
Incoming Claim Type: E-Mail Address
Outgoing Claim Type: Name ID
Outgoing Name ID Format: Email
Make sure "Pass Through Claim Values" is selected.
The setting above for "Transform An Incoming Claim" will give you the following claim rule:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
After that, you may configure the attribute-map.xml like so:
<Attribute name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" id="Email"/>
My Mistake:
I found out that every setting in my Claims Rules is correct, except that the rules for Email and EmailToNameID should be under the Issuance Transform Rules Tab of the Relying Party.

Add an ID Attribute for Element EncryptedAssertion or EncryptedData in RSTR from PingFederate

I'm using Apache CXF 3.1.5 to work with PingFederate 7.2.
In PingFederate, I create a WS-Trust SP connection, if the SAML Assertion is not encrypted. it works well.
If the SAML Assertion is encrypted, then it doesn't work, because CXF requires an Id Attribute for Element EncryptedAssertion or EncryptedData in RSTR from PingFederate. While, PingFederate doesn't provide such an Id attribute.
so I have two questions.
Why does CXF require an Id attribute(method createSecurityToken in class AbstractSTSClient)? It seems the standard specifications say that the Id attribute is optional.
How can I add an Id attribute for Element EncryptedAssertion or EncryptedData in PingFederate? or is there something else I can do?
Thanks a lot!
RSTR from PingFederate
I loosened the requirement for an ID in CXF.
Fixed here: https://issues.apache.org/jira/browse/CXF-7003

WS-Policy X509Token with Supporting Tokens

I have a WSDL that contains WSPolicy, the policy defined uses supporting tokens and with-in supporting tokens it uses X509 Tokens. Below is a snippet of the WSDL having the policy
<wsp:Policy xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wssutil="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wssutil:Id="MyPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssX509V3Token11/>
</wsp:Policy>
</sp:X509Token>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Now when I generate my client (using Apache CXF), consume any web service operation, I don't see the wssec security header getting added to the SOAP header. As a result, the SOAP service throws error as the Policy Validation Interceptor fails.
I have done a lot of search and have not found any sample / example using this kind of policy, supporting tokens have been used along with Assymetric / Symmetric bindings.
Want to know if the policy defined is correct, if yes, then what will be the client code to access this service.
Just to add, when I put below interceptor into the client code, the security header gets added (with a Binary Security Token and Signature), however, the service still fails (with Policy Verification Interceptor)
Client client = ClientProxy.getClient(port);
client.getInInterceptors().add(new LoggingInInterceptor());
client.getOutInterceptors().add(new LoggingOutInterceptor());
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.ACTION, "Signature");
outProps.put(WSHandlerConstants.USER, "myclientkey");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
ClientKeystorePasswordCallback.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "clientKeystore.properties");
outProps.put(ConfigurationConstants.SIG_KEY_ID, "DirectReference");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
client.getOutInterceptors().add(wssOut);
Below is the error stack trace
Caused by: org.apache.cxf.binding.soap.SoapFault: These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SupportingTokens
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:86)
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:52)
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:41)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:113)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:798)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1638)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1527)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1330)
at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:56)
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:215)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:638)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:138)
... 2 more
Any help will be much appreciated!! I am stuck with this issue since 2 days.
Using a BinarySecurityToken as a SupportingToken with no security binding won't work with CXF. You need to specify a security binding in order to sign the request as well.

Resources