The j2e-pac4j library is a J2E multi-protocols authentication and authorization client.
It supports these 6 authentication mechanisms on client side :
- OAuth (1.0 & 2.0)
- CAS (1.0, 2.0, SAML, logout & proxy)
- HTTP (form & basic auth authentications)
- OpenID
- SAML (2.0)
- GAE UserService
It's available under the Apache 2 license and based on my pac4j library.
Provider | Protocol | Maven dependency | Client class | Profile class |
---|---|---|---|---|
CAS server | CAS | pac4j-cas | CasClient & CasProxyReceptor | CasProfile |
CAS server using OAuth Wrapper | OAuth 2.0 | pac4j-oauth | CasOAuthWrapperClient | CasOAuthWrapperProfile |
DropBox | OAuth 1.0 | pac4j-oauth | DropBoxClient | DropBoxProfile |
OAuth 2.0 | pac4j-oauth | FacebookClient | FacebookProfile | |
GitHub | OAuth 2.0 | pac4j-oauth | GitHubClient | GitHubProfile |
OAuth 2.0 | pac4j-oauth | Google2Client | Google2Profile | |
OAuth 1.0 & 2.0 | pac4j-oauth | LinkedInClient & LinkedIn2Client | LinkedInProfile & LinkedIn2Profile | |
OAuth 1.0 | pac4j-oauth | TwitterClient | TwitterProfile | |
Windows Live | OAuth 2.0 | pac4j-oauth | WindowsLiveClient | WindowsLiveProfile |
WordPress | OAuth 2.0 | pac4j-oauth | WordPressClient | WordPressProfile |
Yahoo | OAuth 1.0 | pac4j-oauth | YahooClient | YahooProfile |
PayPal | OAuth 2.0 | pac4j-oauth | PayPalClient | PayPalProfile |
Vk | OAuth 2.0 | pac4j-oauth | VkClient | VkProfile |
Foursquare | OAuth 2.0 | pac4j-oauth | FoursquareClient | FoursquareProfile |
Bitbucket | OAuth 1.0 | pac4j-oauth | BitbucketClient | BitbucketProfile |
ORCiD | OAuth 2.0 | pac4j-oauth | OrcidClient | OrcidProfile |
Strava | OAuth 2.0 | pac4j-oauth | StravaClient | StravaProfile |
Web sites with basic auth authentication | HTTP | pac4j-http | BasicAuthClient | HttpProfile |
Web sites with form authentication | HTTP | pac4j-http | FormClient | HttpProfile |
Google - Deprecated | OpenID | pac4j-openid | GoogleOpenIdClient | GoogleOpenIdProfile |
Yahoo | OpenID | pac4j-openid | YahooOpenIdClient | YahooOpenIdProfile |
SAML Identity Provider | SAML 2.0 | pac4j-saml | Saml2Client | Saml2Profile |
Google App Engine User Service | Gae User Service Mechanism | pac4j-gae | GaeUserServiceClient | GaeUserServiceProfile |
This library has only 6 classes :
- the ClientConfiguration class gathers all the clients configuration
- the ClientFactory is the interface to implement to define the clients
- the ClientsConfigFilter is an abstract J2E filter in charge of loading clients configuration
- the RequiresAuthenticationFilter is a J2E filter to protect urls and requires authentication for them. The filter has a stateful or stateless mode.
- the CallbackFilter is a J2E filter to handle the callback of the provider after authentication to finish the authentication process
- the UserUtils is an helper class to know if the user is authenticated, his profile and log out him.
and is based on the pac4j-* libraries.
Learn more by browsing the j2e-pac4j Javadoc and the pac4j Javadoc.
If you want to use a specific client support, you need to add the appropriate Maven dependency in the pom.xml file :
- for OAuth support, the pac4j-oauth dependency is required
- for CAS support, the pac4j-cas dependency is required
- for HTTP support, the pac4j-http dependency is required
- for OpenID support, the pac4j-openid dependency is required
- for SAML support, the pac4j-saml dependency is required
- for Google App Engine support, the pac4j-gae dependency is required.
For example, to add OAuth support, add the following XML snippet :
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-oauth</artifactId>
<version>1.6.0</version>
</dependency>
As these snapshot dependencies are only available in the Sonatype snapshots repository, the appropriate repository must be added in the pom.xml file also :
<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
All the clients used to communicate with various providers (Facebook, Twitter, a CAS server...) must be defined in a specific class implementing the org.pac4j.j2e.configuration.ClientsFactory interface. For example :
public class MyClientsFactory implements ClientsFactory {
@Override
public Clients build() {
final FacebookClient facebookClient = new FacebookClient("fbkey", "fbsecret");
final TwitterClient twitterClient = new TwitterClient("twkey", "twsecret");
// HTTP
final FormClient formClient = new FormClient("http://localhost:8080/theForm.jsp", new SimpleTestUsernamePasswordAuthenticator());
final BasicAuthClient basicAuthClient = new BasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());
// CAS
final CasClient casClient = new CasClient();
casClient.setCasLoginUrl("http://localhost:8888/cas/login");
// OpenID
final GoogleOpenIdClient googleOpenIdClient = new GoogleOpenIdClient();
final Clients clients = new Clients("http://localhost:8080/callback", facebookClient, twitterClient, formClient, basicAuthClient, casClient, googleOpenIdClient);
return clients;
}
}
Pac4j was initially designed to provide authentication flows for web applications. This means it relies on a session concept and on HTTP redirections: this is the stateful mode and it is activated by default. In this mode, you need to configure what we call the callback filter in order to finish the authentication process.
Since j2e-pac4j version 1.1.0, we support now a stateless mode. This can be typically used to protect REST WS where a single HTTP call must be enough to retrieve the resource. A good example of stateless authentication is the basic-auth method where the browser includes in all requests the HTTP Authorization header with the login and password base64 encoded.
To handle callback from providers, you need to define the appropriate J2E filter and its mapping :
<filter>
<filter-name>CallbackFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.CallbackFilter</filter-class>
<init-param>
<param-name>clientsFactory</param-name>
<param-value>org.leleuj.config.MyClientsFactory</param-value>
</init-param>
<init-param>
<param-name>defaultUrl</param-name>
<param-value>/</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CallbackFilter</filter-name>
<url-pattern>/callback</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
You can protect your urls and force the user to be authenticated by a client by using the appropriate filter and mapping. Key parameters are all the clients and the specific client (clientName) used by this filter.
For example, for Facebook :
<filter>
<filter-name>FacebookFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.RequiresAuthenticationFilter</filter-class>
<init-param>
<param-name>clientsFactory</param-name>
<param-value>org.leleuj.config.MyClientsFactory</param-value>
</init-param>
<init-param>
<param-name>clientName</param-name>
<param-value>FacebookClient</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FacebookFilter</filter-name>
<url-pattern>/facebook/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
You can also explicitely compute a redirection url to a provider for authentication by using the getRedirectionUrl method and the ClientsConfiguration class. For example with Facebook :
<%
WebContext context = new J2EContext(request, response);
Clients client = ClientsConfiguration.getClients();
FacebookClient fbClient = (FacebookClient) client.findClient("FacebookClient");
String redirectionUrl = Client.getRedirectionUrl(context, false, false);
%>
After successful authentication, you can test if the user is authenticated using UserUtils.isAuthenticated()
or get the user profile using UserUtils.getUserProfile()
.
The profile returned is a CommonProfile, from which you can retrieve the most common properties that all profiles share. But you can also cast the user profile to the appropriate profile according to the provider used for authentication. For example, after a Facebook authentication :
// facebook profile
FacebookProfile facebookProfile = (FacebookProfile) commonProfile;
Or for all the OAuth 1.0/2.0 profiles, to get the access token :
OAuth10Profile oauthProfile = (OAuth10Profile) commonProfile
String accessToken = oauthProfile.getAccessToken();
// or
String accessToken = facebookProfile.getAccessToken();
In this mode, you need just to protect your resources with the ClientAuthenticationFilter
filter and configure the stateless
parameter to true.
<filter>
<filter-name>StatelessBasicAuthFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.RequiresAuthenticationFilter</filter-class>
<init-param>
<param-name>clientsFactory</param-name>
<param-value>org.leleuj.config.MyClientsFactory</param-value>
</init-param>
<init-param>
<param-name>clientName</param-name>
<param-value>BasicAuthClient</param-value>
</init-param>
<init-param>
<param-name>stateless</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>StatelessBasicAuthFilter</filter-name>
<url-pattern>/rest-basic-auth/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
After successful authentication, you can test if the user is authenticated using UserUtils.isAuthenticated()
or get the user profile using UserUtils.getUserProfile()
.
When you protect a resource with the ClientAuthenticationFilter
, you can also restrict its access to predefined roles depending on the user profiles.
You can use two parameters for that:
- requireAnyRole
- requireAllRoles
For example if you want to restrict the access to the user having the role ROLE_ADMIN:
<filter>
<filter-name>StatelessBasicAuthFilter</filter-name>
<filter-class>org.pac4j.j2e.filter.RequiresAuthenticationFilter</filter-class>
<init-param>
<param-name>clientsFactory</param-name>
<param-value>org.leleuj.config.MyClientsFactory</param-value>
</init-param>
<init-param>
<param-name>clientName</param-name>
<param-value>BasicAuthClient</param-value>
</init-param>
<init-param>
<param-name>stateless</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>requireAnyRole</param-name>
<param-value>ROLE_ADMIN</param-value>
</init-param>
</filter>
Of course you need also to configure a correct AuthorizationGenerator (see authorizations).
A demo with Facebook, Twitter, CAS, form authentication and basic auth authentication providers is available with j2e-pac4j-demo.
The current version 1.1.0-SNAPSHOT is under development. It's available on the Sonatype snapshots repository as a Maven dependency :
The last released version is the 1.0.4 :
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>j2e-pac4j</artifactId>
<version>1.0.4</version>
</dependency>
See the release notes.
If you have any question, please use the following mailing lists :