How do I set JSESSIONID domain to second level on Tomcat? - java

I have a service on Tomcat available at the following domains:
sub1.domain1.com
sub2.domain1.com
sub1.domain2.com
sub2.domain2.com
Now I need transparent authorization (Spring Security) for domain1. If user logs in to the sub1.domain1.com he is authorized on sub2.domain1.com too.
This can be done with Tomcat's setting
sessionCookieDomain=".domain1.com"
But now authorization on sub1.domain2.com doesn't work at all because all JSESSIONID cookie domain is always set to ".domain1.com".
How could I make tomcat use only second level of current domain for the cookies?

The simple answer is that there is no simple answer. Essentially you need a primary login site, and scheme whereby secondary sites get to set cookies for their domain that clone the primary site's session token. Implementing this is complicated.
Two possible SSO technologies are Shibboleth and JASIG CAS.
For more details, refer to the answers to Single Sign On across multiple domains
What if I somehow overload cookie creation and set .domain1.com and .domain2.com where required?
If foo.domain1.com tries to set a cookie with path .domain2.com or anything.domain2.com, the browser will ignore it for security reasons. You have to go through a complex dance of redirections to set the cookies on both domains. Read the question / answers I linked to (above) for more details.

Related

How to require client certificate authentication in only specific java servlets?

I am trying to create a java servlet application that requires client certificate authentication, but only on specific pages. I would like to have a landing page that doesn't require any sort of authentication which will have a link/button to go to a page that does require authentication. Is there a way to do this?
I am using OpenLiberty as the servlet container. I am familiar with using ClientAuthenticationSupported="true" (in server.xml), but I do not want the user prompted to select a certificate until they reach a certain page. I have also looked at HttpServletRequest, but don't see a way to force a specific type of authentication with the available methods.
I want the user to be prompted like they would be visiting prod.idrix.eu/secure. Is there a way to set a servlet's authentication type programmatically to accomplish this? Any help would be appreciated. I think this can be done using two different applications (one that does not require authentication and one that does), but I would like to keep it all as one.
Thanks.
In web.xml you can specify security-constraints that will include URL patterns for the pages that should be protected. You can also configure <login-config> to use CLIENT-CERT authentication method.
In the server.xml then you configure your user registry and mapping between cert and user. More details here - https://www.ibm.com/docs/en/was-liberty/base?topic=liberty-ldap-certificate-map-mode

Inter domain cookies in Tomcat 7 via XML config

I've been tasked with modifying an application, of which I have access to the XML configuration of it in what appears to be Tomcat 7.
I need a cookie (called oname to be specific) shared to another domain (example.com). That is to say that, an iframe on the application to example.com can share the cookies from the application.
First of all, is this possible? Second of all, if it is (which I hope it is! :)) how can I do it via XML and XML only (referring to the configuration files found in the base of the application).
I've done some research on cookies, and I determined I need to modify the domain section on all cookies. If I need to change change all cookies globally (e.g. adding an XML element within the configuration to add domain = example.com to all cookies then that's acceptable!
I've pretty much have 2 options:
Find a specific XML element to change all cookies globally to add my desired domain
Have a JavaScript shim on the client side (I have access to the HTML also) wrap around the normal method to set cookies, while also adding example.com to the domain bit on the cookies.
Thanks for any help!
If your application is running on www.example.com, it can set a cookie for .example.com, but not if it's running on any other domain than example.com. If it would be possible to set cookies for unrelated domains, Anybody could easily set a cookie for any other random site, and as cookie names are typically well predictable, interfere with those sites (e.g. setting jsessionid or other session- and identification cookies in a rogue way).
Your only option is if the other site cooperates and provides a URL that you can redirect to which sets the cookie itself. Beware: Without checking the validity of the request, anybody can redirect to that site and set a cookie through the same measures - you can easily introduce a security issue.

Integrating a single page application with Ping Federate

I have configured IdP and SP in my desktop.To test SSO, I have a single html page deployed in tomcat.I have given the url : http://machinename:portno(here tomcat's port)/webApp/index.html in default url of SP configuration. When I try to hit the SP SSO url,(http://machine_name:portno/sp/startSSO/ping) it redirects to IDP and prompts for authentication. Once the user is authenticated, the user is redirected to the tomcat webpage.
But, when I try to access the tomcat page, I am able to access it without any authentication. Is there any configuration on the SP side? If so, how to do it? When I access the web page, I should be prompted for authentication.
This configuration question really has nothing to do with PingFederate. This is more about how you have chosen to integrate your Tomcat application with the PingFederate SP Adapter. Chances are you are using the SP OpenToken or SP ReferenceID Adapter for a Java app in Tomcat- these Adapters merely provide the user's identity attributes to your application after the SAML Response is validated by PingFederate SP. It is up to your application to validate the specific token type (using the proper steps required by the SP Adapter you have chosen) and then your application is also responsible for enforcing access/maintaining a session based upon the user's identity that is passed in the token.
If you are expecting Access Control/Session management, I'd recommend looking at integrating PingFederate with PingAccess.
Bottom Line: Ping's solution's are hugely flexible so there are a number of ways to accomplish this based upon your application infrastructure and use case requirements. I suggest that you work with your Ping Identity RSA to help you work through these questions in order to have the best possible outcome.

How to build central sign architecture with spring security and angularjs applications

