Giter VIP home page Giter VIP logo

dropwizard-pac4j's Introduction

Build Status Maven Central

dropwizard-pac4j

A Dropwizard bundle for securing REST endpoints using pac4j.

dropwizard-pac4j JDK pac4j jax-rs-pac4j Dropwizard
version >= 6 11 v5 v6 v4
version >= 5.3 11 v5 v5 v3
version >= 5 11 v4 v4 v2
version >= 4 8 v4 v4 v1
version >= 3 8 v3 v3 v1

Usage

dropwizard-pac4j provides two components which must be integrated into applications:

  • A configuration factory populated by values from a pac4j section within an application's config file.
  • A Dropwizard bundle which:
    • connects the values defined in the pac4j configuration section to the jax-rs-pac4j and jee-pac4j libraries.
    • enables the use of the annotation provided in by the jax-rs-pac4j library.
    • enables Jetty session management by default.

Dependencies (dropwizard-pac4j + pac4j-* libraries)

You need to add a dependency on:

  • the dropwizard-pac4j library (groupId: org.pac4j, version: 5.0.0)
  • the appropriate pac4j submodules (groupId: org.pac4j, version: 4.3.0): pac4j-oauth for OAuth support (Facebook, Twitter...), pac4j-cas for CAS support, pac4j-ldap for LDAP authentication, etc.

All released artifacts are available in the Maven central repository.

Installing the bundle

Add the bundle within the application class' initialize method, just like any other bundle:

public class MySecureApplication extends Application<MySecureConfiguration> {
    final Pac4jBundle<MySecureConfiguration> bundle = new Pac4jBundle<MySecureConfiguration>() {
        @Override
        public Pac4jFactory getPac4jFactory(MySecureConfiguration configuration) {
            return configuration.getPac4jFactory();
        }
    };

    @Override
    public void initialize(Bootstrap<TestConfiguration> bootstrap) {
        bootstrap.addBundle(bundle);
    }

    ...

It can be useful to store the bundle in its own field in order to be able to access pac4j configuration as shown at the end of the next section.

Configuring the bundle

Update the application's configuration class to expose accessor methods for Pac4jFactory:

public class MySecureConfiguration extends Configuration {
    @NotNull
    Pac4jFactory pac4jFactory = new Pac4jFactory();

    @JsonProperty("pac4j")
    public Pac4jFactory getPac4jFactory() {
        return pac4jFactory;
    }

    @JsonProperty("pac4j")
    public void setPac4jFactory(Pac4jFactory pac4jFactory) {
        this.pac4jFactory = pac4jFactory;
    }
}

Note that it is also possible to have pac4jFactory be nullable and in this case, pac4j won't be configured but pac4j's type will be readable in the configuration. If the latter is not desired, do not use this bundle!

Add a pac4j section to a Dropwizard application's configuration file:

pac4j:
  # those protect the whole application at Jersey level
  globalFilters:
    - matchers: excludeUserSession
      authorizers: isAuthenticated
  servlet:
    security:
      - ...
    callback:
      - ...
    logout:
      - ...
  matchers:
    # this let the /user/session url be handled by the annotations
    excludeUserSession:
      class: org.pac4j.core.matching.PathMatcher
      excludePath: ^/user/session$
  callbackUrl: /user/session
  defaultClient: DirectBasicAuthClient
  clients:
    - org.pac4j.http.client.direct.DirectBasicAuthClient:
        authenticator:
          class: org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator
  • globalFilters to declare global filters: the clients, authorizers, matchers, and skipResponse properties directly map to the parameters used by org.pac4j.jax.rs.filter.SecurityFilter.

  • servlet to declare servlet-level filters:

  • security: the clients, authorizers, and matchers properties directly map to the parameters used by org.pac4j.jee.filter.SecurityFilter. The mapping property is used to optionally specify urls to which this filter will be applied to, defaulting to all urls (/*).

  • callback: the defaultUrl, and renewSession properties directly map to the parameters used by org.pac4j.jee.filter.CallbackFilter. The mapping property is used to specify urls to which this filter will be applied to. It does not usually contains a wildcard.

  • logout: the defaultUrl and logoutUrlPattern properties directly map to the parameters used by org.pac4j.jee.filter.LogoutFilter. The mapping property is used to specify urls to which this filter will be applied to. It does not usually contains a wildcard.

  • sessionEnabled: set to false to disable Jetty session management. If not set, the bundle will simply enable it by default.

  • matchers: the key is the name of the Matcher and its instance is declared as explained below. Their name can be used in filter's matchers as well as in the Pac4JSecurity annotation.

  • authorizers: the key is the name of the Authorizer and its instance is declared as explained below. Their name can be used in filter's authorizers as well as in the Pac4JSecurity annotation.

  • clients: the key is the class of the Client and its instance is configured based on the properties. Its name is by default the short name of its class, but it can also be set explictly. Their name can be used in filter's clients as well as in the Pac4JSecurity annotation.

  • defaultClient: the name of one of the client configured via clients. It will be used as the default pac4j Client. Pac4j exploits it in particular when no client is specified during callback, but also when no clients are specified on a security filter.

  • defaultClients: the names (separated by commas) of some of the clients configured via clients. They will be used as the default value for the clients parameter of the Pac4JSecurity annotation.

To specify instances of Client, Authenticator, PasswordEncoder, CredentialsExtractor, ProfileCreator, AuthorizationGenerator, Authorizer, Matcher, CallbackUrlResolver, HttpActionAdapter and RedirectActionBuilder, it only necessary to refer to their class name using the class key as above and the other properties are set on the instantiated object.

URLs Relativity

Note that all urls used within Jersey filters are relative to the dropwizard applicationContext suffixed by the dropwizard roothPath while the urls used within Servlet filters are only relative to the dropwizard applicationContext.

For Jersey, this also includes callbackUrls, enforced by JaxRsCallbackUrlResolver, which is the defaultCallbackUrlResolver in the config if not overridden.

Advanced Configuration

For more complex setup of pac4j configuration, the Config can be retrieved from the Pac4jBundle object stored in your Application:

public class MySecureApplication extends Application<MySecureConfiguration> {

    final Pac4jBundle<MySecureConfiguration> bundle = ...;

    @Override
    public void run(MySecureConfiguration config, Environment env) throws Exception {
        Config conf = bundle.getConfig()
        
        DirectBasicAuthClient c = conf.getClients().findClient(DirectBasicAuthClient.class);
        c.setCredentialsExtractor(...);
        
        env.jersey().register(new DogsResource());
    }
}

Securing REST endpoints

From here, jax-rs-pac4j takes over with its annotations. See pac4j documentation on how to implement Clients, Authorizers, Matchers and all the other points of extension.

Usage with Dropwizard's ResourceTestRule

When using ResourceTestRule, it usually make sense to mock the profile that is injected for @Pac4jProfile annotations by using one of the alternative Pac4JValueFactoryProvider binders:

@Rule
public final ResourceTestRule resources = ResourceTestRule.builder()
      .addProvide(MyResource.class)
      .addProvider(new Pac4JValueFactoryProvider.Binder(new CockpitProfile("my-mock-user-id")))
      .build();

Release notes

See the release notes. Learn more by browsing the dropwizard-pac4j Javadoc and the pac4j Javadoc.

Need help?

You can use the mailing lists or the commercial support.

Development

The version 5.0.1-SNAPSHOT is under development.

Maven artifacts are built via Travis and available in the Sonatype snapshots repository. This repository must be added in the Maven settings.xml or pom.xml files:

<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>

dropwizard-pac4j's People

Contributors

dependabot[bot] avatar eocantu avatar evnm avatar leleuj avatar renovate[bot] avatar richeyh avatar victornoel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

dropwizard-pac4j's Issues

Maturing to v1.0.0

  1. I haven't seen any communication about this extension on the Dropwizard mailing list: did you post something? It would be great to get some feedbacks.

  2. The current version is 0.0.1-SNAPSHOT: what's the strategy to reach the 1.0.0 version?

  3. Shouldn't this extension be hosted in the pac4j organization?

What's the correct format for excludedPaths?

I've updated our dropwizard-pac4j and am now getting parse errors for the excludedPath field.


yml has an error:
  * Failed to parse configuration at: pac4j.matchers.excludeUserSession.excludedPaths; Cannot deserialize instance of `java.util.ArrayList` out of VALUE_STRING token
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: service.config.Config["pac4j"]->org.pac4j.dropwizard.Pac4jFactory["matchers"]->java.util.LinkedHashMap["excludeUserSession"]->org.pac4j.core.matching.PathMatcher["excludedPaths"])

I was previously supplying a regex string eg
excludedPaths: ^(.*swagger.*|.*jfree.*|.*wms.chart.*|.*service\/info.*|.*\/healthcheck)$

dropwizard-pac4j-demo?

Almost all pac4j implementations have a demo to demonstrate its features. It would great to have a dropwizard-pac4j-demo for this bundle.

saml.keyStoreAlias seems to be ignored

Version: 2.0.0

It seems the configuration-defined alias for the SP keystore key is ignored. Config yaml extract:

pac4j:
  callbackUrl: /callback
  clientsProperties:
    ... other entries here ...
    saml.keyStoreAlias: dev123

But when the keystore is generated, I see in the logs:

WARN  [2017-10-08 16:02:03,583] org.pac4j.saml.client.SAML2ClientConfiguration: Provided keystoreResource does not exist. Creating one for: file [/XXXXXXXX.jks]
WARN  [2017-10-08 16:02:03,662] org.pac4j.saml.client.SAML2ClientConfiguration: Using keystore alias SAML2ClientConfiguration
WARN  [2017-10-08 16:02:03,662] org.pac4j.saml.client.SAML2ClientConfiguration: Using keystore type jks
INFO  [2017-10-08 16:02:04,340] org.pac4j.saml.client.SAML2ClientConfiguration: Created XXXXXXX.jks with key alias saml2clientconfiguration

And, indeed, inspecting the generated keystore there is a key with alias saml2clientconfiguration created.

Is there maybe some other way to set the alias of the key or is this a bug?

excludePath example uses deprecated class

The documentation here https://github.com/pac4j/dropwizard-pac4j says

matchers:
# this let the /user/session url be handled by the annotations
excludeUserSession:
class: org.pac4j.core.matching.ExcludedPathMatcher

But org.pac4j.core.matching.ExcludedPathMatcher is deprecated and results in a no class found:

caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'org.pac4j.core.matching.ExcludedPathMatcher' as a subtype of [simple type, class org.pac4j.core.matching.Matcher]: no such class found

Can no longer use regex strings for ExcludedPaths

I used to supply a regex string for path exclusion, eg:

excludedPaths: ^(.swagger.|.jfree.|.wms.chart.|.service/info.|.*/healthcheck)$

After updating dropwizard-pac4j, I tried to convert this to a list, eg

excludedPaths: [.swagger. , .jfree. , .wms.chart. , /.service/info. , .*/healthcheck]

but am now gettng an exception thrown:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Excluded path must begin with a / (through reference chain: com.ibm.itsm.topology.service.config.Config["pac4j"]->org.pac4j.dropwizard.Pac4jFactory["matchers"]->java.util.LinkedHashMap["excludeUserSession"]->org.pac4j.core.matching.PathMatcher["excludedPaths"])
Caused by: org.pac4j.core.exception.TechnicalException: Excluded path must begin with a /

Does this mean that regex is no longer valid and only full paths can be defined? I have hundreds of swagger pages so it's really not a nice solution to have to specify the full path.

Applying AlwaysUseSessionProfileStorageDecision for direct client

I need to store user profile on the HTTP session. As far as I can tell, this is accomplished by AlwaysUseSessionProfileStorageDecision. I first attempted to do this in the config yml file, but couldn't figure out the proper syntax to do so. I then switched to doing it through code instead, in my dropwizard config file I changed the getPac4jFactory function like this:

@JsonProperty("pac4j")
 public void setPac4jFactory(Pac4jFactory pac4jFactory) {
   this.pac4jFactory = pac4jFactory;
 }
 public Pac4jFactory getPac4jFactory() {
   if (pac4jFactory.getSecurityLogic() == null) {
     DefaultSecurityLogic sl = new DefaultSecurityLogic<>();
     sl.setProfileStorageDecision(new AlwaysUseSessionProfileStorageDecision());
     pac4jFactory.setSecurityLogic(sl);
   }
   return pac4jFactory;
 }

While the above succeeds in setting the property the way I want it, this is then nullified by the org.pac4j.j2e.filter.SecurityFilter ctor which instantiates a new DefaultSecurityLogic that has a DefaultProfileStorageDecision. The SecurityFilter's default ctor is called through J2EHelper.registerSecurityFilter. It would seem to me that J2EHelper.registerSecurityFilter should use the securityLogic set in the passed in Config object rather than instantiating a new DefaultSecurityLogic.

To the above Jérôme then replied

Yes, indeed, I think there is a bug: the securityLogic should be used to build the SecurityFilter if ever the property is not null.

See full discussion here:

https://groups.google.com/forum/#!topic/pac4j-users/u6WecNrIN9I

Cannot inject "Pac4jProfile" in a "@ScopedRequest" ressource

Upgrading Pac4j from v2.1.0 (either to v2.3.0 or v3.x.x), you can no longer inject a profile into a @RequestScoped ressource constructor like this:

@Path("/myressource")
@RequestScoped
public class MyResource {

