I am writing a SAML SP and can not figure out a uniform way to extract a user's username/login from the SAML response returned by the IdP. It looks like this information can be in a variety of places (NameID, Attribute) from different IdP's, and the IdP metadata does not seem to offer any hints.
Right now, I am using an extra configuration directive containing XPath for retrieving the username, but would like to eliminate this. Is this something I can specify in SP metadata?
It's unrelated to SAML Meta Data, but a proprietary configuration of your SP.
As you stated, you could either use the value of the NamedID or the value of an Attribute Statement. If your SP allows to do SSO with different IdPs this setting could be IdP-entity based. E.g. one IdP may only support the 'transient NameId Format' then you can not use the value as it's an opaque handle which must change all the time. To get some idea you may look at OpenAM's doc, it is using an 'Account Mapper' for this purpose (https://backstage.forgerock.com/docs/openam/13.5/admin-guide/chap-federation#sp-account-mapper)
Related
I'm reading the SAML specification and experimenting with Keycloak and Shibboleth IdPs and I'm not sure how to implement one feature in an SP-initiated login.
I have a service that traditionally used to have an SP status information displayed on its login page (e.g. application version, status). After switching to using an IdP login page I'd like to keep displaying such per-SP additional information on the login page of the IdP. I'm interested in the data exchange, not in templating the login page itself.
Does SAML 2.0 specification allow for sending arbitrary data to the IdP for the purpose of logging in? If not, what are other options that can be used to decorate IdP login page using SP-generated data?
Sort of. The authentication request from SP to IdP is allowed to have "custom" extensions (the Extensions parent element), the content of the extensions is up to you. From the spec:
[Optional] This extension point contains optional
protocol message extension elements that are agreed on between the
communicating parties. No extension schema is required in order to
make use of this extension point, and even if one is provided, the lax
validation setting does not impose a requirement for the extension to
be valid. SAML extension elements MUST be namespace-qualified in a
non-SAML-defined namespace.
If you're writing your own IdP, you could certainly make use of Extensions and do whatever you wish with it. "Standard" (commercial/OSS) IdPs won't know what to do with your extension. It'd be an interesting test to see if Shibboleth or Keycloak libraries parse the Extensions element and give you the contents.
The other, more standard possibility is using RelayState. This is a spec-compliant way of passing some provider-specific state information around, incl. from SP to IdP:
3.1.1 Use of RelayState Some bindings define a "RelayState" mechanism for preserving and conveying state information. When such a mechanism
is used in conveying a request message as the initial step of a SAML
protocol, it places requirements on the selection and use of the
binding subsequently used to convey the response. Namely, if a SAML
request message is accompanied by RelayState data, then the SAML
responder MUST return its SAML protocol response using a binding that
also supports a RelayState mechanism, and it MUST place the exact
RelayState data it received with the request into the corresponding
RelayState parameter in the response.
Again, all IdPs or downstack libraries will parse RelayState but how they handle it from there depends on their reading of the spec. For one, the spec requires RelayState to be 80 bytes and integrity protection via a signature or "other means". This limitation is often ignored by IdPs and SPs.
What SP-specific information are you trying to display on IdP login page?
The only thing that an SP can send to the IdP is the Subject (see lines 585-589 of the spec).
I'm integrating with a 3rd party and for the claims configuration, they recommended we create sAM-Account-Name to Name ID, and keep getting this error in the SAML response:
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy" />
</samlp:StatusCode>
</samlp:Status>
So I assumed I was not sending the correctly formatted NameID. In the SP's metatdata, they have this listed:
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</NameIDFormat>
Rightly so, I assume I'm supposed to use the transient NameID format. However, that doesn't work either, and the vendor insists they expect our SAML response to use urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified as the Name ID format. From what I understand, that's default for ADFS.
As a test, I followed the steps here: https://blogs.msdn.microsoft.com/card/2010/02/17/name-identifiers-in-saml-assertions/ and was able to get a bogus NameID (transient) to pass to the vendor's site, where it then displayed back in the browser that the username was not valid, so at least I got something which makes me believe I'm on the right track and their authentication server is expecting transient while their application is not.
I would try the steps here, but I don't want to affect my whole claims provider: https://social.technet.microsoft.com/wiki/contents/articles/4038.ad-fs-2-0-how-to-request-a-specific-name-id-format-from-a-claims-provider-cp-during-saml-2-0-single-sign-on-sso.aspx
We're running Server 2012 R2 for our ADFS server. This isn't the first Relaying Party Trust we've configured, and our setup is working well with our other vendors. I however, am relatively new to managing ADFS, so I may have missed something simple.
Any thoughts or guidance would be appreciated.
If the claims mapping in ADFS for your relying party includes Active Directory samAccountName to SAML NameID, the "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" specified by the service provider's metadata doesn't really make a lot of sense as this value isn't transient.
As per the SAML v2.0 specification, the optional NameIDPolicy in the SAML authn request "specifies constraints on the name identifier to be used to represent the requested subject".
In practice, it's simpler to either not include a NameIDPolicy so it defaults to "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified" or explicitly use this value.
Given the above, the NameIDFormat in the service provider's metadata can be safely ignored and NameIDPolicy not included in the authn request.
The the SP can deny a claim based on its format, which is ultimately the issue. The solution then is the SP should either change their requirements, or one must send the claim in the required format.
In this case, the SP is requiring the claim to be transient, even though they verbally require unspecified (default). Verbal claim requirements don't count when dealing with systems!
To get ADFS configured with this SP, one simply needs to:
Create a transform rule, with the rule template: Send LDAP Attributes as Claims
LDAP attribute is SAM-Account-Name
Outgoing Claim Type is whatever you want it to be (custom text, not from the dropdown)
Create another transform rule with the rule template: Transform an Incoming Claim
The incoming claim type is whatever your Outgoing Claim Type was previous.
The Outgoing claim type is then Name ID with the format as Transient Identifier.
This will allow the sAM-Account-Name to be sent to the SP with a transient format, even though we know that attribute is by definition, not transient.
See screenshots:
I've set up Shibboleth IDPv3 to test my SP implementation. SP sends a SAML Logon request and the user is presented with the Shibboleth IDP credentials page in which the user enters their Kerberos credentials (I've configured the Loginflow with KerberosAuthNConfiguration). The SAML response comes back with a nameId which has what looks like an encoded value. However, what I want is the NameId element to contain the username that the user used to login to the IDP credentials page.
I had a few attempts by trying to configure the beans in the various XML configuration files without any luck. Has anybody tried something similar is this even possible to achieve ?
If you look in the file saml-nameid.properties you will see the parameter idp.nameid.saml2.default. I suspect that your configuration is set to the default of urn:oasis:names:tc:SAML:2.0:nameid-format:transient which is not an encoded value, but rather a random string.
It sounds like you want to send a "persistent" identifier rather than a transient identifier. To do this,
Change idp.nameid.saml2.default to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
Next, you will need to enable the Persistent NameID Generator in the file saml-nameid.xml.
Finally you need to set the attribute to use in your nameid via the idp.persistentId.sourceAttribute property, also in saml-nameid.properties.
Details on how to do this can be found at the Shibboleth IdP PersistentNameIDGenerationConfiguration page.
I have many clients that uses SSO, for that we use SAML 2. Many of my clients uses providers like Okta, PingIdentity and a bunch of them ADFS. Doing the integration with ADFS always at the beginning raises this error when they came back with the SAMLResponse.
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester"><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"/></samlp:StatusCode></samlp:Status>
Im asking to use as name Identifier this:
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
Im pretty new to SAML and I just want to know what is happening on ADFS, since this is just happening with clients that uses that.
Thanks a lot.
By default, ADFS sends the NameId format as "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified". You can adjust it. See: https://social.technet.microsoft.com/wiki/contents/articles/4038.ad-fs-2-0-how-to-request-a-specific-name-id-format-from-a-claims-provider-cp-during-saml-2-0-single-sign-on-sso.aspx
The other way to do this is to identity what attribute needs to be mapped to NameID e.g. email address.
Have a normal LDAP rule for email.
Then have a Transform rule that transforms email to NameID and select the NameID format you need from the drop-down.
I've implemented my Service Provider and Identify Provider following the SAML Profile for Web SSO using HTTP POST Protocol Binding. However, I am a bit confused as to how the Identity Provider will provide an <AuthnStatement> if the HTTP POST coming from the Service Provider is not tied to a session on the Identity Provider.
Could someone enlighten me how one would be able to do this?
The other approach I could use is the HTTP Redirect Binding, but that requires User-Agent intervention (i.e., the browser), often using the User-Agent simply as a pass-thru intermediary to faciliate the Request-Response message exchange. I'd rather use HTTP POST for this reason, because the message exchange occurs server-side, so the user sees nothing happening on their screen.
However, using HTTP Redirect makes more sense to me with respect to how I'd be able to tie a session to a request. Since the HTTP Redirect is facilitated via a User-Agent, the request to the IdP will have a session (if previously authenticated). What I don't get though is how to send an <AuthnRequest> on a HTTP Redirect. Answered by JST
So I'm a bit confused and would love to hear what other people are doing. Here are my questions again:
Using the HTTP POST Protocol Binding with the IsPassive option the <AuthnRequest>, how do I tie a request made by the Service Provider to a session on the Identity Provider? In other words, how does the Identity Provider know who is making the request if the POST is coming from the Service Provider which is technically an anonymous session?
Using the HTTP Redirect Protocol Binding, how do I send an <AuthnRequest> to the Identity Provider if I am using a HTTP Redirect? Answered by JST
UPDATE
Sorry for the confusion if I was unclear in my explanation above. I am implementing both the IdP and SP (via a plugin). The IdP is an existing application for which I want the SP (a third-party system) to use for authentication (i.e., Web SSO). I am developing a simple PoC at the moment. The SP is actually a third-party Spring application for which I am developing a plugin to perform the SAML operations.
I should have mentioned that I am trying to do this using the IsPassive option, that meaning the User-Agent doesn't come into play during the message exchange. It is simply the catalyst that gets the SAML-party started. Right? With that in mind, given that the user is anonymous at Step 1, what does the SP send to the IdP to allow the IdP figure out whether the user is already authenticated? Because of IsPassive, the HTTP POST isn't sent via the User-Agent
UPDATE
Question 1 Revised: How does the IdP resolve the Principal when the AuthnRequset is sent with the IsPassive option on?
Straight from the SAML 2.0 Profiles document, page 15, lines 417 to 419:
In step 4, the principal is identified
by the identity provide by some means
outside the scope of this profile.
What I'm really after is an explanation how to implement some means.
The thing to keep in mind is that there's no connection between a session on the IdP and a session on the SP. They don't know about each other, and communicate only through the SAML messages. The general steps for SP-initiated SAML SSO are:
Anonymous user visits resource (page) at SP.
SP identifies that user needs to be authenticated at IdP.
SP constructs AuthnRequest and sends to IdP.
IdP does some sort of authentication, constructs SAML Response and sends to SP.
SP validates Response and, if valid, does whatever is necessary to identify user at SP and get them to originally requested resource.
Yes, there does need to be some way to connect the SP's AuthnRequest to the IdP's Response. That's covered by the SAML spec: the SP's AuthnRequest includes an ID value, and the corresponding response from the IdP MUST include an InResponseTo attribute (on its SubjectConfirmationData element) with that ID value. The Authentication Request Protocol also allows the SP to pass a RelayState parameter to the IdP, which the IdP is then REQUIRED to pass along unchanged with the SAML Response. You (in the SP role) can use that RelayState value to capture state information allowing the user to be relayed to the originally requested resource.
That implies that when you implement an SP, you'll need some mechanism for recording ID and RelayState values, and your Response processing needs to validate InResponseTo and RelayState values it receives. How you choose to create and interpret RelayState values is up to you, but keep in mind that there is a length limit. (We use random GUID values corresponding to locally saved state data, which has the extra advantage of not giving any hint of meaning to the RelayState values.)
How does the IdP know who is making the request? The AuthnRequest must include an Issuer element that identifies the SP. It might also contain an AssertionConsumerServiceURL (the URL to which the Response is to be sent), or the IdP may have a local mapping of the Issuer to the proper URL.
How do you send an AuthnRequest using HTTP Redirect? The only difference between AuthnRequest sent using POST vs. Redirect, besides using GET rather than POST, is that the AuthnRequest XML has to get compressed (using the DEFLATE encoding).
Hope that answers most of your questions.
John,
I might suggest taking a step back and doing some more research before you decide to write your own SAML IDP/SP Implementation. You appear to be mixing Bindings with Profiles, Unsolicited vs Solicited Web SSO as well as the fact that SAML requires that the User Agent (aka Browser) is the bearer of almost all the messages between the IDP and SP. There is also a ton of info in the spec that will will have to implement to ensure your solution is actually secure.
I would suggest starting with our SAML Knowledge Base and then moving on to the OASIS SAML 2.0 Technical Overview for information on these flows.
Alternatively, if you decide to go best-of-breed you can check out our PingFederate product which can enable ALL the SAML IDP/SP use cases for you in < a day.
Hope this helps -
Ian
Unlike Ian, I am not associated with a company producing SAML-related products. However, I'd give somewhat similar advice: step back and identify why you are implementing SP or IdP. Are you really acting as both SP and IdP, or are you really just one or the other? If you're implementing/acting as IdP only, then it's fairly likely that a product like PingFederate or something similar offers all you need through configuration rather than requiring you to write custom code. If you're implementing SP, then such a product MAY be able to help you out, but it depends to a large extent on the characteristics of the system you're integrating it into. I am speaking as a developer who has done both IdP and SP implementations, and evaluated several tools before determining that because of our specific system, clients, and requirements, a custom implementation was our best option. It's been in place for over a year, with several clients using it (including some using varying commercial IdP tools).
If you can identify your use cases in terms of SAML profiles/bindings, then you'll be better equipped to make a buy-vs-build decision.