Question

Setup:

  • glassfish 3.1.1
  • JSF 2.1
  • jdbcRealm with postgreSQL

After typing valid user credentials to the login form I get logged in and redirected to the next page. But if I leave that page and go to another one, which is in the allowed url-pattern of course, I get the "HTTP Status 403 - Access to the requested resource has been denied". After that I can not visit any site of the webapp anymore.

The login only works, if I set the Standard-Realm in glassfish's server-config/security to my own realm!

I get one warning in the server log at deploy time:

Warnung: Keine Principals zugeordnet zu Rolle [USER].
(Warning: No principals mapped to role [USER])

If I remove the JSESSIONID with Chrome Debugger, I can login again. Looks like the Session gets destroyed on the server side after visiting one allowed website or something?!

I attached some relevant sources. I think it has nothing to do with the Realm and so on, since the login mechanism works and there are no exceptions...

web.xml

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>jdbcRealm</realm-name>
    <form-login-config>
        <form-login-page>/faces/login.xhtml</form-login-page>
        <form-error-page>/faces/loginError.xhtml</form-error-page>
    </form-login-config>
</login-config>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>User</web-resource-name>
        <url-pattern>/faces/user/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>ADMIN</role-name>
    </auth-constraint>
</security-constraint>

glassfish-web-app.xml (Added manually)

<glassfish-web-app>
<security-role-mapping>
    <role-name>USER</role-name>
    <group-name>USER</group-name>
</security-role-mapping>
</glassfish-web-app>

login.xhtml

<h:form>
<h:outputLabel for="usernameInput">
    Username:
</h:outputLabel>
<h:inputText id="usernameInput" value="#{authBackingBean.username}" 
             required="true" />
<br />
<h:outputLabel for="passwordInput">
    Password:
</h:outputLabel>
<h:inputSecret id="passwordInput" value="#{authBackingBean.password}" 
               required="true" />
<br />
<h:commandButton value="Login" 
                 action="#{authBackingBean.login}" />

AuthBackingBean

@Stateless
@Named
public class AuthBackingBean {

    private String username;
    private String password;

    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String login() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        try {
            request.login(this.username, this.password);
        } catch (ServletException e) {
            context.addMessage(null, new FacesMessage("Login failed."));
            return "loginError";
        }
        return "user/index";
    }

    public void logout() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        try {
            request.logout();
        } catch (ServletException e) {
            context.addMessage(null, new FacesMessage("Logout failed."));
        }
    }
}

P.S: I'm really disappointed about oracle's f***ed up documentation since it contains many logical errors, typos and copy/paste errors. It's unstructured, hard to read and overloaded. (sorry but that had to be said)

Was it helpful?

Solution

This is hilarious, after hours of testing and writing this question I found the answer one minute after posting it:

I activated "Standard-Principal auf Rollenzuordnung" (Standard-Principal to Rolemapping) in server-config/security and now it works.

OTHER TIPS

After following this documentation for Roles, Principals and Role Mapping I have figured out that instead of enabling the "Standard-Principal to Role Mapping" you could define a glassfish-web.xml (under WEB-INF) descriptor with the mapping of your Roles.

Example:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD
GlassFish Application Server 3.1 Servlet 3.0//EN"
        "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd"
        >

<glassfish-web-app>
    <context-root>/istop</context-root>
    <security-role-mapping>
        <role-name>described-role</role-name>
        <principal-name>user-that-should-have-this-role</principal-name>
        <group-name>equivalent-role-in-db</group-name>
    </security-role-mapping>
</glassfish-web-app>

make sure that described-role used in <role-name /> matches either a definition in web.xml using <role-name /> or @DeclaredRoles

Finally, if I understand correctly what the option "Standar-Principal to Role Mapping" does, is that it is expecting a Role from the realm mapping Goup Name Column matching with the one defined in your application, so any user in your database must have a Role that matches one of the defined roles.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top