SAML IDP initiated SSO transaction - saml

Webapp #1 has a button to webapp #2. When our users click that button, they should be redirected to webapp #2, and be automatically logged-in.
The integration is SAML, so webapp #1 (the IDP) sends a SAML "request" to webapp #2 (the SP), which returns a redirect URL, and webapp #1 redirects to it.
The SP gave me a URL to HTTP POST an assertion identifying the user via the "email" attribute, so I produced this:
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" IssueInstant="2021-12-22T16:59:43.999Z" Version="2.0"><saml2:Issuer>http://www.whatever.com</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><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><saml2:Conditions><saml2:OneTimeUse></saml2:OneTimeUse></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2021-12-22T16:59:44.053Z" SessionIndex="cfb8f9b5-9616-47db-bc92-7588ce18cf62" SessionNotOnOrAfter="2021-12-22T16:59:44.068Z"><saml2:AuthnContext></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="email"><saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">si#captisintel.com</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>
The SP responds with a 302 and a Location header that looks like this:
Location: ?SAMLRequest=nVNNj9owEP0rke%2FkS4VtLc...
Decoded:
<?xml version="1.0"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_f848f04c71671a745722" Version="2.0" IssueInstant="2021-12-22T18:36:19.337Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://auth.whatever2.com/saml/callback" Destination=""><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">whatever2</saml:Issuer><samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/><samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"><saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>
When I visit that URL, I am presented with the login page.
So this is not working.
I have 0 visibility over the SP logs to know what's wrong. All I can guess is that I am not posting this correctly. So does this look right, or should I post this differently? I tried posting the Assertion in the body as-is, wrapping it in a "<samlp:Response" envelope, wrapping it plus prefixing it with "SAMLResponse=". I tried each plain and deflated/base64 encoded.
Another clue is that the SP always returns a 302, no matter what I send them. Even if I send "BLAHBLAH" and not an actual SAML payload, they still respond with a 302.
Any advice?

In a IdP initiated flow, the IdP sends the SAML Response containing a Assertion in a POST like you do. If all goes well the SP should now consider the user authenticated.
The SAML response should be sent in input control named SAMLResponse and should be Base64 encoded.
<input type="hidden" name="SAMLResponse" value="<Base64 encoded SAML Response>"/>
I would guess that what happens is that for some reason, the SP does not accept your SAMLResponse and instead starts the normal SP initiated SAML flow by sending a SAML request to the IdP to authenticate the user.
Why your response is not accepted can be many things. Without the SP logs we can mostly guess.
Off the bat I see that you assertion is missing a Bearer subject confirmation which is mandatory.
From the SAML Profiles spec 4.1.4.2
Any assertion issued for consumption using this profile MUST contain a element with at
least one element containing a Method of
urn:oasis:names:tc:SAML:2.0:cm:bearer. Such an assertion is termed a bearer assertion.
Bearer assertions MAY contain additional elements.
There is also more requirements on the assertion in the same chapter
Some other ideas though:
You should have your assertion in a SAML response, but there are several boiler plate elements that need to be set. So ensure it is valid
It is not unusual to see that the response message itself must be signed and not just the assertion.
I would suggest having a look at the SAML profiles spec 4.1.4.2 to understand what assertion and response must contain.
And also, try agian to see if you can get any feedback on whats wrong from the SP to avoid banging your head bloody doing blind try and fail.
SAML is not the most stright forward protocol there is and there is a lot to get right to get it working and get it secure. As I always try to say to people starting out with it: Dont build it your self, there is alot of good opensource alternatives out there for doing SAML that will make your system so much more secure and maintainable.
If you want to get a better understanding of SAML and how to implement it I can recommend my book, SAML 2.0: Designing secure identity federation
Good uck!

You should be sending a SAML response containing a SAML assertion to the SP rather than just a SAML assertion. You also need to ensure this is encoded correctly as per the SAML v2.0 Bindings specification.
You really need the SP to assist with the debugging. Hopefully their logs will provides details as to why they're rejecting your HTTP Post.

Related

How is a failed login attempt represented with SAML with SP-initiated SSO?

I would like to set up my Service Provider (SP) for SP-initiated SSO.
When the user successfully logs in, I'm expecting the IdP to POST a SAML Assertion to my SP (is this called endpoint on my SP called an Assertion Consumer Service?).
What should I expect to happen when my SP and IdP are configured correctly but the user fails to authenticate – either with their primary credentials or MFA? Will the IdP POST a failure message to my SP?
If so, what is the conventional terminology for this payload? Is it still called a SAML Assertion but containing some kind of failure syntax differences or is it a totally different type of SAML payload, called something else? Do both success and failure payloads get sent to the same SP endpoint?
Thank you!
The thing you get back from the Identity Provider is always a SAML Response. If it's a successful response, you get an assertion. If it's a failed response, you get an error message passed from the IdP... And there's no real "standard" for those responses, other than the typical SAML message formatting.
Section 3.5.6 of the Binding spec describes the expectation for the POST profile. Each profile will provide for this, but as the SP, in most situations, you'll be using this binding.
Section 3.2.2 of Core defines the StatusResponseType - effectively, the status code of response that should be sent in various situations, the status message and status detail. It should be noted that most IdPs will simply return the urn:oasis:names:tc:SAML:2.0:status:AuthnFailed status code, and then maybe some additional detail in the status message or detail fields... But you cannot count on more than the code.
And yes, responses will always go to the typical SAML protocol endpoint, no matter their status.

