Skip to content

Commit

Permalink
Changes and rework for pac4j 5 (#239)
Browse files Browse the repository at this point in the history
* added .fbExcludeFilterFile to .gitignore, changed pac4j to 5.3.1,
changed jersey-pac4j back to 2.35, added tests to jersey228-pac4j,
reworked dependencies-management

* Refactoring for SessionStore providers and simplified usage by providing
an implementation specific feature

* We will need Java 11 for pac4j 5

Co-authored-by: Michael Kohlsche <[email protected]>
  • Loading branch information
SiMiKohl and SiMiKohl authored Mar 10, 2022
1 parent 06027ba commit 2e90b1f
Show file tree
Hide file tree
Showing 70 changed files with 1,482 additions and 558 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Java CI

env:
JDK_CURRENT: 8
JDK_CURRENT: 11
DISTRIBUTION: zulu

on:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ target/
jax-rs-pac4j.iml
.pmd
.pmdruleset.xml
*.iml
*.iml
.fbExcludeFilterFile
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


The `jax-rs-pac4j` project is an **easy and powerful security library for JAX-RS web applications and web services** which supports authentication and authorization, but also logout and advanced features like session fixation and CSRF protection.
It's based on Java 8, servlet 3 (when present), JAX-RS 2 and on the **[pac4j security engine](https://github.com/pac4j/pac4j) v4**. It's available under the Apache 2 license.
It's based on Java 11, servlet 4 (when present), JAX-RS 2 and on the **[pac4j security engine](https://github.com/pac4j/pac4j) v5**. It's available under the Apache 2 license.

[**Main concepts and components:**](http://www.pac4j.org/docs/main-concepts-and-components.html)

Expand All @@ -28,15 +28,22 @@ These filters can be directly registered by hand, or instead, the following feat

5) Generic JAX-RS Providers and Features activate the use of some of the filters on the JAX-RS implementation based on various conditions

- The `JaxRsContextFactoryProvider` enables generic JAX-RS based pac4j functioning, without session handling (i.e., it will only work with direct clients)
- The `Pac4JFeature` enables generic JAX-RS based pac4j functionality. The default configuration does not provide session handling (i.e., it will only work with direct clients). The feature registers the following default providers:
- `JaxRsContextFactoryProvider` to create the generic pac4j context for JAX-RS
- `JaxRsConfigProvider` to provide the pac4j configuration
- `JaxRsSessionStoreProvider` to provide the configured pac4j `SessionStore`


- The `Pac4JSecurityFeature` enables annotation-based activation of the filters at the resource method level
- The `Pac4JSecurityFilterFeature` activates a global filter that will be applied to every resources.

6) Container/Implementation-specific Providers and Features extend the basic functionality provided by the generic ones

- The `Pac4JValueFactoryProvider` enables injection of the security profile in resource method
- The `ServletJaxRsContextFactoryProvider` provides session handling (and thus indirect clients support) by replacing the generic `JaxRsContextFactoryProvider` (for Servlet-based JAX-RS implementations, e.g., Jersey on Netty or Grizzly Servlet, Resteasy on Undertow).
- The `GrizzlyJaxRsContextFactoryProvider` provides session handling (and thus indirect clients support) by replacing the generic `JaxRsContextFactoryProvider` (for Grizzly2 without Servlet support).

- The `Pac4JServletFeature` provides session handling (and thus indirect clients support) by replacing the generic `JaxRsContextFactoryProvider` with `ServletJaxRsContextFactoryProvider` (for Servlet-based JAX-RS implementations, e.g., Jersey on Netty or Grizzly Servlet, Resteasy on Undertow) and `JaxRsSessionStoreProvider` with `ServletSessionStoreProvider`.

- The `Pac4JGrizzlyFeature` provides session handling (and thus indirect clients support) by replacing the generic `JaxRsContextFactoryProvider` with `GrizzlyJaxRsContextFactoryProvider` (for Grizzly2 without Servlet support) and `JaxRsSessionStoreProvider` with `GrizzlySessionStoreProvider`.


