Using Multiple Authentication Providers with @Auth

2,377 views
Skip to first unread message

Peter Briggs

unread,
Aug 26, 2013, 8:45:46 AM8/26/13
to dropwiz...@googlegroups.com
Hi all,

Does Dropwizard have any built-in support for using multiple authentication providers?

For example, I want to add a basic auth provider and an OAuth2 provider and then specify at the resource level which provider should be used.

When I tried adding both providers and then used the @Auth annotation on a resource it seemed to default to authenticating against the first provider that I added. If there is some way to specify which provider should be used, that would be great.

Thanks!
Pete

Coda Hale

unread,
Aug 26, 2013, 9:23:55 AM8/26/13
to dropwiz...@googlegroups.com
It doesn't support that, no.


--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-us...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Coda Hale
http://codahale.com

Peter Briggs

unread,
Aug 26, 2013, 9:50:46 AM8/26/13
to dropwiz...@googlegroups.com
Ok, thanks for the quick response Coda.

Christopher Currie

unread,
Aug 26, 2013, 12:37:51 PM8/26/13
to dropwiz...@googlegroups.com
One idea I've explored for this use case is to have the different authenticators support different principal types. Something like this might work:


It's weakness is that you have to have two different principal types, but you might be able to mitigate it using a common base class (as demonstrated in the gist) or using a parameterized class.

HTH,
Christopher

Peter Briggs

unread,
Aug 27, 2013, 4:55:08 AM8/27/13
to dropwiz...@googlegroups.com
Great, thanks for the gist Christopher - it seems like that sort of approach would work in my case alright.

Just to check I understand correctly, in your example the decision about whether to use basic auth or OAuth would happen in the provider, is that right? So instead of trying to work with two separate providers (which is what I was looking at previously), I would just have one provider that would look at the request headers to determine whether basic auth or oauth should be used, and then call the .authenticate() method of the appropriate Authenticator?

Thanks,
Pete

Christopher Currie

unread,
Aug 27, 2013, 1:03:07 PM8/27/13
to dropwiz...@googlegroups.com
I have to say, I'm not 100% certain on this one. When I wrote that gist, I had assumed that Jersey would select a provider based on the type of the injected argument. But reading the code, I'm pretty sure that it wouldn't. So to use my gist, it would appear that you'd need to write a provider that would look at the type provided to getInjectable(), and select the Authenticator to use.

However, now that I know you'd have to write a new provider anyway, I think a better idea would be to use different annotations to select the kind of authentication you would want.

The idea is, if the provider returns null, Jersey will keep looking for a new provider that can do the job. So, create some marker annotations:

    @Target(...)
    @Retention(...)
    public @interface HttpBasicAuth {}

use it, along with @Auth, in your resources:

    @GET
    public String resourceMethod(@Auth @HttpBasicAuth User user)
    {
    }

and register derived provider that looks for it:

public class AnnotatedBasicAuthProvider<T> extends BasicAuthProvider<T> {

    public AnnotatedBasicAuthProvider(Authenticator<BasicCredentials, T> authenticator, String realm) {
        super(authenticator, realm);
    }
    
    @Override
    public Injectable<?> getInjectable(ComponentContext ic,
                                       Auth a,
                                       Parameter c)
    {
        if (c.isAnnotationPresent(HttpBasicAuth.class)) {
            return super.getInjectable(ic, a, c);            
        }
        
        return null;
    }

}

This would allow multiple providers to be registered and doesn't require multiple user principal types.

Of course, you don't have to use marker annotations to select which methods get which auth type, the provider could use any logic it wanted.

HTH,
Christopher

Peter Briggs

unread,
Aug 28, 2013, 11:37:56 AM8/28/13
to dropwiz...@googlegroups.com
Thanks very much for the detailed suggestions Christopher - I think you're correct that Jersey won't select the right provider automatically, so I'll look at letting the provider(s) handle the selection logic.

Ken Yee

unread,
Aug 28, 2013, 1:25:23 PM8/28/13
to dropwiz...@googlegroups.com
I know this is heresy for some folks, but why wouldn't you use Dropwizard integrated w/ Spring if you want to use multiple providers at once?
Spring Security does support it:
  http://static.springsource.org/spring-security/site/docs/3.1.x/reference/core-services.html#core-services-authentication-manager


Peter Briggs

unread,
Aug 29, 2013, 7:54:52 AM8/29/13
to dropwiz...@googlegroups.com
In my case there's no particular reason other than that I don't have the experience with Spring - thanks for the link though, I'll take a look at Dropwizard/Spring integration as an option.


