Pac4j Play Integration

The goal of this project is to create a well documented playground for pac4j authentication and authorization with Play.

The main concepts in pac4j are:

  • a client: that represents an authentication mechanism. It performs the login process and returns a user profile.
  • an authenticator: is required by HTTP clients to validate provided credentials.
  • an authorizer: that checks if the given profile has the rights to access a requested resource.
  • a matcher: defines a (regular) expression that is applied on security filters
  • a config: which defines the security configurations via clients, authorizers and matchers

1. Clients

Clients can be categorized into:

  1. direct client: such as web services o HTTP clients, which negotiate the access directly.
  2. indirect client: that uses redirects to a third party service to perform the login (e.g. facebook, google, twitter) More details about them can be found here

The first category is for web service authentication, where the credentials happens for each http request (stateless). The second category if for UI authentication and the login happens once per session (stateful).

The supported clients are listed here.

While most clients are self-sufficient, the HTTP clients require defining an Authenticator to handle the credentials validation.

In this playground we are interested in:

  1. basic auth (using both indirect (IndirectBasicAuthClient) and direct (DirectBasicAuthClient) clients).
  2. cookie client: CookieClient value sent as a cookie
  3. header client: HeaderClient value sent as a HTTP header
  4. parameter client: ParameterClient value sent as a HTTP parameter

Clients (like Authorizers) are generally defined in a security configuration.

2. Authenticator

It is used by Clients (see above) to validate credentials and create a user profile. The Authenticator interface has only one method

def validate(c: Credentials, context: WebContext): Unit {

}

Credentials provided via clients can be of two types:

We can define different Authenticators, but we are interested on: - LDAP - JWT - REST API

Recommendations:

  1. use a LocalCachingAuthenticator to cache the requests made to the identity provider. It uses guava but it can be modified to use another store.

3. Authorizer

It checks if a user profile extracted by a client has the authorization to access the requested resource.

Urls can be protected via:

  • Secure annotation on controllers methods

def basicSecured() = Secure("DirectBasicAuthClient") { profiles => actionBuilder { request => Ok(views.html.protectedpage(profiles)) } }
  • Security filter defined in the application.conf file

pac4j.security { rules = [ {"/profile" = { authorizers = "_authenticated_" clients = "DirectBasicAuthClient" }} ] }