I have implemented a SAML Service Provider to support Single Sign On for an ASP.Net web portal, which is a shrink-wrap software configured on clients' sites and must be able to interact with any SAML-compliant Identity Provider.
My Assertion Consumer Service (ACS) page will accept the SAML Response through both GET and POST methods.
As I understand the SAML protocol, the SAML Request ProtocolBinding property specifies which protocols are supported for the response. Currently, my request specifies the HTTP-Redirect binding. However, I would like to declare that I support both HTTP-Redirect (GET) and HTTP-POST (POST). After searching through more SAML documentation than I care to reiterate, I am unable to find the syntax for declaring multiple supported protocol bindings (or whether it is even valid to do so).
While I could make this declaration configurable, my preference would be to declare both bindings so that the Identity Provider will work without additional configuration of my portal.
Below is a sample of my Authentication Request. Please, if anyone knows a way to declare both HTTP-Redirect AND HTTP-POST for the ProtocolBinding, I would greatly appreciate your input!
<?xml version="1.0" encoding="utf-8"?>
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="[AUTHN_ID]"
Version="2.0"
IssueInstant="[ISSUE_INSTANT]"
ProtocolBinding="urn:oasis:names.tc:SAML:2.0:bindings:HTTP-Redirect"
ProviderName="[PROVIDER_NAME]"
AssertionConsumerServiceURL="[ACS_URL]">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
PortalEntityID
</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
</samlp:AuthnRequest>
Thanks in advance to anyone who can help!
The ProtocolBinding attribute on AuthnRequest is used to specify the expected binding to be used by the IdP when sending their SAML Response XML. HTTP-Redirect isn't a valid option to use here, because of the possible length restriction on the URL querystring; a SAML Response, especially if it's signed, can be pretty lengthy. I'll quote from the SAML spec [SAMLProf]:
...the identity provider issues a <Response> message to be delivered by the user agent to the service provider. Either the HTTP POST or HTTP Artifact binding can be used to transfer the message to the service provider through the user agent. The message may indicate an error or will include (at least) an authentication assertion. The HTTP Redirect binding MUST NOT be used, as the response will typically exceed the URL length permitted by most user agents.
After considerable research, it seems that you can only declare one Protocol Binding in a single SAML request.
Related
I am attempting to implement SAML login using Spring Security 5.5.3. Unfortunately, the metadata file looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EntityDescriptor entityID="https://remoteloginsite.org/sso/authentication"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<ArtifactResolutionService index="0" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="https://remoteloginsite.org/sso/ArtifactResolver/metaAlias/authentication"/>
</IDPSSODescriptor>
</EntityDescriptor>
Unfortunately, Spring Security's SAML support bombs when attempting to read this metadata file with the following exception:
Caused by: org.springframework.security.saml2.Saml2Exception: Metadata response is missing verification certificates, necessary for verifying SAML assertions
I'm assuming that this simply means that 5.5.3 doesn't support resolving items such as <SingleLogoutService>,<SingleLoginService>, etc, so if I want to do it, I'll have to reach out to the location URL specified by the <ArtifactResolutionService> myself and use the results to manually build a RelyingPartyRegistration myself.
Question 1: Am I correct in the assumptions I've made about the steps I have to take?
Question 2: Does OpenSaml (version 3) provide any shortcuts that would make this any easier?
Thanks for any help.
Unfortunately, the version of Spring Security we used, 5.5.3, was too NEW to support artifact resolution. SAML support in Spring Security is a work in progress. We ended up not being able to use the 5.6.x releases of Spring Security because the Saml2AuthenticationToken did not implement the Serializable interface.
We manged to configure a RelyingPartyRegistration manually to make the first call to the IdP. Unfortunately, the response contained a SAML artifact ID, requiring us to make a second call. The IDP also turned around and made a GET request to us, which the SAML Authentication Processing Filter did not recognize.
So, we ended up creating a new implementation of the AbstractAuthenticationProcessingFilter specifically to accept URI of that callback. We leveraged the SOAP functionality of OpenSAML 3 to manually create an ArtifactResolve object and sent it via SOAP to the Artifact Resolution Service URL. We received back an ArtifactResponse object, which we manually processed for the information we needed, then passed that into an AuthenticationProvider to correctly tie the whole thing into the Spring Security lifecycle.
I can't really provide much of our code, but I hope this explanation helps someone in the future.
I'm writing my own codes for the OpenID Connect protocol. Basically, I intend to write my own provider and related stuff on Google App Engine's platform using Jersey and Google's datastore via Objectify library.
I'm in the middle of implementing the (access/refresh) token endpoint and there's this client authentication that I need to take care of. I'm just wondering if there are preset authentication schemes' keywords that I could send if in case the client did not have client_secret_basic set during the registration process (or whatever's set in the datastore entry.)
For a failed client authentication with the following methods, the scheme is used as response in the WWW-Authenticate header (401):
client_secret_basic: Basic,
client_secret_post: ???,
client_secret_jwt: ???,
private_key_jwt: ???,
none: obviously none.
I've looked at some open source implementations, nimbus' and OAuth-Apis', but they don't seem to handle this minor issue (they only respond with the generic error response defined in OAuth2 rfc6749#section-5.2.)
If there are no predefined keywords, then I suppose I'll have to make up my own. But it would be great if they exist.
The authoritative list for these is at IANA. There, you can find these handfuls:
Basic
Bearer
Digest
HOBA
Mutual
Negotiate
OAuth
SCRAM-SHA1
SCRAM-SHA-256
vapid
Which of these is client_secret_post, client_secret_jwt and private_key_jwt? None. You'll need to map those to one from the registered list above or return your own values. Better yet, you can submit a draft to the OAuth working group or the OpenID Foundation to get the above IANA registry updated with something that makes sense for these missing cases. Then, we can all interop :-)
I have an ASP.NET MVC application which currently allows users to connect via two ThinkTecture IDP servers. The MVC app trusts both of these IDP servers and it authenticates users perfectly.
The current setup uses the < System.IdentityModel.Services.WSFederationAuthenticationModule > and the < System.IdentityModel.Services.SessionAuthenticationModule > in the < modules > section in the web.config to handle these.
We now have a new party who want to authenticate their users by sending us a SAML v2 token, but the MVC app doesn't seem to recognise it.
I've compared the POST response from both the IDP server (SAML1) and the new login server (SAML2) and there are some subtle differences, which maybe causing problems.
The IDP server seems to use < trust:RequestedSecurityToken > attributes to wrap to < saml:Assertion >. Whereas the new client sends a POST request body containing < saml >< samlp:Response >
My questions are:
1)Is this new < samlp:Response > a SAML2P version which is not supported by Microsoft WIF? Or is it just interested in the < saml:Assertion > element?
2) Where will WIF look for the SAML token? POST Body? Authentication header (Bearer)?
3)Currently, when the user is not authenticated, it redirects them to their local IDP servers, they login and it returns the SAML response, with is then picked up. But the new client, will simply pass a request to view a page with the SAML token (true single-sign-on). I wonder if this difference is causing problems. I currently manually handle redirects to the user's local IDP, so have tried to turn this off for the new client.
EDIT
After much digging...
SAML2 Protocol is not supported by Microsoft WIF and ever likely to be.
SAML2 Protocol messages are usually as a form parameter (saml= < saml:Response>< etc... within the body of the HTTP POST. In my case it didn't use the standard parameter format of (saml=), the XML was just directly inline in the HTTP POST body.
Indeed its not officially supported but you can do something like this to make it work.
http://blogs.msdn.com/b/bradleycotier/archive/2012/10/28/saml-2-0-tokens-and-wif-bridging-the-divide.aspx
AFAIK, samlp is a protocol that is not (yet?) supported by WIF. It is a replacement for the querystring parameters used in WS-Federation. You should look for third party extensions (How should I implement SAMLP 2.0 in an ASP.NET MVC 4 service provider?). Since I haven't used any myself I cananot give further advice.
The best solution I've found is the Kentor IT - AuthServices.
It handles digitally signed SAML tokens.
Although it will not work out of the box for me, as my third party seem to be using a non-standard binding technique (rather than the standard HTTP Post or HTTP Redirect), so I will have to build my own custom-binding.
Spring SAML Extension seem to disregard the query string param configured in IDP xml. Here is the configuration
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://<provier host>/saml/?query1=xxx&query2=yyy"/>
1) When the SSO request gets redirected, SAML extension seem to strip anything after ? and send only SAMLRequest query string param.
2) Also I wanted modify query string param value based on some configuration so that I can hit environment specific endpoints for testing and development
Is there a way to intercept the redirection request before the redirection to satisfy the above needs?
The query parameters are removed by the underlaying OpenSAML library in class org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder. You can extend this class, override method buildRedirectURL and add parameters as you need to the constructed URL. Your implementation would then need to be added to bean org.springframework.security.saml.processor.HTTPRedirectDeflateBinding using its constructor which accepts instances of MessageDecoder and MessageEncoder.
Hit this exact issue with the new Google Apps SAML IDP Federated SSO.
Vladimír's suggestion above helped me solve the problem.
Here is the exact error I was getting to enable others to find the solution.
400. That’s an error.
Invalid Request, no idpId in request URL, check if SSO URL is configured properly on SP side. That’s all we know.
I have an MVC 4 application receiving SAML2 tokens from an initiating IdP. I can see the token as it arrives and I can decrypt it. However, I want to do this with WIF 3.5 and seem to be having problems with SAML Namespaces when I try to use the WSSecurityTokenSerializer as follows:
System.Xml.XmlException was unhandled by user code
HResult=-2146232000
Message=Cannot read the token from the 'Response' element with the 'urn:oasis:names:tc:SAML:2.0:protocol' namespace for BinarySecretSecurityToken, with a '' ValueType. If this element is expected to be valid, ensure that security is configured to consume tokens with the name, namespace and value type specified.
Source=System.ServiceModel
LineNumber=0
LinePosition=0
StackTrace:
at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
at System.IdentityModel.Selectors.SecurityTokenSerializer.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
at SamlHandlingTests.SamlTests.TestMethod1() in g:\Projects\mytempesub\Solution\SamlHandlingTests\SamlTests.cs:line 112
InnerException:
I have seen a post here StackOverflow question but the final resolution of doing things directly with XML doesn't suit me because I need to be able to run this up as a standard IdP-Initiated solution.
Therefore I have two questions:
Has anyone ever managed to overcome this error with WIF? (I don't need the WIF Extensions as I am only concerned with handling SAML2 tokens, not protocol.
To use WIF in an IdP-Initiated environment I understand requires no configuration, I have simply set authentication off and I check the incoming token. However, I would prefer to check the token in the full WIF pipeline but this then needs configuration. How can I configure WIF to function in this IdP-Initiated environment?
Many thanks
Brian
If you need to deserialize the token you might consider instead using Saml2SecurityTokenHandler.
I would also ask, does your scenario require you to deserialize the token yourself? WIF integrates well with ASP.NET MVC applications so you might instead rely on the WIF to do this for you. See Eugenio's answer here.