    @Inject
    public BreakerResource(@Pac4JProfile final CommonProfile profile) {
    }
}

This results in a runtime error while accessing the ressource (even after a successful login with an IndirectBasicAuthClient):

DEBUG [2019-03-19 13:15:33,674] org.pac4j.jax.rs.jersey.features.Pac4JValueFactoryProvider: Cannot inject a Pac4j profile into an unauthenticated request, responding with 401

Replacing @Pac4JProfile with a @Pac4JProfileManager works fine though. And you can still inject a @Pac4JProfile in @Singleton ressources as well.

Observed with dropwizard v1.3.0 and v1.3.8.
Here's a link to the full group discussion.
An one to the bug reproduced in dropwizard-pac4j-demo.

NoClassDefFoundError: org/glassfish/jersey/server/internal/inject/AbstractContainerRequestValueFactory

Updating to the latest dropwizard-pac4j, I'm getting this runtime error. I can't work out what dependency I need to add. Please can you help?

I'm currently using jersey-server 2.31

java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: org/glassfish/jersey/server/internal/inject/AbstractContainerRequestValueFactory at org.pac4j.jax.rs.jersey.features.Pac4JValueFactoryProvider$Binder.<init>(Pac4JValueFactoryProvider.java:169) at org.pac4j.jax.rs.jersey.features.Pac4JValueFactoryProvider$Binder.<init>(Pac4JValueFactoryProvider.java:153) at org.pac4j.dropwizard.Pac4jBundle.run(Pac4jBundle.java:98) at org.pac4j.dropwizard.Pac4jBundle.run(Pac4jBundle.java:35) at io.dropwizard.setup.Bootstrap.run(Bootstrap.java:200) at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:42) at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:87) at io.dropwizard.cli.Cli.run(Cli.java:78) at io.dropwizard.Application.run(Application.java:93)

