Links: Table of Contents | Single HTML

Chapter 14. Security

14.1. Securing server

14.1.1. SecurityContext

Security information is available by injecting a SecurityContext instance using @Context annotation, that provides essentially the equivalent of the functionality available on HttpServletRequest API. The injected security context depends on the actual Jersey application deployment. For example, if a Jersey application is deployed in a Servlet container, the Jersey SecurityContext will return information of the security context retrieved from Servlet request. For Jersey applications deployed on a Grizzly server, the SecurityContext will return information retrieved from the Grizzly request.

SecurityContext can be used in conjunction with sub-resource locators to return different resources if the user principle is included in a certain role. For example, a sub-resource locator could return a different resource if a user is a preferred customer:

Example 14.1. Accessing SecurityContext

@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
    if (sc.isUserInRole("PreferredCustomer") {
        return new PreferredCustomerShoppingBasketResource();
    } else {
        return new ShoppingBasketResource();
    }
}


SecurityContext can be injected also to singleton resources and providers as a class field. In such case the proxy of the request-scoped SecurityContext will be injected.

Example 14.2. Injecting SecurityContext into a singleton resource

@Path("resource")
@Singleton
public static class MyResource {
    @Context
    // Jersey will inject proxy of Security Context
    SecurityContext securityContext;

    @GET
    public String getUserPrincipal() {
        return securityContext.getUserPrincipal().getName();
    }
}


14.1.1.1. Initialize SecurityContext with Servlets

As described above, the SecurityContext by default (if not overwritten by filters) only offers information from an underlying container. In the case you deploy a Jersey application in a Servlet container, you need to setup the <security-constraint>, <auth-constraint> and user to roles mappings in order to pass correct information to the SecurityContext.

14.1.1.2. SecurityContext in ContainerRequestContext

The SecurityContext can be retrieved also from ContainerRequestContext via getSecurityContext() method. You can also set the SecurityContext into the request using method setSecurityContext(SecurityContext). If you set a new SecurityContext in the ContainerRequestFilter into the ContainerRequestContext, then this security context will be used for injections in resource classes (wrapped into the proxy). This way you can implement a custom authentication filter that may setup your own SecurityContext to be used. To ensure the early execution of your custom authentication request filter, set the filter priority to AUTHENTICATION using constants from Priorities. An early execution of you authentication filter will ensure that all other filters, resources, resource methods and sub-resource locators will execute with your custom SecurityContext instance.

14.1.2. Authorization - securing resources

14.1.2.1. Security resources with web.xml

In cases where a Jersey application is deployed in a Servlet container you can rely only on the standard Java EE Web application security mechanisms offered by the Servlet container and configurable via application's web.xml descriptor. You need to define the <security-constraint> elements in the web.xml and assign roles which are able to access these resources. You can also define HTTP methods that are allowed to be executed. See the following example.

Example 14.3. Injecting SecurityContext into singletons

<security-constraint>
    <web-resource-collection>
        <url-pattern>/rest/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <url-pattern>/rest/orders/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>customer</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>my-defaul-realm</realm-name>
</login-config>


The example secures two kinds of URI namespaces using the HTTP Basic Authentication. rest/admin/* will be accessible only for user group "admin" and rest/orders/* will be accessible for "customer" user group. This security configuration does not use JAX-RS or Jersey features at all as it is enforced by the Servlet container even before a request reaches the Jersey application. Keeping this security constrains up to date with your JAX-RS application might not be easy as whenever you change the @Path annotations on your resource classes you may need to update also the web.xml security configurations to reflect the changed JAX-RS resource paths. Therefore Jersey offers a more flexible solution based on placing standard Java EE security annotations directly on JAX-RS resource classes and methods.

14.1.2.2. Securing JAX-RS resources with annotations

With Jersey you can define the access to resources based on the user group using annotations. You can for example define that only a user group "admin" can execute specific resource method. To do that you firstly need to register RolesAllowedDynamicFeature as a provider. The following example shows how to register the feature if your deployment is based on a ResourceConfig.

Example 14.4. Registering RolesAllowedDynamicFeature using ResourceConfig

final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
resourceConfig.register(RolesAllowedDynamicFeature.class);


Then you can use annotations from package javax.annotation.security defined by JSR-250. See the following example.

Example 14.5. Injecting SecurityContext into singletons

@Path("/")
@PermitAll
public class Resource {
    @RolesAllowed("user")
    @GET
    public String get() { return "GET"; }

    @RolesAllowed("admin")
    @POST
    public String post(String content) { return content; }

    @Path("sub")
    public SubResource getSubResource() {
        return new SubResource();
    }
}


The resource class Resource defined in the example is annotated with a @PermitAll annotation. This means that all methods in the class which do not this annotation will be permitted for all user groups (no restrictions are defined). In our example, the annotation will only apply to the getSubResource() method as it is the only method that does not override the annotation by defining custom role-based security settings using the @RolesAllowed annotation. @RolesAllowed annotation present on other methods defines a role or a set of roles that are allowed to execute a particular method.

These Java EE security annotations are processed internally in the request filter registered using the Jersey RolesAllowedDynamicFeature. The roles defined in the annotations are tested against current roles set in the SecurityContext using the SecurityContext.isUserInRole(String role) method. In case the caller is not in the role specified by the annotation, the HTTP 404 error response is returned.

14.2. Client Security

For details about client security please see the Client chapter. Jersey client allows to define parameters of SSL communication using HTTPS protocol. You can also use jersey built-in authentication filter which performs HTTP Basic Authentication. See the client chapter for more details.

14.3. OAuth

OAuth 1.x support has not been migrated from Jersey 1.x to Jersey 2.x yet. The documentation will be updated once the OAuth support feature will be released in Jersey 2.