I have some java code which allows users to reset their passwords stored on a LDAP server. The code runs as part of a web application running on Glassfish.
The problem I'm seeing is that after calling the change password operation, the user can subsequently use either password to access the application.
I have a unit test which runs directly against the LDAP server and I can verify that the password did indeed change and the user cannot gain access using the old password. The problem is not on the LDAP server.
What I've noticed is that if I restart Glassfish after the password change operation, only the new password is valid (as expected). I'm guessing that Glassfish is caching the credentials somewhere.
What do I need to set in Glassfish (or maybe in my web.xml) to either
tell Glassfish not to cache the LDAP credentials
reset the Glassfish password cache
Thanks in advance....
UPDATE
Still having this problem. I also thought that the browser could be storing this information, but that doesn't seem to be the case. I close out of my browser session and both passwords still work in the new session - even with different types of browsers. BTW - I don't know if it matters or not, but this is HTTP basic authentication.
UPDATE
We are also using the single sign on functionality included with Glassfish. From this article, it looks as if the session is tied to a cookie on the browser and maybe the user would be valid until the cookie expired? It looks as if the cookie is tied to a session. Getting closer to figuring this out....
Try adding this property to your ldap realm's additional properties:
com.sun.jndi.ldap.connect.pool=false
Could be your problem related to this Active Directory issue?
http://support.microsoft.com/?id=906305
My problem was.
Related
The Problem
When redirecting from a servlet using response.sendRedirect(redirect_url);, the JSESSIONID cookie is not passed by the browser to the destination. A new JSESSIONID is created for every redirect, and it is impossible to track the user.
Note: This problem is only occurring on my new server implementing https and a domain name; the session ID is properly tracked when I run the web app locally or on another server without SSL or a domain name. Edit: I have set up another site on my server without SSL, and the issue persists. This seems to narrow the issue down to having a reverse proxy Apache.
An Example
The Login servlet on my web app attempts to store the user information in a session attribute then redirects to the MyCards servlet. I am using a redirect so that the URL will display mydomain.com/MyCards instead of mydomain.com/Login. The MyCards servlet attemtps to access the session attribute but finds nothing, and therefore redirects back to the Login servlet. This worked perfectly before deploying the project on my new server with SSL and domain name.
My Setup
Ubuntu 20.04 on DigitalOcean droplet
Apache Web Server (apache2) ... I have enabled mod_sessions, not sure if that's relevant.
Tomcat 9
Reverse proxy in Apache VirtualHost to Tomcat (I can post my .conf file if requested)
A redirect in Apache VirtualHost from HTTP to HTTPS
JDK 11
Possible Solutions
Using a forward instead of a redirect. The session ID is not lost when using requestDispatcher.forward(request, response);. As I mentioned above, I want the URL to reflect the destination for an intuitive user experience, which does not occur when using a forward.
Implementing your own session cookie, as in this answer, and manually storing sessions with a map, as in this answer, which strongly advises against such a facility. Based on my understanding, doing so poses security threats to user data. Also, if the browser is not passing the JSESSIONID cookie, I don't understand why it would choose to pass the manually implemented cookie unless the SameSite attribute is set to None (also bad).
Verifying that the webapp's context.xml does not have cookies="false" configured. Done that.
Using encoded URLs with response.sendRedirect(response.encodeRedirectURL(url));. Again, for the sake of having a clean URL (which the user could bookmark or type in) is preferable, and encoding the session ID into the URL is not.
Using relative URLs instead of absolute URLs...
"A session is only maintained if the redirection is being sent on the same port, host and webapp [and protocol?]. If redirection is done within the same application, using relative paths is the best practice." I tried both redirect_url = "/MyCards" and redirect_url = "MyCards", no luck.
Possible Reasons
Perhaps I am unknowingly switching between HTTP and HTTPS, which is a change in protocol and will not preserve the session ID. Of course, my intention is to remain secure and stay exclusively in HTTPS. Edit: I have set up another site on my server without SSL, and the issue persists. This seems to narrow the issue down to having a reverse proxy Apache. When accessing the web app directly on Tomcat (i.e. with <server_ip>:8080/MyWebApp), the session is tracked properly on redirect. However when using mydomain.com, the session ID is lost on every redirect.
Something to do with naked domains.
Other?
Edit: Maybe the issue is occurring because of the way the client, Apache, and Tomcat interact via the reverse proxy. Does the proxy cause the domain/port to change on every request/response?
My Questions
Why exactly is the session ID lost when using a redirect to a relative URL to a servlet in the same web app on the same server? Shouldn't the redirect occur entirely on the server-side, preventing a new request/session from being created? Since the relative URLs (which I thought would preserve the session) did not solve the issue, does this indicate some problem with my server setup (e.g. unintentional switching between protocols)?
What is the best practice for maintaining the user session ID, even when the user has cookies disabled? Is there no way around URL encoding when cookies are disabled? Or should the app be implemented exclusively with forwards rather than redirects? If so, is there a workaround to changing the URL to reflect the destination?
Note: this is my first post, so I don't have the reputation to comment. I will edit the post with any needed information.
We have Windows Active Directory, where all users are registered and use to login in Windows.
We have an Apache server configured to use LDAP to authenticate users in that Active Directory. It's setup so that, in PHP, all we have to do is call $_SERVER['REMOTE_USER']. Browser verifies user login in Windows and sends this data to Apache, which talks to LDAP to verify authentication. When LDAP authenticates, that code returns user's login, otherwise it returns null.
This way we can safely and easily authenticate users inside PHP and use their AD login to control access to our softwares. Another advantage is that we don't need a login page and not even have to handle passwords in variables: authentication is handled transparently to users and they are automatically logged to our softwares all the time, and their password never comes into our code.
I'd like to do the same thing with Servlet. I see no reason for it not happen if it works with PHP. But I can't find how to do it. I googled but couldn't find anything. Has anybody done something like that and could point me a way?
Standard authentication with login and password is working in Java. If I have domain, login and password, (that in Servlet would come from a login page) I can authenticate any user.
What you're looking to do is plug a SSO provider into your web app. There are several options, you will have to do your own research into what will work best in your environment. You might want to investigate the following security frameworks, which all enable SSO:
Apache Shiro
Spring Security
JCIFS
There are also commercial products like CA SiteMinder that do the same thing.
the HttpServletRequest object you have in the doGet and doPost methods on the servlet has the equivalent of PHP $_SERVER['REMOTE_USER'], it is called getRemoteUser().
Your post is tagged as Tomcat. You could add a "realm" in tomcat to do the Authentication.
I have no idea how you can not prompt for a password unless you are using some sort of SASL plugin to verify the user against LDAP.
$_SERVER['REMOTE_USER'] implies you are using "HTTP Authentication" header which would (AFIK) require a popup for the credentials. Perhaps this is transparent if only using IE against a Windows server.
There is an example of how to configure tomcat
I have web application deployed on websphere application server 7.0. User logins using /j_security_check. When session timeout occures session ivnvalidates but request.getUserPrincipal() is still not null. I expect it should be null. How to clean user principal?
I have found solution in sphere documentation.
In the administrative console, click Security > Global security.
Under Custom properties, click New.
In the Name field, enter com.ibm.ws.security.web.logoutOnHTTPSessionExpire.
In the Values field, enter true.
Click Apply and Save to save the changes to your configuration.
Resynchronize and restart the server.
In addition to solution provided by Vadim, I would like to share two links that describe a couple of alternative workarounds, and explanation of the mechanisms causing this seemingly counter intuitive mode of operation.
If you're using SSO (single sign on) between different applications, there may be a little drawback of using com.ibm.ws.security.web.logoutOnHTTPSessionExpire=true setting. This setting essentially invalidates LTPA token. Since security cache at server refreshes from LTPA token when it times out, invalidated LTPA will cause revalidation (login) of user for remaining applications [1].
Answer to Question 9 (which seems to be same as our question) at [2] provides ideas for two alternative workarounds for this problem, where you may time out authentication using servlet filters based on lifetime and inactivity.
[1]: Security Cache, LTPA Token, and Session Time Outs (requires login)
[2]: Q & A: Frequently asked questions about WebSphere Application Server security
The key thing to bear in mind is a valid/invalid HTTPSession is not the same as security.
They are completely different.
Once you are authenticated by the server, you can still have application work without any HTTPSession if you want to.
Once you are authenticatd by the server, you get a LTPA token returned to your browser and the LTPA token is active for say 2 hours (which is the default).
If your HTTP Session expires that does not affect the LTPA token if you don't to anything extra.
You could try: ibm_security_logout which would invalidate the LTPA token.
I guess with the later versions of Servlet API we do have a proper logout operation available which would eliminate the need for this.
HTH
Manglu
I've spent the last day or so looking in CAS and have managed to get the server working with a simple test application. When I enter a protected area, I'm redirect to a login page - when I log in, I'm taken back to my previous page.
From there, the next step would be deploy two client applications, log into client A, visit the client B protected area and have the system handle the authentication for me (since I'm already logged into client A).
This isn't actually working however. I have to log into the client B site whether I'm logged into the client A site or not.
CAS is running on Tomcat, client A and B are the same project deployed as separate wars on a single instance of JBoss AS 6.
Any ideas how I can achieve the suggested behavior?
EDIT: Yes, both are using CAS. The issue is that it doesn't seem to be recognizing that the user is already logged in. It's as if the CAS isn't able to determine that there is a 'link' between the two services and that when one service has been authenticated, the other service should be automatically authenticated.
I should note that at this stage, I am not using SSL within the application. I'm focused on getting a simple example up and going using HTTP before I look at introducing SSL.
Both of your applications need to be configured to use the CAS server for authentication. The normal procedure would be that application A redirects you to your CAS login page, lets you log in and redirects you back to A. If you then try to log into B, it checks with the CAs server whether you're already logged in and, if so, sends back information about the logged in user.
Again, both your applications need to support CAS as a login mechanism, which I am not sure about from your description.
Detailed description of the CAS protocol can be found here.
CAS was working without SSL in that it would take you to the login site and authenticate you correctly. The issue was if you tried to access via another site, it would ask you to sign in again.
Once I enabled SSL and tried it, it was working correctly. Once logged into client A, it would automatically authenticate you in client B. I had spent some time on the wiki and while it spoke of the importance of using SSL, I do not recall it explicitly stating that SSO will not work without SSL enabled. Maybe a warning should be added to the wiki?
If you want to focus on your applications and make your life easier, use a cloud provider for the CAS server: http://www.casinthecloud.com (free servers are available for tests).
A user is accessing a restricted web application with JAAS (on Glassfish 2.1). LDAPRealm is used, and authentication is successfully performed from LDAP. A password policy should be installed for the users, so that they are forced to change passwords, have passwords of certain complexity/length, password failures and last N passwords should be checked. Password policy of LDAP server used (OpenDS) supports all this, but it is not obvious at all how to receive this kind of information in JAAS FORM login we are using, so that the information (i.e. "Please change you password") can be displayed to the user.
Do you have any ideas how to go about implementing this? Using database only is not an option, users need to be in LDAP. What is not obvious is whether to use LDAP password policies at all, or have it all programmed in our web application. I would like to avoid this and use LDAP's native password policies.
Thank you for answers and best regards,
Bozo
Unfortunately, what you can do using JAAS is kind of constrained to a small set of operations that any login system can support. While LDAP supports a password policy, other login systems (eg keystores) may not, so JAAS cannot have code that requires this.
Hence, you'll have to talk to the LDAP server directly using either JNDI or possibly this library from Novell.
Got it. Have to use a SAM, since you cannot receive LoginException (with reason of login failure) in the existing auth mechanisms in Glassfish.
Answer is here: How to override j_security_check in glassfish?