Homegrown authentication, how do I remember and get the logged in user - jsf

I made a filter and a authentication in an application JSF it works very well but I'd like get the current user and I have no idea how to do that.
anybody could help me?
This method authenticates
public String Authenticates() {
FacesContext fc = FacesContext.getCurrentInstance();
EntityManager manager = getManager();
PersonDAO dao = new PersonDAOJPA(manager);
if (dao.login(getPerson().getEmail(), getPerson().getPassword())) {
ExternalContext ec = fc.getExternalContext();
HttpSession session = (HttpSession) ec.getSession(false);
session.setAttribute("userLogged", true);
getCurrentUser();
return "/index.xhtml" + "?faces-redirect=true";
} else {
FacesMessage ms = new FacesMessage("Email or Password Incorrect");
ms.setSeverity(FacesMessage.SEVERITY_ERROR);
fc.addMessage(null, ms);
return "/account.xhtml";
}
}

You're basically setting a boolean in session to indicate if an user is logged in or not.
if (userService.login(email, password)) {
session.setAttribute("userLogged", true);
}
This is rather simplistic. This can be improved by simply putting the user itself in the session.
User user = userService.find(email, password);
if (user != null) {
session.setAttribute("user", user);
}
Now, wherever you'd like to check if an user is logged in, instead of checking if userLogged equals true, you just check if user does not equal null.
User user = (User) session.getAttribute("user");
if (user != null) {
// User is logged in.
} else {
// User is not logged in.
}
This immediately solves your problem of getting the "current" user. It's this way already available by #{user}.
<p>Your email is #{user.email}.</p>
Unrelated to the concrete problem, you'd better not grab the raw HttpSession from under JSF's covers in a JSF artifact. That false argument in getSession(false) is also another thinking mistake and prone to NullPointerException later on. Instead, use ExternalContext#getSessionMap().
context.getExternalContext().getSessionMap().put("user", user);

Related

User logged in (ID), in back. Jhipster 4.1.1

In a Jhipster 4.4.1 application with Mongodb, JWT.
I need the user logged in for a query, and I do not know how I can retrieve it in a java controller (Resource)
In SecurityUtils I do not see how to get the ID
public static String getCurrentUserLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
String userName = null;
if (authentication != null) {
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
userName = springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
userName = (String) authentication.getPrincipal();
}
}
return userName;
}
I can capture the user ID logged in, without consulting the database.
Thank you
If you need the current user, then you can query against login as given by getCurrentUserLogin() in your question because it's unique anyway.
If you really want the ID, then have a poke around AccountResource and you'll see that UserDTO and User have a .getID() method.

Why can't I log in as the seeded user?

I'm working on a new ASP.NET MVC project, using individual accounts stored in the database for authentication. Here's my class that will seed the database with sample data every time I test:
public class DevelopmentInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
base.Seed(context);
var applicationUserManager = new ApplicationUserManager(new UserStore<ApplicationUser>(context));
var sampleUserOne = new ApplicationUser { UserName = "SampleUser", Email = "sample#example.com" };
var result = applicationUserManager.Create(sampleUserOne, "aaaaaa");
if (!result.Succeeded)
throw new Exception();
context.SaveChanges();
}
}
The Login action is as it is in the template:
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.Email, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The description of problem is very simple: Trying to log in using the seeded user's credentials fails.
Specifically, the FindAsync method returns null, even though the user is present in the database - FindByEmailAsync does find the seeded user.
However, creating a new account works and allows me to log in.
Why can't I log in as the seeded user, even though I can register a new account and log in using that?
I'm suspecting it has to do with how the passwords are hashed, but I don't know how to confirm this.
Am I seeding the account wrong? Should I not be creating a separate ApplicationUserManager in the Seed method? If not, how should I get one in order to call Create? I'm trying to understand how the new system works, before ending up locked out of my account or the users end up locked out of theirs in a deployed application.
The following code:
var user = await UserManager.FindAsync(model.Email, model.Password);
is expecting the userName to be passed in, not the email address.
This simple change should take care of things:
var user = await UserManager.FindAsync(model.UserName, model.Password);
If you see the definition of PasswordSignInAsync, it requires the username string and not the email. Maybe the reason why the UI for login ask for email is because of the autogenerated code where the email would be equal to username inside the controller.

How to restrict access if user is not logged in

My project has a template main.xhtml and three views login.xhtml, dashboard.xhtml, new.xhtml. Once I login in login.xhtml, the LoginBean will validate and if successful, then it will take to dashboard.xhtml. If user need to create an new record he click the new button which takes to new.xhtml.
But the problem is, if dashboard.xhtml is requested directly from browser, then it is working without login. Do I need to check every view that the user is logged in? How can I achieve this?
It sounds like as if you're homegrowing authentication. In that case, you need to also homegrow access restriction. That is normally to be done using a servlet filter.
Assuming that you're logging in as follows in a #RequestScoped bean,
public String login() {
User user = userService.find(username, password);
FacesContext context = FacesContext.getCurrentInstance();
if (user != null) {
context.getExternalContext().getSessionMap().put("user", user);
return "dashboard.xhtml?faces-redirect=true";
} else {
context.addMessage(null, new FacesMessage("Unknown login, try again."));
return null;
}
}
Then you can check for the logged-in user in a #WebFilter("/*") filter as follows:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
User user = (session != null) ? session.getAttribute("user") : null;
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loginRequest = request.getRequestURI().startsWith(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);
if (user != null || loginRequest || resourceRequest)) {
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURL);
}
}
Note thus that this would continue the request when the user is logged in, or when the login page itself is requested directly, or when a JSF resource (CSS/JS/image) is been requested.
If you were using container managed authentication, then the filter would have been unnecessary. See also How to handle authentication/authorization with users in a database?

