ToastShaman / dropwizard-auth-jwt

A Dropwizard authentication filter using JSON Web Token (JWT)
Apache License 2.0
116 stars 50 forks source link

Authorization headers with base64 padding lead to exception #13

Closed keyboardsamurai closed 8 years ago

keyboardsamurai commented 8 years ago

Using dropwizard-auth-jwt version 0.8.1-1 and dropwizard 0.8.1. According to the form on http://jwt.io/ this here is a perfectly valid header:

eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFM1MTIifQ==.eyJzdWJqZWN0IjoiZ29vZC1ndXkifQ==.gPQWFSJRuMVr6NvMeKzpO8GVTf8ZfoQgAhI3AGj+yO94ZgZBbxM/guX1RaogQIlxSpNQ1axQgpZtOi1MpxM0ng==

When I try to send it to the server though I get an Exception because the decoding part doesn't seem to expect the padding '=' characters.

Here is the Exception:

ERROR [2015-09-22 22:21:23,557] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 5d18365d900cf40f
! com.google.common.io.BaseEncoding$DecodingException: Unrecognized character: =
! at com.google.common.io.BaseEncoding$Alphabet.decode(BaseEncoding.java:503) ~[guava-18.0.jar:na]
! at com.google.common.io.BaseEncoding$StandardBaseEncoding$2.read(BaseEncoding.java:675) ~[guava-18.0.jar:na]
! at com.google.common.io.BaseEncoding.decodeChecked(BaseEncoding.java:245) ~[guava-18.0.jar:na]
! at com.google.common.io.BaseEncoding.decode(BaseEncoding.java:226) ~[guava-18.0.jar:na]
! ... 57 common frames omitted
! Causing: java.lang.IllegalArgumentException: com.google.common.io.BaseEncoding$DecodingException: Unrecognized character: =
! at com.google.common.io.BaseEncoding.decode(BaseEncoding.java:228) ~[guava-18.0.jar:na]
! at com.github.toastshaman.dropwizard.auth.jwt.JsonWebTokenUtils.fromBase64(JsonWebTokenUtils.java:26) ~[dropwizard-auth-jwt-0.8.1-1.jar:na]
! at com.github.toastshaman.dropwizard.auth.jwt.JsonWebTokenUtils.fromBase64ToString(JsonWebTokenUtils.java:30) ~[dropwizard-auth-jwt-0.8.1-1.jar:na]
! at com.github.toastshaman.dropwizard.auth.jwt.parser.DefaultJsonWebTokenParser.parse(DefaultJsonWebTokenParser.java:32) ~[dropwizard-auth-jwt-0.8.1-1.jar:na]
! at com.github.toastshaman.dropwizard.auth.jwt.JWTAuthFactory.provide(JWTAuthFactory.java:95) ~[dropwizard-auth-jwt-0.8.1-1.jar:na]
! at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:125) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:158) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:101) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:305) ~[jersey-server-2.17.jar:na]
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [jersey-common-2.17.jar:na]
! at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:288) [jersey-server-2.17.jar:na]
! at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1110) [jersey-server-2.17.jar:na]
! at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:401) [jersey-container-servlet-core-2.17.jar:na]
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386) [jersey-container-servlet-core-2.17.jar:na]
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335) [jersey-container-servlet-core-2.17.jar:na]
! at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:222) [jersey-container-servlet-core-2.17.jar:na]
! at io.dropwizard.jetty.NonblockingServletHolder.handle(NonblockingServletHolder.java:49) [dropwizard-jetty-0.8.1.jar:0.8.1]
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83) [jetty-servlets-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364) [jetty-servlets-9.2.9.v20150224.jar:9.2.9.v20150224]
! at io.dropwizard.jetty.BiDiGzipFilter.doFilter(BiDiGzipFilter.java:134) [dropwizard-jetty-0.8.1.jar:0.8.1]
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at io.dropwizard.servlets.ThreadNameFilter.doFilter(ThreadNameFilter.java:29) [dropwizard-servlets-0.8.1.jar:0.8.1]
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.handle(AllowedMethodsFilter.java:44) [dropwizard-jersey-0.8.1.jar:0.8.1]
! at io.dropwizard.jersey.filter.AllowedMethodsFilter.doFilter(AllowedMethodsFilter.java:39) [dropwizard-jersey-0.8.1.jar:0.8.1]
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at com.myapp.server.CacheControlFilter.doFilter(CacheControlFilter.java:20) [classes/:na]
! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) [jetty-servlet-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:240) [metrics-jetty9-3.1.1.jar:3.1.1]
! at io.dropwizard.jetty.ContextRoutingHandler.handle(ContextRoutingHandler.java:38) [dropwizard-jetty-0.8.1.jar:0.8.1]
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:95) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:159) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.Server.handle(Server.java:497) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) [jetty-server-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540) [jetty-io-9.2.11.v20150529.jar:9.2.11.v20150529]
! at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) [jetty-util-9.2.9.v20150224.jar:9.2.9.v20150224]
! at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) [jetty-util-9.2.9.v20150224.jar:9.2.9.v20150224]
! at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
keyboardsamurai commented 8 years ago

Reading up on how base64 encoding should be handled in https://www.rfc-editor.org/rfc/rfc7515.txt tells me that padding should not be added. It would be nice to have some leniency, let alone better error handling, but I guess my client library is mostly at fault here.

keyboardsamurai commented 8 years ago

Just in case anyone comes across this issue and is interested in supporting more lenient padding handling, swap out the fromBase64 method in JsonWebTokenUtils with this while you get your client library fixed.

public static byte[] fromBase64(String input) {
    if(input.contains("=")){
        return BaseEncoding.base64().decode(input);
    }else{
        return BaseEncoding.base64Url().omitPadding().decode(input);
    }
}