pac4j is a Java security engine to authenticate users, get their profiles and manage their authorizations in order to secure your Java web applications. It's available under the Apache 2 license.
It is currently available for many frameworks / tools and supports many authentication mechanisms. See the big picture.
Its core API is provided by the pac4j-core submodule (groupId: org.pac4j).
pac4j supports most authentication mechanisms, called clients:
- indirect / stateful clients are for UI when the user authenticates once at an external provider (like Facebook, a CAS server...) or via a local form (or basic auth popup)
- direct / stateless clients are for web services when credentials (like basic auth, tokens...) are passed for each HTTP request.
See the authentication flows.
| The authentication mechanism you want | The pac4j-* submodule(s) you must use |
|---|---|
| OAuth (1.0 & 2.0): Facebook, Twitter, Google, Yahoo, LinkedIn, Github... | pac4j-oauth |
| CAS (1.0, 2.0, 3.0, SAML, logout, proxy) | pac4j-cas |
| SAML (2.0) | pac4j-saml |
| OpenID Connect (1.0) | pac4j-oidc |
| HTTP (form, basic auth, IP, header, cookie, GET/POST parameter) + JWT or LDAP or Relational DB or MongoDB or Stormpath or CAS REST API |
pac4j-http+ pac4j-jwtor pac4j-ldapor pac4j-sqlor pac4j-mongoor pac4j-stormpathor pac4j-cas |
| Google App Engine UserService | pac4j-gae |
| OpenID | pac4j-openid |
pac4j supports many authorization checks, called authorizers available in the pac4j-core (and pac4j-http) submodules: role / permission checks, IP check, profile type verification, CSRF token validation... and the regular web security protections for XSS, cache control, Xframe... (like the default filters of Spring Security).
The next version 1.8.1-SNAPSHOT is under development. Maven artifacts are built via Travis: 
The source code can be cloned and locally built via Maven:
git clone git@github.com:pac4j/pac4j.git
cd pac4j
mvn clean installThe latest released version is the , available in the Maven central repository. See the release notes.
pac4j is an easy and powerful security engine. Add the pac4j-core dependency to benefit from the core API of pac4j. Other dependencies will be optionally added for specific support: pac4j-oauth for OAuth, pac4j-cas for CAS, pac4j-saml for SAML...
To define your security configuration, gather all your authentication mechanisms = clients via the Clients class (to share the same callback url). Also define your authorizers to check authorizations and aggregate both (clients and authorizers) on the Config:
FacebookClient facebookClient = new FacebookClient(FB_KEY, FB_SECRET);
TwitterClient twitterClient = new TwitterClient(TW_KEY, TW_SECRET);
FormClient formClient = new FormClient("http://localhost:8080/theForm.jsp", new SimpleTestUsernamePasswordAuthenticator(), new UsernameProfileCreator());
CasClient casClient = new CasClient();
casClient.setCasLoginUrl("http://mycasserver/login");
Clients clients = new Clients("http://localhost:8080/callback", facebookClient, twitterClient, formClient, casClient);
Config config = new Config(clients);
config.addAuthorizer("admin", new RequireAnyRoleAuthorizer("ROLE_ADMIN"));
config.addAuthorizer("custom", new CustomAuthorizer());Notice you may also use the ConfigSingleton object to keep one instance of your configuration and share it among the different components (if you don't have any dependency injection capability). You can also use the ConfigFactory to build you configuration if no other mean is available.
To secure your Java web application, the reference implementation is to create two "filters": one to protect urls, the other one to receive callbacks for stateful authentication processes (indirect clients).
- For your protection "filter", it must be based on two String parameters:
clientName(list of clients used for authentication) andauthorizerName(list of authorizers to check authorizations) and use the following logic (loop on direct clients for authentication then check the user profile and authorizations):
EnvSpecificWebContext context = new EnvSpecificWebContex(...);
Clients configClients = config.getClients();
List<Client> currentClients = clientFinder.find(configClients, context, clientName);
boolean useSession = useSession(context, currentClients);
ProfileManager manager = new ProfileManager(context);
UserProfile profile = manager.get(useSession);
if (profile == null && currentClients != null && currentClients.size() > 0) {
for (final Client currentClient: currentClients) {
if (currentClient instanceof DirectClient) {
final Credentials credentials;
try {
credentials = currentClient.getCredentials(context);
} catch (RequiresHttpAction e) { ... }
profile = currentClient.getUserProfile(credentials, context);
if (profile != null) {
manager.save(useSession, profile);
break;
}
}
}
}
if (profile != null) {
if (authorizationChecker.isAuthorized(context, profile, authorizerName, config.getAuthorizers())) {
grantAccess();
} else {
forbidden(context, currentClients, profile);
}
} else {
if (startAuthentication(context, currentClients)) {
saveRequestedUrl(context, currentClients);
redirectToIdentityProvider(context, currentClients);
} else {
unauthorized(context, currentClients);
}
}The EnvSpecificWebContext class is a specific implementation of the WebContext interface for your framework.
See the final implementations in j2e-pac4j and play-pac4j.
- For your callback "filter", get the credentials and the user profile on the callback url:
EnvSpecificWebContext context = new EnvSpecificWebContex(...);
Clients clients = config.getClients();
Client client = clients.findClient(context);
Credentials credentials;
try {
credentials = client.getCredentials(context);
} catch (RequiresHttpAction e) {
handleSpecialHttpBehaviours();
}
UserProfile profile = client.getUserProfile(credentials, context);
saveUserProfile(context, profile);
redirectToOriginallyRequestedUrl(context, response);See the final implementations in j2e-pac4j and play-pac4j.
Read the Javadoc and the technical components for more information.
If you have any question, please use the following mailing lists:
