• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Best practice for secure login authorisation

 
Ranch Hand
Posts: 68
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am trying to make a JSF 2 page that would require secure user login password protection. Obviously proper password validation and a user session id validation are a crucial part of this problem (on the 'after login welcome' page the site has further navigation rules to different pages).

I spent some long time browsing for solutions and got a little bit swarmed with the information. It seems that for session id HttpSession objects are often used - is it a safe practice? How and where to handle the logic for that? In a the bean constructor? - although I am quite lost in the issue, this does not seem quite secure...

And password validation is also another problem. Using simple validators like in 'Core JSF' are useful i.e. for range verification, but don't look safe for proper login-password validation.

I am quite sure that this is not an impossible task and most likely is described somewhere. I found this BalusC blog post which is about session tracking, but here cookies are used for storing session ideas and I don't want this at all - I want need to keep the session valid for i.e. 10 minutes. I don't want to annoy anybody with the old 'first search carefully than ask' syndrome, but for an inexperience side choosing the right security/authorization approach is quite hard.

 
Marshal
Posts: 28177
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I get the feeling that the problem isn't so much that you can't find solutions, it's more like you don't understand what the potential problems are. Is that right?

If I'm wrong, then could you list the problems you are trying to solve? Your post doesn't really do that; perhaps you were assuming that everybody already knew what problems were associated with "secure user login password protection".
 
Adam Kronicki
Ranch Hand
Posts: 68
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok I'll try to explain in a more clear form.

I have a JSF project that needs to be protected by a login username/password first page. Additionally I need a session id tracking system to validate the user on further page navigation. So this is the general problem. I think that 2 mechanism are crucial here:

-proper password validation
-proper user session key tracking

My solution for that is to make a session scoped Bean with a login/password validator and a session key generator. Then in further pages in the Bean constructors I could check this bean's session key. However, doesn't seem to be a safe solution is it? So I am trying to ask for the proper solution to this situation. There might be also other important aspect that need to be taken care of in order to keep this safe and secure in JSF, which I did not thought about earlier. Maybe sb. with more experience can draw my attention to other issues I should look into.

 
Saloon Keeper
Posts: 27752
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I strongly recommend you forget about trying to invent a security system of your own for JSF. I've worked with J2EE since before JSPs were invented and seen probably dozens of webapps, many in critical sectors such as finance. And not ONE of the ones with user-designed security systems were even remotely secure. Most could be broken in under 5 minutes by unskilled people.

J2EE comes with a very strong security system that can block a lot of unauthorized activity before it can even reach (and therefore exploit) the application itself. Just about any basic J2EE book will give you a description of how web.xml is configured to employ it. And then proceed to use a user-defined "logon system" as a code example.

When you use J2EE standard container-managed security, the login process is handled on an as-needed basis by the server itself. You can provide the login page images, but you can provide no login logic. You never actually get informed when a login occurs, in fact. You define security roles, and map URL patterns in web.xml to restrict what roles may access those patterns.

Sessions are where J2EE keeps security context. Since session objects never leave the server, they cannot be analyzed or tampered with by ill-meaning webapp clients. The session ID is just a hash key that has no specific meaning other than making it virtually impossible for an invader to break into someone else's session. You don't need to concern yourself with this mechanism, as the framework does it all transparently and automatically.

JSF integrates into the standard J2EE container security system almost seamlessly. The only JSF-specific quirk you need to address is that since JSF URLs don't always track the page resources like URLs do in most frameworks, and since container-managed security is based on the URL, not the resource, you have to use the "redirect" navigation property on rules that navigate to secured pages.
 
Adam Kronicki
Ranch Hand
Posts: 68
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:I strongly recommend you forget about trying to invent a security system of your own for JSF. I've worked with J2EE since before JSPs were invented and seen probably dozens of webapps, many in critical sectors such as finance. And not ONE of the ones with user-designed security systems were even remotely secure. Most could be broken in under 5 minutes by unskilled people.

J2EE comes with a very strong security system that can block a lot of unauthorized activity before it can even reach (and therefore exploit) the application itself. Just about any basic J2EE book will give you a description of how web.xml is configured to employ it. And then proceed to use a user-defined "logon system" as a code example.

When you use J2EE standard container-managed security, the login process is handled on an as-needed basis by the server itself. You can provide the login page images, but you can provide no login logic. You never actually get informed when a login occurs, in fact. You define security roles, and map URL patterns in web.xml to restrict what roles may access those patterns.

Sessions are where J2EE keeps security context. Since session objects never leave the server, they cannot be analyzed or tampered with by ill-meaning webapp clients. The session ID is just a hash key that has no specific meaning other than making it virtually impossible for an invader to break into someone else's session. You don't need to concern yourself with this mechanism, as the framework does it all transparently and automatically.

JSF integrates into the standard J2EE container security system almost seamlessly. The only JSF-specific quirk you need to address is that since JSF URLs don't always track the page resources like URLs do in most frameworks, and since container-managed security is based on the URL, not the resource, you have to use the "redirect" navigation property on rules that navigate to secured pages.



Basing on what I found (mainly your posts Tim) I saw that container based form should be the best option here. I am now trying to implement this using links like this. Or at least I hope this is the right track. However now some new questions appear:

-if the login form must be a simple html form, can I somehow retrieve the login value further in the application? After login on the page I would like to show "Welcome star_warrior" and also I would need the star_warrior value for an 3rd part DB to show only user relevant content. Is it possible to get the login in further JSF beans logic?