Is it possible to programmatically set Principal in JSF+EJB

I want to retrieve username using EJBContext.getCallerPrincipal()
public class GlobalInterceptor {
#EJB
private AuditLogsEJB auditLogsEJB;
#Resource
private EJBContext context;
#AroundInvoke
public Object auditLog(InvocationContext invocationContext) throws Exception
{
System.out.println(context.getCallerPrincipal()); //it outputs "ANONYMOUS"
}
}
However I don't have any security realm, I don't have any <security-role> or <group-name> defined because the username/password is sent to a remote application to validate. But for convenience sake I still want to use the Principal class to get username and role.
Is there a way to programmatically set Principal(username and role) in JSF managed bean or any EJB, so that the interceptor can retrieve it? e.g.:
String role = authenticationWSPort.validate(username, password);
if(role != null)
{
Principal p = new Principal(username);
p.getRoles.add(role);
FacesContext.getCurrentInstance().blah-blah.blah-blah.addPrincipal(p);
//I am looking for something similar to the 3 lines above
}
else
// invalid username and password
Obviously the correct way to do this is by setting up a realm, and using that.
Perhaps you could create & configure your own Realm implementation that would let you create users on the fly, prior to invoking request.login(username, password) in a servlet.
Or.
If you -really- want to futz with the underlying Request, it's possible, but it's application-server specific, and goes something like this, assuming you're in a tomcat (catalina) based container:
if (request instanceof RequestFacade) {
Request unwrapped = null;
RequestFacade rf = RequestFacade.class.cast(request);
try {
Field requestField = rf.getClass().getDeclaredField("request");
requestField.setAccessible(true);
unwrapped = Request.class.cast(requestField.get(rf));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
unwrapped = null;
}
if (unwrapped != null) {
unwrapped.setUserPrincipal(... your principal construction here ...);
}
}

Programmatically control login with Servlet 3.0

I've tested the default security containers in Glassfish 3.0.1 and come to the conclusion that I won't spend any more time on that. Instead I want to control the verification myself. But I need some guidance to get me on right track.
At the moment I have a UserBean that has a login/logout function (see below). And I don't want to use the *j_security_check* built in container, but use core JSF 2.0.
My questions are;
Do I need a ServletFilter to redirect traffic if the user is not logged in (if accessing certain folders)?
How do I store User Pricipals after the user successfully logged in ?
Appreciate any help or link to a example, greetings Chris.
PS. Excuse me for clustering two questions together
#ManagedBean
#SessionScoped
public class UserBean {
private AuthenticateUser authenticateUser;
...
public String login() {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
JsfUtil.log("Username : " +authenticateUser.getUserName());
JsfUtil.log("Password : " +authenticateUser.getPassword());
AuthenticateUser authRequest = authenticationFacade.find(authenticateUser);
try {
if(!authRequest.equals(authenticateUser))
return "/loginError";
request.login(authenticateUser.getUserName(), authenticateUser.getPassword());
return "";
} catch(ServletException e){
JsfUtil.addErrorMessage(e, "Incorrect username or password, please try again.");
return "/loginError";
}
...
public String logOut() {
String result = "/index?faces-redirect=true";
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.logout();
} catch (ServletException e) {
JsfUtil.log("Failed to logout user!" +e.getRootCause().toString());
result = "/loginError?faces-redirect=true";
}
return result;
}
When you want to utilize request.login(), then you should really have configured a Realm in the container which represents the user database. But you seem to have replaced the Realm by some AuthenticationFacade. In this case, the request.login() is not useful for you.
You need to just put the user in the session scope and intercept on that. Here's a kickoff example:
#ManagedBean
#SessionScoped
public class UserManager {
#EJB
private UserService userService;
private String username;
private String password;
private User current;
public String login() {
current = userService.find(username, password);
if (current == null) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unknown login, try again"));
return null;
} else {
return "userhome?faces-redirect=true";
}
}
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "index?faces-redirect=true";
}
public boolean isLoggedIn() {
return current != null;
}
// Getters/setters (but do NOT provide a setter for current!)
}
When taking authentication in hands like this, then you definitely need a filter to restrict access. When using container managed security you would typically specify it as <url-pattern> of <security-constraint> for this. But without it, you've to take it in your hands. It's good to know that JSF managed beans are keyed by their managed bean name in any scope.
UserManager userManager = ((HttpServletRequest) request).getSession().getAttribute("userManager");
if (userManager == null || !userManager.isLoggedIn()) {
((HttpServletResponse) response).sendRedirect("login.xhtml");
} else {
chain.doFilter(request, response);
}
Map the above filter on the desired URL-pattern.
When you still want to reconsider using container managed authentication, then the following related answers may be useful:
Java EE Login Page Problem (and Configuring Realm in Glassfish)
Performing user authentication in Java EE / JSF using j_security_check
Be aware if you are if you are using JDBC realm security. There are some fixed/expected words in the fields where you configure the realm in the Glassfish admin console.
In the JAAS Context: filed, you have to type: jdbcRealm. This keyword makes the security container use the expected JDBC realm. If you type something else, it won't work.
Here is good example, done by Gordan Jugo; Netbeans/Glassfish JDBC Security Realm

Resources