I think that your suggested "closest thing" isn't *too* far off the mark of what the quoted documentation snippet is referring to. For each request, dropwizard-auth sniffs the SecurityContext for any in-context Principals. If it doesn't find a Principal, then it throws the "Cannot inject a custom principal" exception that you're observing.
In your `filter` method, you need to manually inject a "shim" Principal into the current ContainerRequestContext in the case where one doesn't already exist for the user you've extracted from the cookie. On Fri, Jul 8, 2016 at 8:56 AM, <[email protected]> wrote: > Hi friends! > > I'm enjoying Dropwizard, but scratching my head about how to go about > Optionally protecting resources. The older Auth model had `@Auth(required = > false)`, and after upgrading, I've more or less got what I'd like, but > having trouble fully understanding the line in the documentation > <http://www.dropwizard.io/0.9.3/docs/manual/auth.html>: > > "you need to implement a custom filter which injects a security context > containing the principal if it exists, without performing authentication." > > Maybe some code would help. I have an Auth filter that reads cookie values > to check a session ID (this is Kotlin, so please excuse any differences > with Java): > > ``` > override fun filter(requestContext: ContainerRequestContext?) { > val cookieValue : String? = getCookie(requestContext) > try { > if (cookieValue != null) { > val credentials : MyCredentials = > MyCredentials.fromCookie(cookieValue) > val result : Optional<User> = > authenticator.authenticate(credentials) > if (result.isPresent) { > requestContext?.securityContext = object: SecurityContext { > override fun isUserInRole(role: String?): Boolean { > return authorizer.authorize(result.get(), role) > } > override fun getAuthenticationScheme(): String { > return SecurityContext.FORM_AUTH > } > override fun getUserPrincipal(): Principal { return > result.get() } > override fun isSecure(): Boolean { return > requestContext?.securityContext?.isSecure ?: false } > } > return > } > } > return > } catch (e : IllegalArgumentException) { > LOGGER.warn("Error decoding credentials:", e) > } catch (e : AuthenticationException) { > LOGGER.warn("Error authenticating credentials", e) > throw InternalServerErrorException() > } > throw > WebApplicationException(unauthorizedHandler.buildResponse(prefix, realm)) > } > ``` > > Which then I register with my app using: > > ``` > env.jersey().register(AuthDynamicFeature(MyAuthFilter.Builder() > .setAuthenticator(MyAuthenticator(sessions, userDao)) > .setAuthorizer(PermitAllAuthorizer()) > .setPrefix("MyApp") > .setRealm("myRealm") > .buildAuthFilter())) > env.jersey().register(AuthValueFactoryProvider.Binder(User::class.java)) > ``` > > This works fine for ensuring anything annotated with `@Auth` is mandatory > protection. But for optional protection, how do I alter the filter above? > If you return null in `getUserPrincipal`, the app fails with "Cannot inject > a custom principal into unauthenticated request". > > The closes thing I can think of is creating a static `OPTIONAL_AUTH` > instance of my Principal to return in a SecurityContext when the > session/cookie doesn't work out, and checking against it in my resources, > subsequently throwing 401s for anything I deem "mandatory protection" but > this feels extremely hacky and I'm sure there's a Better Way. > > Any help would be appreciated. Thanks so much for your time :D > > -Pablo > > -- > 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 [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- Evan Meagher -- 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