Pac4j-SAML with Dropwizard-pac4j version compatibility

I have integrated SAML with dropwizard using pac4j-saml submodule with dropwizard-pac4j bundle.

When upgrading to the new version for both bundle(3.0.0) and submodule(3.6.1) from current bundle(2.0.0) + pac4j-saml(2.3.1), I am facing issues.

There is no more redirection happening to my SAML authentication and I am getting 404 for my login endpoint. (source code below).
The same code works with the library versions mentioned above. Was there some breaking change introduced with the major version upgrade for both?

@GET
@Path(LOGIN)
@Pac4JSecurity(clients = "SAML2Client", authorizers = “mustBeAuth")
@Pac4JLogout(localLogout = false, defaultUrl = "/#")
public void login(@Pac4JProfileManager ProfileManager<CommonProfile> pm) {
}

Debug Logs

DEBUG [2019-11-21 15:06:57,605] org.pac4j.core.engine.DefaultSecurityLogic: === SECURITY ===
DEBUG [2019-11-21 15:06:57,605] org.pac4j.core.engine.DefaultSecurityLogic: url: http://localhost:8080/service/auth/login
DEBUG [2019-11-21 15:06:57,605] org.pac4j.core.engine.DefaultSecurityLogic: matchers: 
DEBUG [2019-11-21 15:06:57,605] org.pac4j.core.engine.DefaultSecurityLogic: clients: SAML2Client
DEBUG [2019-11-21 15:06:57,605] org.pac4j.core.client.finder.DefaultSecurityClientFinder: Provided clientNames: SAML2Client
DEBUG [2019-11-21 15:06:57,606] org.pac4j.core.client.finder.DefaultSecurityClientFinder: clientNameOnRequest: null
DEBUG [2019-11-21 15:06:57,609] org.pac4j.core.client.finder.DefaultSecurityClientFinder: result: [SAML2Client]
DEBUG [2019-11-21 15:06:57,609] org.pac4j.core.engine.DefaultSecurityLogic: currentClients: [#SAML2Client# | name: SAML2Client | callbackUrl: /service/auth/callback | urlResolver: org.pac4j.jax.rs.pac4j.JaxRsUrlResolver@341ead4 | callbackUrlResolver: null | ajaxRequestResolver: org.pac4j.jax.rs.pac4j.JaxRsAjaxRequestResolver@4bf0f27e | redirectActionBuilder: null | credentialsExtractor: null | authenticator: null | profileCreator: org.pac4j.core.profile.creator.AuthenticatorProfileCreator@2fc314a5 | logoutActionBuilder: org.pac4j.core.logout.NoLogoutActionBuilder@3995aa17 | authorizationGenerators: [] |]
DEBUG [2019-11-21 15:06:57,609] org.pac4j.core.engine.DefaultSecurityLogic: loadProfilesFromSession: true
DEBUG [2019-11-21 15:06:57,611] org.pac4j.core.engine.DefaultSecurityLogic: profiles: []
DEBUG [2019-11-21 15:06:57,611] org.pac4j.core.engine.DefaultSecurityLogic: Starting authentication
DEBUG [2019-11-21 15:06:57,612] org.pac4j.core.engine.DefaultSecurityLogic: requestedUrl: http://localhost:8080/service/auth/login
INFO  [2019-11-21 15:06:57,613] org.pac4j.saml.config.SAML2Configuration: Bootstrapped Blacklisted Algorithms
INFO  [2019-11-21 15:06:57,613] org.pac4j.saml.config.SAML2Configuration: Bootstrapped Signature Algorithms
INFO  [2019-11-21 15:06:57,613] org.pac4j.saml.config.SAML2Configuration: Bootstrapped Signature Reference Digest Methods
INFO  [2019-11-21 15:06:57,613] org.pac4j.saml.config.SAML2Configuration: Bootstrapped Canonicalization Algorithm
INFO  [2019-11-21 15:06:57,649] org.pac4j.saml.metadata.SAML2ServiceProviderMetadataResolver: Using SP entity ID PDA
INFO  [2019-11-21 15:06:57,702] org.pac4j.saml.client.SAML2Client: AJAX request detected -> returning the appropriate action
DEBUG [2019-11-21 15:06:57,704] org.pac4j.saml.context.SAML2ContextProvider: Creating message storage by org.pac4j.saml.storage.EmptyStorageFactory
INFO  [2019-11-21 15:06:57,760] org.pac4j.saml.crypto.DefaultSignatureSigningParametersProvider: Created signature signing parameters.
Signature algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
Signature canonicalization algorithm: http://www.w3.org/2001/10/xml-exc-c14n#
Signature reference digest methods: http://www.w3.org/2001/04/xmlenc#sha256
DEBUG [2019-11-21 15:06:57,762] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Initialized Pac4jHTTPPostEncoder
DEBUG [2019-11-21 15:06:57,762] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Invoking Velocity template to create POST body
DEBUG [2019-11-21 15:06:57,764] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Encoding action url of '<redected>' with encoded value '<redected>'
DEBUG [2019-11-21 15:06:57,764] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Marshalling and Base64 encoding SAML message
DEBUG [2019-11-21 15:06:57,764] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Marshalling message
DEBUG [2019-11-21 15:06:57,765] org.pac4j.saml.transport.Pac4jHTTPPostEncoder: Setting RelayState parameter to: 'http://localhost:8080/service/auth/callback?client_name=SAML2Client', encoded as 'http&#x3a;&#x2f;&#x2f;localhost&#x3a;8080&#x2f;service&#x2f;auth&#x2f;callback&#x3f;client_name&#x3d;SAML2Client'
DEBUG [2019-11-21 15:06:57,778] org.pac4j.core.engine.DefaultSecurityLogic: extra HTTP action required in security: 401

Also if I upgrade to 3.8.3 for pac4j-saml, I am unable to even run the project.

Debug Logs

java.lang.NoClassDefFoundError: org/hibernate/bytecode/instrumentation/internal/FieldInterceptionHelper
	at org.hibernate.jpa.internal.util.PersistenceUtilHelper.isLoadedWithoutReference(PersistenceUtilHelper.java:113)
	at org.hibernate.jpa.HibernatePersistenceProvider$1.isLoadedWithoutReference(HibernatePersistenceProvider.java:188)
	at javax.persistence.Persistence$1.isLoaded(Persistence.java:111)
	at org.hibernate.validator.internal.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:47)
	at org.hibernate.validator.internal.engine.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:128)
	at org.hibernate.validator.internal.engine.resolver.CachingTraversableResolverForSingleValidation.isReachable(CachingTraversableResolverForSingleValidation.java:36)
	at org.hibernate.validator.internal.engine.ValidatorImpl.isReachable(ValidatorImpl.java:1612)
	at org.hibernate.validator.internal.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1597)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:609)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:582)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:528)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:496)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:461)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:411)
	at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:208)
	at io.dropwizard.configuration.BaseConfigurationFactory.validate(BaseConfigurationFactory.java:236)
	at io.dropwizard.configuration.BaseConfigurationFactory.build(BaseConfigurationFactory.java:128)