SAML Single Logout for Keycloak

I'm trying to implement single logout for SAML in keycloak and the documentation doesn't mention this properly and is confusing. I was looking for exact steps on how to implement it. So far, what i have done is:
Generate the logout request payload, base64 encode it, url encode it and send it to the logout url as a param. Assume that the realm name is Abc
http://auth-server/auth/realms/Abc/protocol/saml?SAMLRequest={encodedSAMLRequest}
The saml payload is
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="random uuid" Version="2.0" IssueInstant="2021-02-09T06:53:26Z" Destination="ip-address:8443/auth/realms/Abc/protocol/saml">
<saml:Issuer>https://ip-address:8443/auth/realms/Abc</saml:Issuer>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user-email#abc.com</saml:NameID>
</samlp:LogoutRequest>
However, while sending this, i get 400 error saying "Unknown login requestor"
(eventhough I want to logout)
The site here says the request is valid. Maybe I am missing some extra parameter or something? I would also need an exact way to send. I have to use scala. Thanks in advance!
I think your Issuer might be wrong.
It looks like your issuer is a Keycloak URI, but it is supposed to be a URI representing your application (service provider). It is the same as the client ID field of your configured SAML client in the Keycloak admin gui

SAML spec: returning to the SP without a user

I'm using the standard SAML 2.0 SP-initiated SSO protocol for authentication.
Normally the IdP returns a samlp:Response XML object to my SP, containing a saml:Assertion about the authenticated user.
Does the SAML spec allow the IdP to return a response to the SP that doesn't contain user information?
I'd like handle the situation where authentication couldn't be done, but we want to return to the SP's site. Maybe the IdP could return some kind of error or message to our SP? Right now it seems like if authentication is impossible, the user is stuck on the IdP's site.
I guess they could just redirect to an agreed-upon URL, although then you would lose the RelayState information. Would that be the right approach, or does the SAML spec handle this scenario?
The SAML2 spec handles this. The Idp can return a samlp:response with a status code of Responder meaning that the idp failed to fulfill the request. Then there can be more detailed status information on exactly why.
But the case where an Idp fails to authenticate the user can be handled in the protocol. However, I think that most Idps behave as you describe - keep the user on the Idp if things goes wrong.
Added by OP — this is from the SAML spec:
<StatusCode> [Optional]
A subordinate status code that provides more specific information on an error condition. Note that responders MAY omit subordinate status codes in order to prevent attacks that seek to probe for additional information by intentionally presenting erroneous requests.
The permissible top-level values are as follows:
urn:oasis:names:tc:SAML:2.0:status:Success
The request succeeded. Additional information MAY be returned in the and/or elements.
urn:oasis:names:tc:SAML:2.0:status:Requester
The request could not be performed due to an error on the part of the requester.
urn:oasis:names:tc:SAML:2.0:status:Responder
The request could not be performed due to an error on the part of the SAML responder or SAML authority.
urn:oasis:names:tc:SAML:2.0:status:VersionMismatch
The SAML responder could not process the request because the version of the request message was incorrect.

How does SAML work in relation to an application that is not a service provider?

