Description
Parsin JWT string using jjwt-0.5 fails on android platform.
jjwt library is added to android project as gradle dependency.
compile 'io.jsonwebtoken:jjwt:0.5'
Following code
String json = "{ \"name\" : \"John\"}";
String jwt = Jwts.builder().setPayload(json).compact();
System.out.println("JWT = " + jwt);
String name = Jwts.parser().parseClaimsJwt(jwt).getBody().get("name").toString();
System.out.println("name = " + name);
works correctly on desktop JDK producing following output
JWT = eyJhbGciOiJub25lIn0.eyAibmFtZSIgOiAiSm9obiJ9.
name = John
However when the same code is run on android (Nexus-5 device running android 5.1.1) if fails with exception thrown from parseClaimsJwt
method:
JWT = eyJhbGciOiJub25lIn0.eyAibmFtZSIgOiAiSm9obiJ9.
Caused by: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported.
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJwt(DefaultJwtParser.java:365)
at com.example.MainActivity.onCreate(MainActivity.java:53)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
... 10 more
Caused by: java.lang.IllegalArgumentException: bad base-64
at android.util.Base64.decode(Base64.java:161)
at android.util.Base64.decode(Base64.java:136)
at android.util.Base64.decode(Base64.java:118)
at io.jsonwebtoken.impl.AndroidBase64Codec.decode(AndroidBase64Codec.java:28)
at io.jsonwebtoken.impl.Base64UrlCodec.decode(Base64UrlCodec.java:78)
at io.jsonwebtoken.impl.AbstractTextCodec.decodeToString(AbstractTextCodec.java:36)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:161)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:325)
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJwt(DefaultJwtParser.java:358)
It looks to me that android.util.Base64.decode()
method (that is used internally by jjwt) requires input to contain padding characters (=
) (or it just needs to be configured/called different way).
If I modify JWT string passed to parseClaimsJwt
method by adding missing padding character (=
) then it works correctly on android. Following code (with =
added in proper place inside JWT string)
String jwt = "eyJhbGciOiJub25lIn0=.eyAibmFtZSIgOiAiSm9obiJ9.";
String name = Jwts.parser().parseClaimsJwt(jwt).getBody().get("name").toString();
System.out.println("name = " + name);
... produces expected result:
name = John
I glimpsed quickly through the jjwt code and line https://github.com/mikosik/jjwt/blob/master/src/main/java/io/jsonwebtoken/impl/Base64UrlCodec.java#L85 looks fishy to me.
It is:
int paddingCount = chars.length % 4;
but I guess it should be
int paddingCount = 4 - chars.length % 4;
Activity
lhazlewood commentedon Jun 26, 2015
Thanks for the report! This should be relatively easy to fix.
#31: fixed base64 url padding bug
Merge pull request #32 from jwtk/base64padding
lhazlewood commentedon Jun 26, 2015
The PR for this was successful and merged to master. The fix will be in the 0.5.1 release.
#31: updated release notes to reflect upcoming 0.5.1 release
#31: prepping for maven release build
lhazlewood commentedon Jun 26, 2015
This has been released as 0.5.1. Please allow 1 to 2 hours for the release artifact to appear in Maven Central. Cheers!
mikosik commentedon Jun 28, 2015
@lhazlewood Great! Thanks for a quick response and fix. 🙇