I have 4 single page applications with same technologies: Spring MVC, Spring Security, Angulajs.
Each application has own ldap authentication and authorization. We want to build a single sign architecture and make a central authentication application. And make the other 4 application use this central application.
When user login into one of the apps, he should not need to login the others.
What is the easy way to implent this in server side and client side?
What you want is Single Sign-On (SSO). There are two options:
Use some existed SSO server like CAS.
Do it yourself using subdomain cookie technique.
First option is exactly what you want implement. When you open URL of app1 you will be redirected to SSO server and prompted for login/password. After successful authentication you will be redirected to app1 URL. Now if you open app2 URL you will be signed in automatically. One of advantages is that user password is stored only in SSO server.
Second option is more lightweight IMHO, because instead of using existed SSO server for sharing authentication information between your apps you use HTTP cookies. From the other side you need to write some minimal authentication code which may be less secure.
Subdomain cookie technique:
Use subdomains for all your apps (app1.domain.com, app2.domain.com)
When user connects to app1, generate some token (your session id), store it in some shared DB and as a cookie for domain.com
When user opens app2, check if token is present (as a cookie for domain.com), verify that it is valid (use shared DB) and allow access.
It is very simple algorithm that do not take into account all possible security vulnerabilities (like session fixation for example). So if you do not have enough time to solve them it may be better to go with first option.

Best way for allowing subdomain session cookies using Tomcat

By default tomcat will create a session cookie for the current domain.
If you are on www.example.com, your cookie will be created for www.example.com (will only work on www.example.com). Whereas for example.com it will be created for .example.com (desired behaviour, will work on any subdomain of example.com as well as example.com itself).
I've seen a few Tomcat valves which seem to intercept the creation of session cookies and create a replacement cookie with the correct .example.com domain, however none of them seem to work flawlessly and they all appear to leave the existing cookie and just create a new one. This means that two JSESSIONID cookies are being sent with each request.
I was wondering if anybody has a definitive solution to this problem.
This is apparently supported via a configuration setting in 6.0.27 and onwards:
Configuration is done by editing
META-INF/context.xml
<Context
sessionCookiePath="/something"
sessionCookieDomain=".domain.tld" />
https://issues.apache.org/bugzilla/show_bug.cgi?id=48379
I have just gone through all of this looking for a simple solution. I started looking at it from the tomcat perspective first.
Tomcat does not give direct access to configuring the domain cookie for the session, and I definitely did not want to custom patch tomcat to fix that problem as shown in some other posts.
Valves in tomcat also seems to be a problem solution due to the limitations on accessing headers & cookies built into the Servlet specification. They also fail completely if the http response is commited before it gets passed to your valve.
Since we proxy our requests through Apache, I then moved onto how to use apache to fix the problem instead.
I first tried the mod_proxy directive ProxyPassReverseCookieDomain, but it does not work for JSESSIONID cookies because tomcat does not set the domain attribute and ProxyPassReverseCookieDomain cannot work without some sort of domain being part of the cookie.
I also came across a hack using ProxyPassReverseCookiePath where they were rewriting the path to add a domain attribute to the cookie, but that felt way to messy for a production site.
I finally got it to work by rewriting the response headers using the mod_headers module in apache as mentioned by Dave above.
I have added the following line inside the virtual host definition:
Header edit Set-Cookie "(JSESSIONID\s?=[^;,]+?)((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(;\s?(?:(?i)Domain\s?=)[^;,]+?)?((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(,|$)" "$1$2; Domain=.example.com$4$5"
The above should all be a single line in the config. It will replace any JSESSIONID cookies domain attribute with ".example.com". If a JSESSIONID cookie does not contain a domain attribute, then the pattern will add one with a value of ".example.com". As a bonus, this solution does not suffer from the double JSESSION cookies problem of the valves.
The pattern should work with multiple cookies in the Set-Cookie header without affecting the other cookies in the header. It should also be modifiable to work with other cookies by changing JSESSIONID in the first part of the pattern to what ever cookie name you desire.
I am not reg-ex power user, so I am sure there are a couple of optimisations that could be made to the pattern, but it seems to be working for us so far.
I will update this post if I find any bugs with the pattern. Hopefully this will stop a few of you from having to go through the last couple of days worth of frustrations as I did.
As a session (and its Id) is basically considered of value only for the issueing application, you may rather look for setting an additional cookie. Have a look at Tomcats SingleSignOnValve, providing the extra-Cookie JSESSIONIDSSO (note the ...SSO) for the server path "/" instead of "/applicationName" (as JSESSIONID cookies are usually set).
With such a Valve you may implement any interprocess communication you need in order to synchronize any state between different servers, virtual hosts or webapps on any number of tomcats/webservers/whatever.
Another reason why you cannot use tomcats session cookie for your own purposes is, that multiple webapps on the same host have different session ids. E.g. there are different cookies for "/webapp1" and "/webapp2". If you provide "/webapp1"'s cookie to "/webapp2", this wouldn't find the session you referenced, invalidate your session+cookie and set its own new one. You'd have to rewrite all of tomcats session handling to accept external session id values (bad idea securitywise) or to share a certain state among applications.
Session handling should be considered the containers (tomcats) business. Whatever else you need you should add without interfering with what the container believes is necessary to do.
I've run into this at $DAYJOB. In my case I wanted to implement SSL signon then redirect to a non SSL page. The core problem in tomcat is the method (from memory) SessionManager.configureSessionCookie which hard codes all the variables you would like to get access to.
I came up with a few ideas, including a particularly egregious hack using mod_headers in apache to rewrite the cookie based on regex substitution.
The definative way to solve this would be to submit a patch to the tomcat developers that adds configurable parameters to the SessionManager class.
The valve techniques do not seem to be 100% perfect. If you dare to modify Tomcat itself:
catalina.jar contains the following class: org.apache.catalina.connector.Request
The Request has a method:
configureSessionCookie(Cookie cookie)
For our environment it was best to just hardcode it, but you could do more fancy logic:
cookie.setDomain(".xyz.com");
Seems to work perfectly. Would be nice if this was configurable in tomcat.

Categories

Resources