Caused by: java.lang.ClassNotFoundException: org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 26 more

Mailing List Issue: https://groups.google.com/forum/?fromgroups#!topic/pac4j-users/CxyAu7IJPk0

Publishing 3.0-RC1

@victornoel would it possible to publish dropwizard-pac4j and jax-rs-pac4j?

Alternatively is there a timeline on when they will be published?

Thanks,

JM

Enable Jetty sessions in Pac4jBundle

Very minor thing: as you know, Dropwizard does not enable sessions by default. It's easy to forget to enable them if using a pac4j client that requires them, so it might be useful to have some code that enables sessions if such a client has been specified.

public void build(Environment environment)
{
	boolean sessionsRequired = ...; // maybe from config?
	if (sessionsRequired)
	{
	    MutableServletContextHandler contextHandler = environment.getApplicationContext();
	    if (contextHandler.getSessionHandler() == null)
	    {
	        contextHandler.setSessionHandler(new SessionHandler());
	    }
	}
        
    ...
}

Consider making Pac4jFactory easier to extend

Currently Pac4jFactory is difficult to work with if you need to override things:

  1. the run() method is final, so you cannot extend the class to do additional (or different) configuration

  2. All collections used in this class are immutable which means you can't modify things later, such as adding clients or matchers,

That said, I fully acknowledge that doing these things might be abusing this bundle and that there may be better ways to do more customized/advanced configuration.