So I'm struggling a bit with the basics of the flow of SAML. Here's the scenario I find confusing.
I have a java web application. The user is logged in. I know they want to order cookies from a 3rd party because they've clicked on the "I want chocolate chip cookies" link. I also know that "Mrs. Pillsbury Cookies Co." is a "Service Provider" because she sent me her meta-data and I've registered her with my Gluu Server (IdP). I've also sent her my IdP meta-data so we've done the whole hand-shaking thing.
My question is...how do I now send the SAMLResponse to Mrs. Pillsbury? She's given me a SOAP endpoint that is waiting for a SAMLResponse. How do I tell my Java application to get some XML from my gluu server as a SAMLReponse that I can then pass to the Pillsbury SOAP endpoint? That's the part where I'm stuck...I don't know how to get a response to forward. I can see in the metadata that there are lots of SSO endpoints
<SingleSignOnService Binding="urn:mace:shibboleth:2.0:profiles:AuthnRequest" Location="https://idp.myjavaapp.com/idp/profile/SAML2/Unsolicited/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.myjavaapp.com/idp/profile/SAML2/POST/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://idp.myjavaapp.com/idp/profile/SAML2/POST-SimpleSign/SSO
Am I supposed to hit one of those SSO endpoints and it'll generate a response that I can then forward on to Pillsbury? Can one of you SAML experts out there get me straigtened out? Thanks in advance.
There are a few ways SAML Requests/Responses can be generated.
IdP initiated:
This is a SAML Response generated w/o a SAML request. This requires the user to login/be logged into the idP and the idP will generate a SAML Response based off the SP setup in the idp.
SP initiated:
This is usually an HTTP Redirect but can be a POST as well. This is a SAML Request Redirect/POST that gets sent to the idP based of some link or button on the SP's website.
As I understand it you have the following relationship:
Your App
\
3rd Party ordering
/
IdP Server
Your app needs to make a request to the 3rd party, but also need it to authenticate against the IdP. Yes?
Normally the process works such that the 3rd party requests the token itself. Your app shouldn't have the token intended for the 3rd party -- it should only have the token for its own app.
Usually you send whatever your app-specific request is to the 3rd party first. When they receive that bit of information they hold onto it and then make a SP-Initiated authentication request to your IdP. They will attach a bit of information as part of the auth request called relay state. This bit of information is used to reconstitute the session after the IdP responds.
Once the IdP receives the request it does whatever it needs to do to authenticate the user, and sends the token back to the 3rd party. As part of that response they also send the relay state. The 3rd party then verifies the token and sets the session as necessary, then reads the relay state and sets whatever internal state is necessary to continue the order.
You're on the right track. As the previous answers have explained, it can be done one of two ways: the SP site (Pillsbury) sends you an authentication request, or you can direct your IDP/Gluu server to send an SAML message to the SP without them prompting: "unsolicited".
In the case of the first "SP-Initiated", you just create a link to the SP site for the user's browser to follow. The user's browser hits the SP site, the SP site realizes that it needs to authenticate the user: so it creates a SAML Authentication Request to your IDP endpoint, directing the user's browser there. Then your IDP server will respond according to the metadata/relationship that you've set up with the SP site. Just as one of the other answers explained, this Authentication Request can include a RelayState parameter which will be sent back to the SP to tell them where to send the user after the SAML message had been consumed & validated. I haven't used Gluu but I believe the SP would use the second endpoint you showed in your question to do this.
In the case of the second "IDP-initiated", you need to direct the user's browser to one of the Gluu server endpoints to generate a SAML assertion, which will be POST'd back to the SP site without the SP site's prompting. This one is less used because every time the user is directed to the SP site from your site, they will be forced through the AuthN process among other reasons. I believe this is the first listed endpoint that you showed in your question.
Here's a really good explanation of IDP-initiated from Shibboleth, that should help clear this up for you: https://wiki.shibboleth.net/confluence/display/SHIB2/IdPUnsolicitedSSO
Best of luck!

How to ask for user login when using SAML SOAP binding?

I am learning SAML, and regarding SOAP binding, I am not sure how this works.
For redirect binding and post binding, it is very clear that SP can talk to IdP through browser then IdP can display a login screen if necessary.
But for SOAP binding, it doesn't need to go through browser, an SP can simply send an HTTP request which consist of a SOAP request to an IdP, then if IdP find that there is no valid user session, how can he display a login screen for user to input the username and password?
Or am I missing anything?
Authentication is out of scope of the SAML spec. However, what SAML Profile are you looking at? Is this for Web SSO or something else? For Web SSO, SOAP is only used with the HTTP artifact binding which means you would either be resolving the AuthnRequest (IDP calling the SP) or retrieving the Response (SP calling IDP). The Artifact is sent either via POST or Redirect while resolution of the message (AuthnRequest or Response) is done via back-channel SOAP. So, the browser (http client) is always involved with Web SSO so it is simple for the IDP to authenticate the user via some browser-friendly technology (username/password HTML form, 2 factor strong auth, x509 certs, etc etc).
You can find an example in the SAML Bindings
POST /SamlService HTTP/1.1
Host: www.example.com
Content-Type: text/xml
Content-Length: nnn
SOAPAction: http://www.oasis-open.org/committees/security
<SOAP-ENV:Envelope
xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/”>
<SOAP-ENV:Body>
<samlp:ArtifactResolve xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="identifier_2"
Version="2.0"
IssueInstant="2004-12-05T09:22:04Z"
Destination="https://idp.example.org/SAML2/ArtifactResolution">
<saml:Issuer>https://sp.example.com/SAML2</saml:Issuer>
<samlp:Artifact>artifact</samlp:Artifact>
</samlp:ArtifactResolve>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The syntax might not be exact. Just something to give an idea.
How the IdP chooses to authenticate the user is out of scope for SAML. If you're looking for an example, maybe there is a native application that displays a dialog box to the user, asking him to authenticate. Maybe the IdP sends you a text message through an SMS gateway and you have to respond to the text message in a certain way. The sky is the limit.