I have a Java EE application that uses JDBCReal as JAAS Context for authentication on GlassFish 3.1. And below is the authentication code in a JSF2.0 managedbean -
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
if (request.getUserPrincipal() != null) {
request.logout();
}
if (request.getUserPrincipal() == null) {
request.login(this.username, this.password);
}
I am trying to add some admin functionalities (like create/delete/update/disable user). I am almost done with all of them except for the "disable" one, which is confusing me on how to proceed.
The only way that I can think of right now is to add a field, something like "status", in the "users" table, which will have a value ("enabled" or "disabled"). And check that "status" before doing the authentication.
Is that how I should do it considering that I am using JAAS (JDBCRealm)? Or, is there some other (standard) way?
I am trying to see, if there is someone here who has some experience in this area and can point me towards the right direction.
I suppose you manage your users table through JDBC/JPA.
In unix/linux the passwd -l change the hash to an invalid value. From man passwd:
-l This option is used to lock the specified account and it is
available to root only. The locking is performed by rendering
the encrypted password into an invalid string (by prefixing the
encrypted string with an !).
In practice an unlocked account from /etc/shadow:
test:$6$c7Lz2A2l$8AoSBy8C2U7uUns4aDRP2J/QRzUOYF...o69XPR/:15259:0:99999:7:::
And the same account after passwd -l test:
test:!$6$c7Lz2A2l$8AoSBy8C2U7uUns4aDRP2J/QRzUOYF...o69XPR/:15259:0:99999:7:::
The prefixed value is invalid because hash functions always return the same number of bits. If your stored value is longer than that length they will never match. You can do the same with your hashed passwords - just prefix the password with an ! (or any other string) through JDBC/JPA.
Of course this does not work with plaintext passwords.
Another solution is removing the user's roles from the database. In this case the user could login but if you set up the security-constraints well in the web.xml the user wouldn't be able to do anything (except logout).
Related
I have a java web application. I implemented a login system, with user rights a while ago, and included a "remember-me" functionality with unique string ID's saved client side in cookies.
This has worked ok, except for the fact that the remember me functionality always fails on first page load whenever a new session starts. However, since most users access a non-restricted page first, complaints has been absent. Nonetheless, I'd like to fix it. Here is what I have learned.
I use implementations of javax.servlet.Filter to check if a user has rights to se a page. for example baseURL/pages/admin/*. Filter interface has a method called doFilter, which accepts a ServletRequest, and ServletResponse object as parameters. I cast these to HttpServletRequest and HttpServletResponse. The HttpServletRequest gives me access to cookies and session.
If i iterate through the cookies, I find my "remember"-cookie, with the unique ID as a value. However, this ID is wrong.
Now, in my Servlet class, which follows the front controller pattern, I also have a check for user logged in, and remember me. But because this is executed after the filter, it is not sufficient to check only here. Still, I do want to check for every page, even if it is not restricted, as it changes the layout slightly if you are logged in.
The java HttpServlet service method accepts a HttpServletRequest and HttpServletResponse object. In other words, no need for casting here. Funny thing is though, If i try to access my cookies from here, it will give me an identical id for the session cookie, but a completely different uid for my "remember"-cookie.
I have found that my system adds new remember cookies for each of my filters. And if I try to access a page in the admin path, both cookies from /webapp/pages, and cookie from /webapp/pages/admin will be present in chrome inspector. When accessing the cookies in the filter, the /webapp/pages/admin is the only one that will exist. Oppositely, the /webapp/pages is the only one that will exist in the front controller servlet service method.
I guess this is because of the mapping of said filter and servlet, which matches the path of the cookie. The problem is that I never intended there to be cookies stored hierarchically, and only want the one to be stored, at /webapp/pages. My system has now stored plenty of these deeper pathed cookies all over my client network, and whenever a user logs in and out, they might get out of sync with a new uid.
Is there a way I can force retrieving the /webapp/pages cookie over the /webapp/pages/admin cookie? Or is there a way to retrieve both? I could just check both uid's for a match if I can manage that (hence the title of my question)
For the future, I have made sure to set the path of cookie storage, so that the same path will be used, but as the cookies has a year to expire, this will not solve my problems for a long time, unless I find a way to check the correct cookie.
The answer to the title question is; you can't.
The browser will decide which cookies it deems most relevant, and there is nothing you can do to change that. When your filter is mapped to a subpath, and servlet is mapped to a higher path, you will get the best matching cookie for each path.
The specific problem in the question text is caused by a bad coding pattern. The remember me cookies should be stored at a specific path when created, in this case /webapp/pages. This will prevent the cookie from being created as multiples, in hierarchical paths.
There is still the problem of already existing cookies client side. These can be handled by adding the following javascript in a central area of your code, somewhere where you'd know that all users will encounter it:
document.cookie = 'remember=; path=/webapp/pages/user; expires=' + new Date(0).toUTCString();
document.cookie = 'remember=; path=/webapp/pages/admin; expires=' + new Date(0).toUTCString();
This will set the unwanted cookies to expire at an already past date, effectively deleting it.
Now only one cookie with name "remember" will exist for the domain, and both servlet and filters will fetch the same cookie, regardless of their mapped subpaths.
I'm working on an application that requires the use of LDAP for authentication. Every student at my University has a MyID. There is a wiki on one of the University's pages that states:
To form the full DN (distinguished name) of a MyID, use this format:
cn=MyID,ou=users,o=uga (where MyID is replaced by the user's MyID).
In LDAP, a NULL password or username is considered an anonymous bind
attempt (bind is the LDAP word for authentication) and will always
succeed. Your application should either filter out NULL password
strings or validate the successful bind attempt. To validate a bind
attempt, have your application attempt to read the attribute
ugaAuthCheck. The attribute should have the value of 'y' (the letter y
without the quotes).
I am using JLDAP to handle connecting to the LDAP server over SSL. I am able to search the directory once connected, but I'm at a loss as to:
To validate a bind attempt, have your application attempt to read the
attribute ugaAuthCheck.
I bind to the server with this JLDAP method:
lc.bind( ldapVersion, loginDN, password.getBytes("UTF8") );
How does one read an attribute off of a bind in JLDAP? I've been digging through the JLDAP source but I'm not really seeing what an attribute is....so perhaps its actually called something different?
There are JLDAP Samples provided by Novell.
You might want to look at the "CompareAttrs.java" or "Search.java" code for some ideas.
-jim
I work on google app project and I am struggling a bit with java oauth library (1.10.1-beta).
I followed closely : http://code.google.com/p/google-oauth-java-client/wiki/OAuth2#Authorization_code_flow
Problem is that I dont know from where I should get userId or userEmail. I know there is userinfo API but I am actually trying to create Credentials, so I cannot access userinfo API AFIAK.
My application work nicely on localhost (because of test#example.com user is always there) but fails miserably when deployed in google engine environment (NullPointerException user.getUserId()).
// we ask for token because we got authCode
GoogleTokenResponse gTokenResponse = userUtils.getFlow().newTokenRequest(authCode).setRedirectUri(userUtils.getRedirectUri()).execute();
//trying to search for user email / id / whatever
User user = UserServiceFactory.getUserService().getCurrentUser();
//user is null -> nullPointerException is thrown
userUtils.getFlow().createAndStoreCredential(gTokenResponse, user.getUserId());
Could you please point out a flaw in my use-case or give me a hint ? I searched a lot in SDK samples,Stackoverflow and here but there is not many implementations.
PS: In method AuthorizationCodeFlow.createAndStoreCredential(...) is userId mandatory only when you use persistent storage for Credentials and yes i am using that so userId cannot be null in my case.
Thanks.
You are doing OAUTH (authorization) before you identified your user (authentication). You must redirect your user to the login page when he is not logged in :
UserServiceFactory.getUserService().getCurrentUser() == null
You do that by redirecting the user to the loginUrl :
String loginUrl = userService.createLoginURL(request.getOriginalRef().toString());
The next time the user arrives at your app, he will be logged in, and you can ask for the userId.
I need to implement a simple remember me option in a java servlet with cookies, without using any advanced framework.
First, at login, I create the cookie and send it in response to the browser (client). The value to be stored in the cookie is just a simple hash from username + password.
How should I manage the incoming request from the browser, sending the cookie?
My approach is to check between registered users if there is any user that has the hash from username + password equal to the value in the cookie?
Is this approach correct?
Also, I did not understand exactly what is the mechanism of the expiration date. Does the browser delete the cookie when it is expired, it not, how do I check if the cookie is expired?
As long as you're not using HTTPS the method you suggest is highly insecure. I would suggest to generate some sort of session token (e.g. use java.util.UUID.randomUUID()) and set this as cookie and store it somewhere on the server side so you later can identify the user associated with this session id in the cookie.
This gives you the opportunity to reset a certain session cookie if you think there's some fraud happening and there's no direct relation between the user name/password and the cookie id you use. But note: this method is still vulnerable to a man-in-the-middle attack.
Concerning the expiration: yes the cookie becomes invalid and might get deleted by the browser if it is expired. But you can set the cookie to something in the year 3000, so it lives forever.
I have an Ldap directory synchronised from a microsoft active directory.
This Ldap contain many account, each account have a password attribute.
I must develop a java program where a user have to log with his AD login and password, but i don't know the method employed to correctly encrypt the password typed.
I need it to compare with the ldap password.
I also need to bind new account with the same password encryption.
Anyone know how to do?
Well first of all you can use a BIND with SSL, but that's considered kind of the lame way to go about it and may be disabled on some systems. A truly secure way is using SPNEGO-GSS, and this is not trivial. You have to learn and understand about Kerberos. That's a long topic but you can start with reading and going through everything here
I've found the solution with spring,
here the method to test login/pass couple :
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("cn", login));
boolean authentifie = ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);