In my case I do this because

  • When trying to learn pac4j, it's easier and more flexible when you do the configuration in code (e.g. type-checking)

  • In my apps, authentication changes rarely and is configured the same way in dev and in production, so it might as well be in code.

Not compatible with dropwizard 2

The latest version of dropwizard (2.0.2 at the time of writing) uses jersey 2.30. dropwizard-pac4j depends on jersey225-pac4j, and as a result is not compatible.

A good solution might be to release separate artifacts targeting different dropwizard versions, similar to what jax-rs-pac4j does

Usage with ResourceTestRule

Are there any examples of using Dropwizard's ResourceTestRule with this module?

I'm getting a:

ERROR [2017-04-18 22:00:18,608] org.glassfish.jersey.internal.Errors: Following issues have been detected: 
WARNING: No injection source found for a parameter of type public ... (org.pac4j.core.profile.CommonProfile) at index 0.

error when trying to test my resource.

Dropwizard 3 support

There doesn't seem to be any Dropwizard 3 support right now in dropwizard-pac4j, but the changes required to support 3 look to be pretty simple. If I made a PR would there be any chance of getting it merged? There might be a good reason that supporting Dropwizard 3 is difficult that I'm not seeing. The hardest part might be figuring out a version number that would make sense....

FYI, the reason I need support for Dropwizard 3 is that my app has made extensive use of Hibernate Criteria queries and those block us from upgrading straight to 4. We'll eventually get rid of them all, but in the meantime we're planning to run Dropwizard 3. we're currently just modifying the source locally to make dropwizard-pac4j 6.0.0 work with Dropwizard 3, but it would be nicer to be able to import a compatible version of the library.

Authorizer Headers are not carried through to Response

I am not sure if this is an issue with dropwizard-pac4j or jax-rs-pac4j, or something I am doing incorrectly

Authorizers such as xssprotection, noframe, csrf, and nosniff work by setting a header on the WebContext. I have enabled these Authorizers, and I can see them being called and setting the header on the ServletJaxRsContext (I can see this by looking at the abortResponse). However, I do not see the headers in the server's response.

It seems that the headers from ServletJaxRsContext are lost and do not actually make it into the response.

Example code:

Pac4j Configuration:

