users@glassfish.java.net

"Security context" not propagated to Interceptors?

From: <glassfish_at_javadesktop.org>
Date: Fri, 14 Nov 2008 00:52:01 PST

Hi.
I am learning EJB3 and Glassfish, so I am writing this silly code every now and then. This time I came across sth strange to me.
I configured two usernames on the server using the web console: "szczyp" in group "szczyp", and "guest" in group "guest". I also ticked the "Default Principal To Role Mapping". I am using the default file realm.
I have a web and ejb module deployed on the server. Both modules have the roles and security restrictions specified: the web module in web.xml, and ejb module with annotations, which require the user to be of role "szczyp" to be able to access the resources.
The ejb has a single interceptor.
In each of the resources (servlet, interceptor, ejb) I call similar code to retrieve the username / principal name and check if the user / caller is in the role I am expecting him/her to be ("szczyp" in this case, since this is the only role that can proceed that far due to security restrictions). Also, the ejb is called from the servlet.
The thing is that for the servlet and ejb the code works as expected, but for the interceptor, the principal name is the expected one, but the injected EJBContext.isCallerInRole("szczyp") returns false. Please see the code snippets:

[b]the web.xml security settings:[/b]

[code]
<security-role>
    <role-name>guest</role-name>
</security-role>
<security-role>
    <role-name>szczyp</role-name>
</security-role>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Whole app</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>szczyp</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Test</realm-name>
</login-config>
[/code]

[b]the servlet:[/b]

[code]
@EJB
private Greeter greeter;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();
    out.println("Servlet:");
    out.println("\tUsername: " + request.getUserPrincipal().getName());
    out.println("\tIs user in role [szczyp]: " + request.isUserInRole("szczyp"));
    out.println();
    out.print(greeter.greet(null));
}
[/code]

[b]the ejb:[/b]

[code]
@Remote
public interface Greeter {

    String greet(String s);
}

----------------------------------------------------------

@Interceptors(TestInterceptor.class)
@DeclareRoles( { "szczyp", "guest" })
@RolesAllowed("szczyp")
@Stateless
public class GreeterBean implements Greeter {

    @Resource
    private EJBContext context;

    @Override
    public String greet(String s) {
        StringBuilder sb = new StringBuilder();
        if (s != null) {
            sb.append(s).append("\n");
        }
        sb.append("EJB:\n");
        sb.append("\tUsername: " + context.getCallerPrincipal().getName()).append("\n");
        sb.append("\tIs caller in role [szczyp]: " + context.isCallerInRole("szczyp")).append("\n");
        return sb.toString();
    }

}
[/code]

[b]the interceptor:[/b]

[code]
public class TestInterceptor {

    @Resource
    private EJBContext context;

    @AroundInvoke
    public Object doStuff(InvocationContext ctx) throws Exception {
        StringBuilder sb = new StringBuilder("EJB interceptor:\n");
        sb.append("\tUsername: " + context.getCallerPrincipal().getName()).append("\n");
        sb.append("\tIs caller in role [szczyp]: " + context.isCallerInRole("szczyp")).append("\n");
        ctx.setParameters(new String[] { sb.toString() });
        return ctx.proceed();
    }
}
[/code]

[b]The result is as follows:[/b]

[code]
Servlet:
        Username: szczyp
        Is user in role [szczyp]: true

EJB interceptor:
        Username: szczyp
        Is caller in role [szczyp]: false

EJB:
        Username: szczyp
        Is caller in role [szczyp]: true
[/code]

As you can see, the interceptor reports false for the caller-in-role test.
Is this the correct behavior, or is this a bug, or I simply don't know of something obvious?

Second question: are the roles declared using the @DeclaresRoles annotation global for the whole ejb module, or local to the ejb method / class they are declared for?

Thanks.
[Message sent by forum member 'szczyp' (szczyp)]

http://forums.java.net/jive/thread.jspa?messageID=316726