View on GitHub RESTX     the lightweight Java REST framework
Improve This Page

RESTX Security support

Restx provides its own session and security support. The rationale for that is that Restx fully embraces the “no conversation state on web application server” moto, which is incompatible with standard Java session (and therefore security) management.

When used in a servlet container, you can use the container security features. But then you rely on the container session management which is stateful and requires more complex load balancing management and HA tuning.

The session mechanism in Restx is based on signed client cookies storing only a set of session keys, the server being able to reproduce the full session state based only on these keys. The keys being signed, they can’t be tampered on the client side.

The security mechanisms relies on this session facilty and provides convenient authorization management together with a very flexible authentication support.

Authentication

Basics

You can access the currently authenticated principal using RestxSession#getPrincipal():

Optional<RestxPrincipal> principal = RestxSession.current().getPrincipal();

It doesn’t assume how this has been set, so authentication is very flexible, you only need to call RestxSession#authenticateAs(RestxPrincipal principal) like this in your code:

RestxSession.current().authenticateAs(principal);

If you already have an authentication mechanism, call that method once you get an authenticated principal (that is to say a user or a third party app or anything else that you consider can authenticate in your app).

Using restx-security-basic

If you don’t already have such authentication mechanism, Restx provides a basic authentication facility in the restx-security-basic module.

We recommend that you read these articles before dealing with password storage and general authentication issues:

All you need to do is:

  • add a dependency on the module
  • provide an implementation of BasicPrincipalAuthenticator

BasicPrincipalAuthenticator defines 2 methods that you need to implement:

  • Optional<? extends RestxPrincipal> authenticate(String name, String passwordHash, ImmutableMap<String, ?> principalData)
  • Optional<? extends RestxPrincipal> findByName(String name)

For a complete example of a BasicAuthenticator using mongo storage, you can have a look at the rxinvoice example, and especially its AppModule and UserResource.

The restx-security-basic module provides the following endpoints:

POST /sessions

Using json object like this:

{
	"principal": {
		"name": "myprincipal",
		"passwordHash": "1285ec167b6e4dd404c2a11b488e05cd"
	}
}

if the user / passwordHash is valid (according to your implementation of BasicPrincipalAuthenticator), the principal is authenticated for the duration of the session, otherwise a 401 error is returned.

GET /sessions/current

Returns the currently opened session if any, 401 if no session is opened

DELETE /sessions/current

Finish the current session, i.e. logout the currently authenticated principal.

Sudoing, aka “run as”

Restx supports out of the box a su mechanism, which lets you override the current session (and especially the principal) with arbitrary data for the duration of a single request.

To use this mechanism you just need to:

  • be authenticated with a Principal with restx-admin role.
  • use the HTTP Header RestxSu and give it the content of the session keys you want to override

This mechanism is used in the API-DOCS console, allowing to easily tests your requests for arbitrary principals.

Here is an example:

GET /api/sessions/current

RestxSu: { "principal": "test" }

Authorizations

Basics

Handling authorizations on your Restx endpoints is very easy. First, Restx endpoints are secured by default: it means that you need to have a principal authenticated to use a Restx endpoint.

So if you have this:

@GET("/greetings/{who}")
public Message sayHello(String who) {
	return new Message(who);
}

calling GET /greetings/world will return a 401 http code by default.

If you want to make an endpoint public, you need to use the @PermitAll annotation:

@PermitAll 
@GET("/greetings/{who}")
public Message sayHello(String who) {
	return new Message(who);
}

Note that you can also use that annotation at class level rather than method level, to make all endpoints in a class public.

Restx also allows to specify a role for the principal, using the @RolesAllowed annotation:

@RolesAllowed("admin")
@GET("/greetings/{who}")
public Message sayHello(String who) {
	return new Message(who);
}

With that not only Restx will check that a principal is authenticated, but it will also check that it has the admin role. In case a principal is authenticated but does not have the admin role, a 403 HTTP status code will be returned.

Advanced

For more advanced authorizations, have a look at the RestxSecurityManager and Permission types, which let you define and use very flexible authorizations.