Search code examples
jakarta-eeglassfishjaas

JAAS Forbidden Error (403) when accessing a protected URL


I have just started working on a pet project using JSF, JPA, and EJB on a GlassFish server and I'm currently setting up the authentication module using JAAS. It's about complete now except for a bug for which I can't figure out a solution.

My Premise

I have a single table users in the database in which I store all email, password, and role (not normalized for now). I don't have any provisions for groups. Users are simply assigned a single role.

The data I've is something like:

username        |   role   |      password
mannyee            Member        (sha-256 value)  

I've set up a JDBC realm (findRoomieRealm) in the GlassFish server. The attributes setup there are:

JAAS Context    :   jdbcRealm
JNDI        :   jdbc/sample
User Table  :   users
User Name Column:   email 
Password Column :   password
Group Table :   users
Group Name Column:  role
Password Encryption Algorithm:  SHA-256
Group Table User Name Column: (empty)

And then I setup the following in my web.xml

<welcome-file-list>
    <welcome-file>pages/user/dashboard.xhtml</welcome-file>
</welcome-file-list>

<!-- Protected area definition -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted Area</web-resource-name>
        <url-pattern>/pages/user/*</url-pattern> 
    </web-resource-collection>

    <auth-constraint>
        <role-name>MEMBER</role-name>
    </auth-constraint>
</security-constraint>


<!-- Login page -->
<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>findRoomieRealm</realm-name>
    <form-login-config>
        <form-login-page>/faces/login.xhtml</form-login-page>
        <form-error-page>/faces/error.xhtml</form-error-page>
    </form-login-config>
</login-config>

<!-- System roles -->
<security-role>
 <role-name>ADMIN</role-name>
</security-role>
<security-role>
 <role-name>MEMBER</role-name>
</security-role>

My Issue:

When I try to access a protected page, Login page does intercept the request where I can successfully login to the system. I can verify this by the log generated by the server:

Fine:   [Web-Security] Setting Policy Context ID: old = null ctxID = findRoomie/findRoomie
Fine:   [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/j_security_check" "POST")
Fine:   [Web-Security] hasUserDataPermission isGranted: true
Finest:   Processing login with credentials of type: class com.sun.enterprise.security.auth.login.common.PasswordCredential 
Fine:   Logging in user [mannyee] into realm: findRoomieRealm using JAAS module: jdbcRealm
Fine:   Login module initialized: class com.sun.enterprise.security.ee.auth.login.JDBCLoginModule
Finest:   JDBC login succeeded for: mannyee groups:[Member]
Fine:   JAAS login complete.
Fine:   JAAS authentication committed.
Fine:   Password login succeeded for : mannyee
Fine:   Set security context as user: mannyee

But I get a Forbidden status on the requested page (immediately after login) and on the log file I get:

Fine:   [Web-Security] Setting Policy Context ID: old = null ctxID = findRoomie/findRoomie
Fine:   [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "" "GET")
Fine:   [Web-Security] hasUserDataPermission isGranted: true
Fine:   [Web-Security] Policy Context ID was: findRoomie/findRoomie
Fine:   [Web-Security] Codesource with Web URL: file:/findRoomie/findRoomie
Fine:   [Web-Security] Checking Web Permission with Principals : null
Fine:   [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/pages/user/dashboard.xhtml" "GET")
Finest:   JACC Policy Provider: PolicyWrapper.implies, context (findRoomie/findRoomie)- result was(false) permission (("javax.security.jacc.WebResourcePermission" "/pages/user/dashboard.xhtml" "GET"))
Fine:   [Web-Security] hasResource isGranted: false
Fine:   [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/pages/user/dashboard.xhtml" "GET")
Fine:   [Web-Security] Policy Context ID was: findRoomie/findRoomie
Fine:   [Web-Security] Generating a protection domain for Permission check.
Fine:   [Web-Security] Checking with Principal : mannyee
Fine:   [Web-Security] Checking with Principal : Member
Fine:   [Web-Security] Codesource with Web URL: file:/findRoomie/findRoomie
Fine:   [Web-Security] Checking Web Permission with Principals : mannyee, Member
Fine:   [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/pages/user/dashboard.xhtml" "GET")
Finest:   JACC Policy Provider: PolicyWrapper.implies, context (findRoomie/findRoomie)- result was(false) permission (("javax.security.jacc.WebResourcePermission" "/pages/user/dashboard.xhtml" "GET"))
Fine:   [Web-Security] hasResource isGranted: false

Although the user with Member role should have gained access on it, server forbids the request from user mannyee. So I set up the following on glassfish-web.xml (sun-web.xml)

<security-role-mapping>
    <role-name>Member</role-name>
    <principal-name>mannyee</principal-name>
    <!--        <group-name>Member</group-name>-->
  </security-role-mapping>

But still I can't get this user to access the page. I think the issue lies somewhere in role assignment. Sever log shows that GlassFish attempts to authorize by taking both 'mannyee' and 'Member' as principals but fails for both. There is also a line that says

    Fine:   [Web-Security] Checking Web Permission with Principals : null

I am not quite sure what that means.

Can anyone please point out what I am missing here?

Thanks!!


Solution

  • After a bit of tinkering with configuration, I finally found a solution. I made following changes to my Realm

    Assign Groups: ADMIN,MEMBER
    

    and then in glassfish-web.xml,

    <security-role-mapping>
        <role-name>MEMBER</role-name>
        <principal-name>MEMBER</principal-name>
        <group-name>MEMBER</group-name>
    </security-role-mapping>
    

    I also had a case-sensitivity issue, I was storing roles as Member in the table but using MEMBER in all my configurations.