## Usage
Expand All @@ -59,7 +66,7 @@ These filters can be directly registered by hand, or instead, the following feat
The latest released version is the [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.pac4j.jax-rs/core/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/org.pac4j.jax-rs/core), available in the [Maven central repository](https://repo.maven.apache.org/maven2).
The [next version](https://github.com/pac4j/jax-rs-pac4j/wiki/Next-version) is under development.

See the [release notes](https://github.com/pac4j/jax-rs-pac4j/wiki/Release-Notes). Learn more by browsing the [pac4j documentation](https://www.javadoc.io/doc/org.pac4j/pac4j-core/4.0.0/index.html) and the [jax-rs-pac4j Javadoc](http://www.javadoc.io/doc/org.pac4j.jax-rs/core/4.0.0).
See the [release notes](https://github.com/pac4j/jax-rs-pac4j/wiki/Release-Notes). Learn more by browsing the [pac4j documentation](https://www.javadoc.io/doc/org.pac4j/pac4j-core/5.0.0/index.html) and the [jax-rs-pac4j Javadoc](http://www.javadoc.io/doc/org.pac4j.jax-rs/core/4.0.0).

See the [migration guide](https://github.com/pac4j/jax-rs-pac4j/wiki/Migration-guide) as well.

Expand Down
40 changes: 26 additions & 14 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,51 @@
</parent>
<artifactId>core</artifactId>

<properties>
<ws.rs-api.version>2.1.6</ws.rs-api.version>
<annotation-api.version>1.3.5</annotation-api.version>
<inject-api.version>1.0.5</inject-api.version>
<servlet-api.version>4.0.4</servlet-api.version>

<hamcrest.version>2.2</hamcrest.version>
</properties>

<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>${ws.rs-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${annotation-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>${inject-api.version}</version>
</dependency>
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-core</artifactId>
</dependency>

<!-- optional dependencies -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
<exclusions>
<exclusion>
Expand All @@ -53,12 +64,13 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

/**
*
* This class can be used to inject the pac4j {@link Config} in the JAX-RS runtime.
* This class can be used to inject the pac4j {@link Config} in the JAX-RS
* runtime.
*
* @author Victor Noel - Linagora
* @since 2.0.0
Expand All @@ -18,7 +19,7 @@ public class JaxRsConfigProvider implements ContextResolver<Config> {
public JaxRsConfigProvider(Config config) {
this.config = config;
}

@Override
public Config getContext(Class<?> type) {
return config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Providers;

import org.pac4j.core.client.IndirectClient;
import org.pac4j.core.config.Config;
import org.pac4j.jax.rs.features.JaxRsContextFactoryProvider.JaxRsContextFactory;
import org.pac4j.jax.rs.helpers.ProvidersContext;
import org.pac4j.jax.rs.pac4j.JaxRsContext;

/**
*
* This provides to the JAX-RS runtime a way to build a {@link JaxRsContext} adequate for the container.
*
* This is the generic implementation and will not support session management (and hence won't support pac4j
* {@link IndirectClient}).
* This provides the JAX-RS runtime a way to build a {@link JaxRsContext}
* adequate for the container.
*
* This can be subclassed for specific containers.
*
Expand All @@ -30,21 +25,17 @@ public class JaxRsContextFactoryProvider implements ContextResolver<JaxRsContext

@Override
public JaxRsContextFactory getContext(Class<?> type) {
return context -> new JaxRsContext(getProviders(), context, getConfig().getSessionStore());
return context -> new JaxRsContext(getProviders(), context);
}

protected Providers getProviders() {
assert providers != null;
return providers;
}

protected Config getConfig() {
return new ProvidersContext(providers).resolveNotNull(Config.class);
}

/**
* We need to provide a factory because it is not possible to get the {@link ContainerRequestContext} injected
* directly here...
* We need to provide a factory because it is not possible to get the
* {@link ContainerRequestContext} injected directly here...
*/
@FunctionalInterface
public interface JaxRsContextFactory {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.pac4j.jax.rs.features;

import javax.ws.rs.ext.ContextResolver;

import org.pac4j.core.config.Config;
import org.pac4j.core.context.session.SessionStore;

/**
* This class can be used to inject the pac4j {@link SessionStore} in the
* JAX-RS runtime.
*
* This can be subclassed for container specific implementations.
*
* @author Michael Kohlsche
* @since 5.0.0
*/
public class JaxRsSessionStoreProvider implements ContextResolver<SessionStore> {

protected final Config config;

public JaxRsSessionStoreProvider(Config config) {
this.config = config;
}

@Override
public SessionStore getContext(Class<?> type) {
return config.getSessionStore();
}

}
46 changes: 46 additions & 0 deletions core/src/main/java/org/pac4j/jax/rs/features/Pac4JFeature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.pac4j.jax.rs.features;

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;

import org.pac4j.core.config.Config;

/**
* This feature can be used to register the default set of necessary providers.
*
* This should be subclassed for container specific implementations and override
* the necessary registration methods.
*
* @author Michael Kohlsche
* @since 5.0.0
*/
public class Pac4JFeature implements Feature {

protected final Config config;

public Pac4JFeature(Config config) {
this.config = config;
}

@Override
public boolean configure(FeatureContext context) {
return registerConfigProvider(context) && registerSessionStoreProvider(context)
&& registerContextFactoryProvider(context);
}

protected boolean registerConfigProvider(FeatureContext context) {
context.register(new JaxRsConfigProvider(config));
return true;
}

protected boolean registerContextFactoryProvider(FeatureContext context) {
context.register(JaxRsContextFactoryProvider.class);
return true;
}

protected boolean registerSessionStoreProvider(FeatureContext context) {
context.register(new JaxRsSessionStoreProvider(config));
return true;
}

}
30 changes: 20 additions & 10 deletions core/src/main/java/org/pac4j/jax/rs/filters/AbstractFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.pac4j.core.authorization.authorizer.Authorizer;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.http.adapter.HttpActionAdapter;
import org.pac4j.jax.rs.helpers.ProvidersContext;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
Expand All @@ -35,6 +36,10 @@ protected Config getConfig() {
return new ProvidersContext(providers).resolveNotNull(Config.class);
}

protected SessionStore getSessionStore() {
return new ProvidersContext(providers).resolveNotNull(SessionStore.class);
}

protected abstract void filter(JaxRsContext context) throws IOException;

@Override
Expand All @@ -45,9 +50,12 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
// in case the filter aborts the request, we never arrive here, but if it is not aborted
// there is case when pac4j sets things on the response, this is the role of this method.
// unfortunately, if skipResponse is used, we can't do that because pac4j considers
// in case the filter aborts the request, we never arrive here, but if it is not
// aborted
// there is case when pac4j sets things on the response, this is the role of
// this method.
// unfortunately, if skipResponse is used, we can't do that because pac4j
// considers
// its abort response in the same way as the normal response
if (skipResponse == null || !skipResponse) {
new RequestJaxRsContext(providers, requestContext).contextOrNew().getResponseHolder()
Expand All @@ -56,13 +64,14 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont
}

/**
* Prefer to set a specific {@link HttpActionAdapter} on the {@link Config} instead of overriding this method.
* Prefer to set a specific {@link HttpActionAdapter} on the {@link Config}
* instead of overriding this method.
*
* @param config the security configuration
*
* @return an {@link HttpActionAdapter}
*/
protected HttpActionAdapter<Object, JaxRsContext> adapter(Config config) {
protected HttpActionAdapter adapter(Config config) {

final HttpActionAdapter adapter;
if (config.getHttpActionAdapter() != null) {
Expand All @@ -84,12 +93,13 @@ public Boolean isSkipResponse() {
}

/**
* Note that if this is set to <code>true</code>, this will also disable the effects of {@link Authorizer} and such
* that set things on the HTTP response! Use with caution!
* Note that if this is set to <code>true</code>, this will also disable the
* effects of {@link Authorizer} and such that set things on the HTTP response!
* Use with caution!
*
* @param skipResponse
* If set to <code>true</code>, the pac4j response, such as redirect, will be skipped (the annotated
* method will be executed instead).
* @param skipResponse If set to <code>true</code>, the pac4j response, such as
* redirect, will be skipped (the annotated method will be
* executed instead).
*/
public void setSkipResponse(Boolean skipResponse) {
this.skipResponse = skipResponse;
Expand Down
Loading

0 comments on commit 2e90b1f

Please sign in to comment.