--
You received this message because you are subscribed to a topic in the Google Groups "dropwizard-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dropwizard-user/txI-Epmy42c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dropwizard-us...@googlegroups.com.

Sbham

unread,
Oct 14, 2014, 8:12:32 AM10/14/14
to dropwiz...@googlegroups.com
Hey there,

Has anybody figured a way to user multiple auth providers in one DW app, and scope them by resources. something of the sort of: a few token related rest resources would use auth basic, and the rest would use a jwt auth provider?
If not, would could one use one dw app that has the very few resources for basic (myapi/tokens: GET, POST...), and in a different app use a jwt provider (myapi/allmyresources) ?

Just wondering, it would make sense for DW to "scope" authproviders by resource methods/classes? I guess one would have to make sure to have the same subject....

Cheers!
-S

Javier Campanini

unread,
Oct 14, 2014, 10:19:01 AM10/14/14
to dropwiz...@googlegroups.com
The auth bits are just different Jersey Providers. If you were dead set on doing this using only the things Dropwizard provides, write different annotations for each auth method, and supply your own providers.

For example, create a @TokenedAuth + @JwtAuth annotation + provider, and have it check for a token, etc.

Another solution, even though it's more heavy weight, is to use something like Apache Shiro to do auth. It explicitly lets you set what sort of filters you want on each URL. It adds a level of complexity (it's a whole auth framework) but it should do what you're looking for.

Bilal Aslam

unread,
Oct 14, 2014, 3:37:08 PM10/14/14
to dropwiz...@googlegroups.com
We do this today in 0.7.1. This becomes simpler in 0.8 because of AuthFactory. Okay, here's what we did - we created a new auth provider that implements InjectableProvider<Auth, Parameter>. This provider inspects the HTTP request and, in our case, depending on the Authorization header's starting value (Basic or Bearer) it calls the appropriate authenticator. It didn't take too long to build this but it's not easily extensible (which is why DW devs are making this easier in an upcoming release).

Sbham

unread,
Oct 17, 2014, 12:18:36 PM10/17/14
to dropwiz...@googlegroups.com
Thanks Bilal & Javier! that was very much helpful.

I was trying to stay within the native DW facilities and extend an injectable provider. I came to the same design as Bilal, where depending on the header, I do what is necessary...

However, I cam across this SO answer, that I though would be a good read to the group: http://stackoverflow.com/questions/20662871/how-to-do-basic-authentication-of-a-resource-in-dropwizard/20663876#20663876


I didn't hear about the AuthFactory, any more details on it ?

Cheers!
-S

chri...@gmail.com

unread,
Jan 16, 2015, 6:25:59 AM1/16/15
to dropwiz...@googlegroups.com
Just for information:

I had some success upgrading to DW v0.8.0rc1, which introduces AuthFactory, and using the ChainedAuthFactory in particular. The code for the v0.8.0rc1 auth module is here in Github and documentation here.

Kevin Kuhl

unread,
May 19, 2015, 3:45:03 PM5/19/15
to dropwiz...@googlegroups.com
Hey Chris,

Did ChainedAuthFactory help you here? ChainedAuthFactory is designed to authenticate using the first of many registered auth providers. It seems like if you want "mutually exclusive" authentication providers for your resources, you'd need to do something different. I've been looking at the 0.8.0 code trying to see how I could change a few things to create a new authentication provider and amended Auth annotation that would allow a resource to provide authentication with exactly ONE of many providers. I'm also on 0.8.0 btw.

Just wondering if you found an easier way to handle this.

Thanks
Kevin

Kevin Kuhl

unread,
May 19, 2015, 4:15:07 PM5/19/15
to dropwiz...@googlegroups.com
Sorry forgot to add about the potential approach:

The simplest way I can think about doing this is to add another AuthFactory very similar to ChainedAuthFactory but that checks a property of the annotation during createValueFactory that names the specific Class of the provider one calls out to authenticate the resource with. Creating a new extension of AuthFactory is no big, but the Annotation bit is a bit invasive due to the inability to extend annotations. I'd have to modify the Auth.java class to have a new property of type Class and modify some of the places those properties are passed into constructors and clone() methods.

Maybe this approach is naive, it's just surfaced from sitting looking through the code a bit. Any insight would be appreciated.

Thanks,
Kevin

Evan Meagher

unread,
Dec 30, 2015, 1:31:37 PM12/30/15
to dropwizard-user, kku...@gmail.com
Pardon the gravedigging, but I ran into a similar issue a few months ago wherein I wanted endpoints authenticated by different Principals. I've been running a solution similar to that proposed by Kevin Kuhl without issue.

Reply all
Reply to author
Forward
0 new messages