bootstrap.addBundle(object : Pac4jBundle<MyConfiguration>() {
  override fun getPac4jFactory(config: MyConfiguration): Pac4jFactory {
    val encoder = SpringSecurityPasswordEncoder(BCryptPasswordEncoder())
    val dbAuthenticator = CustomDbAuthenticator(dbi, encoder)
    val formClient = FormClient("/auth/login", dbAuthenticator)

    val authMatcher = PathMatcher().apply {
      excludeBranch("/auth")
    }
    val globalAuthorizers = Pac4jFactory.JaxRsSecurityFilterConfiguration().apply {
      matchers = "auth"
      authorizers = "isFullyAuthenticated,csrf,nosniff,noframe,xssprotection"
    }

    return Pac4jFactory().apply {
      callbackUrl = "/auth/callback"
      globalFilters = listOf(globalAuthorizers)
      clients = listOf(formClient)
      matchers = mapOf("auth" to authMatcher)
    }
  }
}

Add Resources

override fun run(config: MyConfiguration, environment: Environment) {
  environment.jersey().register(AuthResource())
  environment.jersey().register(NormalResource())
}

AuthResource:

@Path("/auth")
class AuthResource() {

  @GET
  @Path("/login")
  @Produces(MediaType.TEXT_HTML)
  fun login(): View {
    return object : View("/login.ftl") {
      val callbackUrl = config.clients.findClient(FormClient::class.java).callbackUrl
    }
  }

  @POST
  @Path("/callback")
  @Pac4JCallback(renewSession = booleanArrayOf(false), defaultUrl = arrayOf("/normal/home/"))
  fun loginFormPost() {
    // Handled by pac4j
  }

  @GET
  @Path("/logout")
  @Pac4JLogout(defaultUrl = arrayOf("/auth/login"))
  fun logout() {
    // Handled by pac4j
  }
}

NormalResource:

This is where I would expect to have the headers set in the response, but they are not there.

@Path("/normal")
class NormalResource {

  @GET
  @Path("/home")
  @Produces(MediaType.TEXT_HTML)
  fun home(): View {
    return object : View("/home.ftl") {}
  }

  @GET
  @Path("/test")
  fun test(): Response {
    return Response.ok().build()
  }
}

Fix Javadoc warnings

When I released the version 1.0.0, I saw these Javadoc warnings:

    7 warnings
    [WARNING] Javadoc Warnings
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jBundle.java:45: warning: no @return
    [WARNING] public Collection<Pac4jFeatureSupport> supportedFeatures() {
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jConfiguration.java:13: warning: no description for @param
    [WARNING] * @param <T>
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jFactory.java:176: warning: no @return
    [WARNING] public String getClients() {
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jFactory.java:184: warning: no @return
    [WARNING] public String getAuthorizers() {
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jFactory.java:192: warning: no @return
    [WARNING] public String getMatchers() {
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jFactory.java:200: warning: no @return
    [WARNING] public Boolean getMultiProfile() {
    [WARNING] ^
    [WARNING] /Users/jleleu/releases/dropwizard-pac4j/target/checkout/src/main/java/org/pac4j/dropwizard/Pac4jFactory.java:208: warning: no @return
    [WARNING] public Boolean getSkipResponse() {
    [WARNING] ^

Unable to configure DbProfileService as authenticator

I have been trying to configure the DB authenticator with a CookieClient in the demo app, like this:

  clients:
      - org.pac4j.http.client.direct.CookieClient:
          cookieName: "demo"
          authenticator:
           class: org.pac4j.sql.profile.service.DbProfileService

But the application fails to start and shows this error message:

demo-config.yml has an error:

  • Failed to parse configuration at: pac4j.clients.[0].authenticator; Failed to load class 'javax.sql.DataSource$Access4JacksonDeserializerc5504170': com.fasterxml.jackson.module.afterburner.deser.BeanPropertyMutator
    at [Source: N/A; line: -1, column: -1] (through reference chain: org.pac4j.demo.dw.Pac4JDemoConfiguration["pac4j"]->org.pac4j.dropwizard.Pac4jFactory["clients"]->java.util.ArrayList[0]->org.pac4j.http.client.direct.CookieClient["authenticator"])

Dropwizard Application doesn't start when used with Guice

Throws the following exception on startup. The ServletJaxRsContextFactoryProvider has a request scoped injection thats causing this.

javax.servlet.ServletException: io.dropwizard.jersey.setup.JerseyServletContainer-5aab5b31@8b30bcb6==io.dropwizard.jersey.setup.JerseyServletContainer,jsp=null,order=1,inst=false
	at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:658)
	at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:421)
	at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:760)
	at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:348)
	at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785)
	at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:261)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at com.codahale.metrics.jetty9.InstrumentedHandler.doStart(InstrumentedHandler.java:103)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.handler.gzip.GzipHandler.doStart(GzipHandler.java:273)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.handler.StatisticsHandler.doStart(StatisticsHandler.java:252)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
	at org.eclipse.jetty.server.Server.start(Server.java:449)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.Server.doStart(Server.java:416)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at io.dropwizard.cli.ServerCommand.run(ServerCommand.java:53)
	at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:44)
	at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:85)
	at io.dropwizard.cli.Cli.run(Cli.java:75)
	at io.dropwizard.Application.run(Application.java:93)
Caused by: A MultiException has 1 exceptions.  They are:
1. com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped [javax.servlet.http.HttpServletRequest]. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request.
  at com.google.inject.servlet.InternalServletModule.provideHttpServletRequest(InternalServletModule.java:106) (via modules: com.google.inject.servlet.ServletModule -> com.google.inject.servlet.InternalServletModule)
  while locating javax.servlet.http.HttpServletRequest

1 error

	at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:494)
	at com.squarespace.jersey2.guice.GuiceScopeContext.findOrCreate(GuiceScopeContext.java:36)
	at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2022)
	at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:114)
	at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:88)
	at org.glassfish.jersey.internal.inject.ContextInjectionResolver.resolve(ContextInjectionResolver.java:126)
	at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:943)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:993)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:983)
	at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:617)
	at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:184)
	at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:350)
	at org.glassfish.jersey.server.ApplicationHandler$3.call(ApplicationHandler.java:347)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
	at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:255)
	at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:347)
	at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:392)
	at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:177)
	at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:369)
	at javax.servlet.GenericServlet.init(GenericServlet.java:244)
	at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:637)
	... 41 more
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot access scoped [javax.servlet.http.HttpServletRequest]. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request.
  at com.google.inject.servlet.InternalServletModule.provideHttpServletRequest(InternalServletModule.java:106) (via modules: com.google.inject.servlet.ServletModule -> com.google.inject.servlet.InternalServletModule)
  while locating javax.servlet.http.HttpServletRequest

