Issue with SSO between SAML SP and ADFS IdP - spring

we are developing a web application which offers multiple login mechanisms such as LDAP, Kerberos, SAP Logon Ticket as well as SAML.
For this we use the Spring Security Framework which works (mostly) fantastic!
A few months ago we added SAML support to our application and tested this with an external IdP (SSOcircle). We also worked closely with CEO of SSOcircle to get us up and running.
Everything worked just fine and we thought we could enroll SAML with our first real life customer.
So we setup a test server (SP) on a linux machine, and configured our part (we used this doc: http://docs.spring.io/spring-security-saml/docs/current/reference/html/chapter-idp-guide.html) and waited for our customer to do their part.
But when they tried to SSO into our application (they use ADFS), we ran into an issue.
Because right now, we get one out of two error messages. Either this one
Authentication request failed:
org.springframework.security.core.userdetails.UsernameNotFoundException:
Empty username not allowed!
or this one
Error validating SAML message org.opensaml.common.SAMLException:
NameID element must be present as part of the Subject in the Response
message, please enable it in the IDP configuration
During the troubleshooting I came across these other threads here on StackOverflow:
SAMLException: NameID element must be present as part of the Subject in the Response message, please enable it in the IDP configuration
Configuring ADFS 3.0 / SAML 2.0 to work with Spring Security for SSO integration
NameID element must be present as part of the Subject
The odd thing is, that the second error message (regarding the nameid) element comes up only if we change the adfs claim rule from "Outgoing claim type" to "Pass Through claim type".
Right now, I have no idea where to continue my troubleshooting. Any ideas or thoughts on this issue?
Best regards
René
EDIT1: I attatched a link to the debug logfile and our saml security config
EDIT2: Does someone know if there is a way to specify a timezone which SAML should use? Right now, Zulu time seems to be the time zone used although our OS is configured to use CET/CEST. Therefore we had to use responseSkew parameters for login/logout.
EDIT3: Debug & Config removed because we solved the problem

Okay, we solved the problem.
During a live debugging we noticed that NameID was not send as a SAML assertion attribute key/value pair but as a "standalone" key/value pair in the SAML assertion "header".
So we modified our code to cover both possible positions within the SAML assertion and now it works just fine. :D

Related

outbound propagation of oidc access token in Liberty

Hello I manage 2 Liberty servers that serve UI and BFF content respectively and I want to secure them both with corporate oidc OP. Having heard about inbound propagation, I was thinking in propagating the access token from UI to BFF.
However I didnt find documentation on how should I configure it to outbound propagate the access token after successful authentication. The documentation only refers to inbound propagation. Only thing I see is a WASOidcClient_*** cookie being set, which I know nothing about it.
I also heard about jwtSso-1.0 feature and tried to create my own JWT with the necessary user information, but can't make this feature get the desired claims from the ID Token (already opened this other question).
So I'm unclear of:
Am I designing this correctly?
How can I get the UI Liberty propagate access token after successful authentication, preferably without coding anything?
Should I propagate access token, or IDToken? BFF needs basic user information that is present in IDToken
What is the WASOidcClient_*** cookie for? Can it be used by different Liberty instances to authenticate requests? Is the name configurable? Im just curious, because this cookie is probably proprietary and not portable, not much desired.
Appreciate it in advance!!

How to know the status of a ticket using REST in CAS OVERLAY 5.3?

I have centralized the authentication of my clients (Python, JAVA GWT, JAVA Spring) using CAS OVERLAY which is done correctly; My problem is, how can I know the status of a ticket to validate my session from any of my clients? I have reviewed and there is a GET type REST service but the truth is I don't know if I am using it correctly.
Client 1 active session with ticket: (Python)
Now to verify the ticket use:
Can you guide me through this problem or is there a better way to validate a ticket for my client-side session?
ADD:
segun https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-Specification.html my ticket is invalid but I don't understand this context
"the ticket did not come from an initial login"
Help me please!
How to know the status of a ticket using REST in CAS OVERLAY 5.3?
If you look at the REST documentation, you'll observe this:
Verify the status of an obtained ticket to make sure it still is valid and has not yet expired.
GET /cas/v1/tickets/TGT-fdsjfsdfjkalfewrihfdhfaie HTTP/1.0
This requires that you turn on REST support, as indicated by the same documentation.

Spring Security Kerberos SSO for a REST API (Tomcat)

Here is my problem:
Context :
-Windows Server 2012 with ActiveDirectory
-Tomcat
-Rest API (Spring)
I'm currently trying to restrict REST request. I want that only specific groups of the AD could access to specific resources. I'm restricted to Kerberos authentication.
System configuration
Create a user in domain "Tomcat"
setspn -a HTTP/apirest.domain#DOMAIN
Generate a tomcat.keytab using ktpass
API rest configuration
I'm using the spring security sample on github that you can find here :
https://github.com/spring-projects/spring-security-kerberos/tree/master/spring-security-kerberos-samples/sec-server-win-auth
I know that there is an EntryPoint and this is not needed in my context (API Rest). I've chosen this sample because it seems to use the windows authentication context and use it to automatically authenticate me in the spring security context. Right after, an ldap request is send to extract all information about the user logged. In my case, I need to extract the group.
I'm also using :
https://github.com/GyllingSW/kerberos-demo
To extract the role of the user with the class "RoleStrippingLdapUserDetailsMapper.java" instead of the "ActiveDirectoryLdapAuthoritiesPopulator". This implementation also offers localhost authentication but the issue with the NTLM token seems to be fixed in last commit of spring security.
I'm not really sure if this is the right way to do what I want.
My authentication seems to fail and I only have one things going wrong in my logs..
"Property 'userDn' not set - anonymous context will be used for read-write operations"
Questions
Do I have to run my tomcat service using the tomcat account ? (Seems to be, yes)
Am I doing the right things with Kerberos security ?
How can I get rid of the anonymous context?
The anonymous context seems to be set just right after Tomcat start. I want to get a context just after that my user (For instance, user1) requests the rest API (EntryPoint or whatever)
If there is something unclear let me know, I will try to reformulate!
Thanks,
You do not need to query LDAP to get information about which groups does user belong to. Active Directory already adds this information to the Kerberos ticket which is sent from browser to Tomcat.
You just need to extract this information from the token for example using Kerb4J library. It comes with Spring integration inspired by spring-security-kerberos project so it should be pretty easy to switch to it.
If you still want to query LDAP you need to authenticate in LDAP before you can make any queries. Again there's no need to use end-user accounts for it - you can use the keytab file for Kerberos authentication in LDAP and query groups using "Tomcat" account
I found a way to fix my issue.
In a REST API context, you have no entry point. I tried to set my entry point to an unmapped URL, just to do the negociation. By doing this, you will receive an HTTP response with the error code 404 (Not found) but with the right header was added by spring security (WWW-Authenticate).
The web browser will not send the ticket service if the error code is not 401.
To solve this problem, you have to create a CustomEntryPoint class (implements AuthenticationEntryPoint) and you need to override the "commence" method to return a 401 HTTP code with the right header.
I hope that could help. If there is a better way, let me know !

Laravel SAML WIA not working

I am using Aacotroneo/Laravel-Saml2 and have successfully setup a login system using ADFS. In another system I am using simpleSAMLphp elsewhere on the same domain successfully with WIA so I know ADFS is setup for that and that everything is setup correctly except the laravel application.
I have installed a browser addon to check the SAML logs for responses and requests. The only thing I can think of is that there is no client request ID sent through from laravel.
&client-request-id=d1ccbbdd-d55e-4828-eb24-0080000000b4
Any suggestions are appreciated. If I have missed a saml2 setting I am more than happy to try them, a lot of them don't seem to work or make any difference whether set to true or false.
Is it possible I need to setup encryption certificates and certain true/false combinations?
Thanks
Check this article
ADFS has non-standard SAML2 Authentication Context Class urn:federation:authentication:windows
By default this class has lower priority than urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
I would suggest making the following changes to AuthNRequest:
<samlp:RequestedAuthnContext Comparison=”minimum”
<samlp:AuthnContextClassRef xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">
urn:federation:authentication:windows
</samlp:AuthnContextClassRef>
<samlp:AuthnContextClassRef xmlns:samlp="urn:oasis:names:tc:SAML:2.0:assertion">
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</samlp:AuthnContextClassRef>
</samlp:RequestedAuthnContext>

Can SAMLCredential.getRemoteEntityID() be trusted?

I'm implementing Spring SAML in an app which is configured with multiple identity providers. My IdP metadata configuration has multiple ExtendedMetadataDelegate with an HTTPMetadataProvider and alias for each IdP. The app chooses which provider to use by extending SAMLContextProvider in a similar way to this.
When an IdP sends authorisation my app needs to know which IdP it came from (different providers have different security authorisations). I'm doing this as the docs suggest and using a custom SAMLUserDetailsService and the SAMLCredential.getRemoteEntityID() to determine which IdP made the request.
My question is, can I rely on the remoteEntityID to identify the provider? What if one IdP provider updates their metadata to include a different entityID or even "forged" entityID which was identical to another provider? Wouldn't it be better to use the peer alias as defined by us?
I'm new to SAML so it's very likely my understanding of some basic concept is incorrect, I just want to make sure I'm not opening a security hole with this configuration.
This is a good question. I didn't know the answer so I tried it out.
I have in my test environment an instance of MS ADFS and and SpringSAML project with a Service Provider and Identity Provider configured (for ADFS). In my custom SAMLUserDetailsService I use SAMLCredential.getRemoteEntityID() to determine which IDP the request came from.
I performed a successful login, then changed the name of the ADFS EntityID, then tried to login again. This resulted in a AuthNResponse;SUCCESS;127.0.0.1 message in the logs, but an error in the browser. I ran through it again with debug enabled in the UserDetailService and found that the request is failing somewhere before it gets to the UserDetailService, however, I'm not seeing any error messages in the logs.
To answer your question, (and perhaps someone else can answer more definitively), SpringSAML handles this scenario appropriately in that it errors out. It does not in that there is no error message in the logs. I assume this is because it's a somewhat unusual scenario to happen, or just a bug.
As far as forging another Identity Provider's Entity ID, the SAML requests are signed and therefore anyone trying to forge and IDPs message would also have to have access to their private key.
Lastly, the alias is not in the request, thus it cannot be used to differentiate between IDPs.

Resources