Your first - and biggest - problem is in using JSF for the login form.
When the container security mechanism takes over and presents a login, the code that handles the login process is
not application code. JSF only works when the process is dispatched from the FacesServlet, and the container login is really only expecting a basic HTML form, although it can work with vanilla
JSP pages. Depending on the server, not only login/loginfail screens, but welcome screens and exception error screens done in JSF may fail to operate properly, as all of these are invoked internally by the server.
Beyond that, if I feel the need to attach a user profile as a reference object based on the login userId, I'm most likely to do that on-demand, rather than explicitly and immediately. Saves overhead if I don't need the object. I actually normally access resources like that via a special static class (JSFUtils) that I write and put my container- and framework-dependent services into in order to keep the bulk of the app in POJO form. Doing that makes my code more portable and easier to
test offline.
I don't recommend using a JSF listener to do what you are doing in any event, because it assumes that all application code MUST be JSF, and there are situations where a non-JSF
servlet or JSP may be more appropriate, especially if you are generating non-HTML output like PDF's or Excel spreadsheets. The common denominator between JSF and non-JSF can be found in a ServletListener, where it's a lot easier to obtain the userId than it is in JSF code, especially since the FacesContext doesn't exist during non-JSF URL processing, but the request and response objects are always directly accessible in a ServletListener. Once the ServletListener has obtainer the user profile object, it simply stores it as a session-scope object, where ordinary
J2EE code can use it in the traditional way and JSF can use it as a session-scoped backing bean.