1 error
	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028)
	at com.squarespace.jersey2.guice.GuiceBindingDescriptor.create(GuiceBindingDescriptor.java:66)
	at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:479)
	... 62 more
Caused by: com.google.inject.OutOfScopeException: Cannot access scoped [javax.servlet.http.HttpServletRequest]. Either we are not currently inside an HTTP Servlet request, or you may have forgotten to apply com.google.inject.servlet.GuiceFilter as a servlet filter for this request.
	at com.google.inject.servlet.GuiceFilter.getContext(GuiceFilter.java:165)
	at com.google.inject.servlet.GuiceFilter.getOriginalRequest(GuiceFilter.java:147)
	at com.google.inject.servlet.ServletScopes$1$1.get(ServletScopes.java:107)
	at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
	at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1019)
	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1085)
	at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1015)
	... 64 more

Cannot configure SAML2Client over yml file

It seems not to be possible to configure the SAML2Client over the yml file.

Take the following example config.yml file:

pac4j:
  callbackUrl: auth/callback

  clients:
    - org.pac4j.saml.client.SAML2Client: {}

Dropwizard fails to start with the following error message:

* Failed to parse configuration at: pac4j.clients.[0]; Can not find a deserializer for non-concrete Map type [map type; class java.security.Provider, [simple type, class java.lang.String] -> [simple type, class java.lang.String]]
 at [Source: N/A; line: -1, column: -1] (through reference chain: org.example.ApplicationConfiguration["pac4j"]->org.pac4j.dropwizard.Pac4jFactory["clients"]->java.util.ArrayList[0])

It seems that the client has some fields which make it not de-serializable.

Stateless session handling?

I have been trying to set up a Google OpenID Client login to my small webapp, but we are running multiple instances of the same application.

Are there any suggestions how am I supposed to do session handling in this case? I was thinking about storing the whole session in a cookie, so nothing is stored on server side, but I don't know how should I approach this.

Have anyone had some experiences similar to this?

Provide a way to define how JAX-RS Filters are created

In order to cover use cases such as pac4j/pac4j#700 or pac4j/jax-rs-pac4j#13, it would be great to have a way to specify how the filters are created.

Like this, the user can decide to modify the filter using the setters to change the logic or use an extension of the filter to redefine pac4j's behaviour.

Note that the objective is not to be able to modify filters for a given annotation or configuration, but more to do it in a general way. If one needs one specific filter on top of the normal ones, then it is better to register it in Jersey by hand.

disable authentication globally?

Is there any way I can disable authentication globally for the dropwizard service?

I have multiple deployment scenarios and I really need to be able to configure whether authentication is enabled in the dropwizard yml config.

I have tried to use a excludePath: ^(.*)$ but every class/method that has an annotation, eg

@Pac4JSecurity(clients="DirectBasicAuthClient" ,authorizers = "isAuthenticated")

still requires authentication.

Thanks

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • actions/checkout v4@0ad4b8fadaa221de15dcec353f45205ec38ea70b
  • actions/setup-java v4
  • actions/cache v4
  • actions/checkout v4@0ad4b8fadaa221de15dcec353f45205ec38ea70b
  • actions/setup-java v4
maven
pom.xml
  • org.sonatype.oss:oss-parent 9
  • io.dropwizard:dropwizard-bom 4.0.7
  • org.junit:junit-bom 5.10.2
  • org.pac4j:pac4j-core 5.7.4
  • org.slf4j:slf4j-api 2.0.13
  • org.assertj:assertj-core 3.25.3
  • org.mockito:mockito-core 5.11.0
  • org.pac4j:pac4j-config 5.7.4
  • org.pac4j:jersey3-pac4j 6.0.1
  • org.pac4j:jakartaee-pac4j 7.1.0
  • org.pac4j:pac4j-http 5.7.4
  • org.pac4j:pac4j-oauth 5.7.4
  • org.apache.maven.plugins:maven-compiler-plugin 3.13.0
  • org.apache.maven.plugins:maven-source-plugin 3.3.1
  • org.apache.maven.plugins:maven-surefire-plugin 3.2.5
  • org.apache.maven.plugins:maven-javadoc-plugin 3.6.3
  • com.github.spotbugs:spotbugs-maven-plugin 4.8.5.0
  • com.github.spotbugs:spotbugs 4.8.5
  • org.apache.maven.plugins:maven-pmd-plugin 3.22.0
  • org.apache.maven.plugins:maven-enforcer-plugin 3.4.1
  • org.apache.maven.plugins:maven-gpg-plugin 3.2.4

  • Check this box to trigger a request for Renovate to run again on this repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.