-One thing I don't like about this is that in case of an invalid user/password event, the container-based system would automatically redirect me to an error page (which I must define). Instead I would rather stay on the same page and just show a red sign 'Invalid user or password' under the login input. But that again must be a JSF page which could uses business logic and an old simple 'rendered' tag attribute. (How)Can I achieve this using container form based security?

-As for my previous session question- could it be that I can only define the session time in project web.xml? And I don't need to validate session tracking over the next beans?

-After login some of my pages use richfaces components and some of my beans need to use the richfaces @KeepAlive annotation - could this lead to some problems for the container?

-finally just for the last paragraph confirmation - you suggest that instead of normal JSF navigation rules I must always use </redirect> tags?

 
Tim Holloway
Saloon Keeper
Posts: 27752
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The login form in container-managed authentication must be an HTML or simple JSP page. It cannot rely on a dispatcher servlet or other complex control mechanism such as are used by systems like JSF or Struts. That's because the server itself send out the login/loginfail form as needed and not via a login URL request. In fact, there is no URL you can use to present the login form. If you just access the login form manually, it doesn't work, because a straight page fetch of the form won't be hooked into the container's authenticator. As far as the annoyance of keeping 2 separate pages (login/loginfail). I don't mind myself because my login/loginfail pages are pretty minimal. I usually just clone the login page and put a failure message on the result to make my loginfail. Login pages should be kept simple - they don't yet have access to secure parts of the app (since you're not yet logged in), and the more stuff that you put on a login page, the more likely you'll introduce a security issue. I especially don't like menus on my login forms.

The items entered into the login form are not accessible to the application for security reasons. However, a userId does get added to the HttpServlet request once you're logged in and you can use that as both a way of testing for being logged in (it's null until after successful login) and as a key to obtain user-specific fined-grained security control, user preferences, and stuff like that. Because container-managed security is designed to allow both app-specific logins and Single Signon users, the only definite way to route a user to a post-login "welcome" page is to monitor HttpServletRequests and detect the point where a given session's userid stops being bull. A ServletFilter can do that and reroute a request to the welcome page.

I don't recommend forcing people to a post-login welcome page myself. It makes it impossible to make secured URLs bookmarkable.

I believe that webapps have some ability to control their session timeout, but I'd have to RTFM. ANY HTTP request made to the server, whether it's RichFaces or just a simple timed page refresh meta tag will reset the user's session timeout counter, so if you want to make a refreshing page time out, you'll have to forcibly time it out based on whatever selection criteria suit you. This is another thing that is generally best handled in a servlet filter, where you'd scan incoming URLs and reset or timeout based on whether you considered them as "idle" or "active" URLs.

Finally, you only need the redirect JSF option when navigating to secured URLs. For other URLs, it's optional.

 
Adam Kronicki
Ranch Hand
Posts: 68
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks Tim. You truly help me on this. I figured out some solutions to most of the points. I am now facing the problem of reading the user role inside a bean. My page does not have separate pages for admin, but rather extended functionality for that role (additional components appear on the page etc.). I am just wondering if it is save by solving it by a simple bean logic (reading somehow the role, or just the login value by the Principal object) or is i done somehow in a more decent way. I think I saw this problem why browsing through pages couple of days ago so I'll try to get back to it. Of course if you have any quick comments don't be ashamed :>

Because container-managed security is designed to allow both app-specific logins and Single Signon users, the only definite way to route a user to a post-login "welcome" page is to monitor HttpServletRequests and detect the point where a given session's userid stops being bull. A ServletFilter can do that and reroute a request to the welcome page


I guess the problem you describe concerns a situation when I have another 'login' application on my Tomcat? In this situation if sb. logs in to another application it would grant him access to others who use base-form container validation. I don't anticipate such situation in the future, but just in case - I don't fully understand how to prevent this, from your description. What I get is that I need a ServletFilter which redirects to the welcome page (or other further pages as it is in my case). But how to detect this occurrence? 'and detect the point where a given session's userid stops being bull' This part I don't really get...
 
Tim Holloway
Saloon Keeper
Posts: 27752
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One of the cardinal rules of security is "never volunteer". As an example, in the J2EE web security system, you cannot "read" a role, you can only ask if the user is permitted that role. J2EE roles are, BTW not containers for users, but rather attributes of users, so a user may be authorized in several roles, which is actually more powerful than the other way around.

To determine if a user is authorized for a role, you query the HttpServletRequest, and since that involved container-specific functionality (and JSF-specific functionality!), I set up a separate security class to pass that function off to, rather than hard-coding it in the business logic. That allows me to put all the security logic - both J2EE standard and proprietary - in one place.

Unlike Struts, most JSF tagsets don't support direct querying of roles in the view definition. However, since the primary use on the view side is to control rendering, it's not as big a hardship as might appear, since you can do the querying in the "rendered=" attribute. It is important to remember, however, that when using a multi-role view that it's not enough to depend on what gets rendered. You should also check roles on the action methods as well.

As far as SSO goes, each webapp has its own security Realm definition. If you want to force a user to specifically login to a certain app, you configure the app with a non-SSO Realm. However, SSO is more convenient for most users, and almost essential when doing portals (logging into 6 different portlets is a bit of an insult!).

Detecting a login is easy in a ServletFilter, even if the actual login was done on another app in an SSO Realm. Until the user is logged in, the UserPrincipal and userid properties of the incoming HTTPServletRequests will be null. Since JSF often creates sessions long before the user logs in, you can store the request's user ID in a session attribute - creating it if it didn't already exist. When there's a change from null to not-null, the user has just logged in. If there was no session, the first request has happened right after login. When either of these happens, just forward the incoming request to your welcome page.
 
reply
    Bookmark Topic Watch Topic
  • New Topic