Repository navigation
java.lang.NoSuchMethodError for Base64.decodeBase64(String) #131
Description
Hi, while using your library I encountered the following runtime exception, which crashes my app:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xxxx.yyyy, PID: 17510
java.lang.NoSuchMethodError: No static method decodeBase64(Ljava/lang/String;)[B in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar)
at com.xxxx.yyyy.network.RealNetworkController$2.onResponse(RealNetworkController.java:172)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
This is caused by your use of the Apache Commons Codec library, in JWTDecoder.java:38:
headerJson = StringUtils.newStringUtf8(Base64.decodeBase64(parts[0]));
payloadJson = StringUtils.newStringUtf8(Base64.decodeBase64(parts[1]));
I have investigated the issue, and I believe it's down to an obscure problem with Android.
The Problem
Until recently, Android was bundled with Apache's HttpClient, which depended on Commons Codec.
However, the version originally bundled with Android (1.3) does not contain the static decodeBase64(String) method. Furthermore, this ancient version overrides the version you specify in your lib's build.gradle.
For a better explanation, see this blog post, and these stack overflow posts:
- http://stackoverflow.com/a/34473643
- http://stackoverflow.com/a/5902269
- http://stackoverflow.com/questions/24306695/base64-dependencies-issue-in-android-studio
The reason you (the developers of java-jwt) may not have been experiencing this error and I have, is because this ancient dependency has been removed from android entirely, after SDK 23 (version 6.0), removing the problem.
Unfortunately for me, my app's minimum version is 4.4 (SDK 19), so I suspect that the legacy code is still in my classpath (this is corroborated by the exception message I pasted above:
declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar
This effectively gives your library an undocumented requirement for Android SDK 23 and above!
The Solution
Some people have been using a workaround, but I would recommend that you simply replace your Commons Codec call with the android-internal Base64 implementation. I will be submitting a pull request to this effect, if/when I have time.
TL;DR
You have an obscure bug to do with historical dependencies in Android on Apache Commons Codec.
I'll submit a PR when I can.
Activity
hzalaz commentedon Jan 6, 2017
@medavox we didn't build this library to be used in Android apps
medavox commentedon Jan 6, 2017
But it is, and has been. It's on jcenter, and it works (almost) without modification.
If this is not OK then sorry, but i didn't know. It didn't feel too difficult to use, to be Java only. Was not obvious from my discovery path.
Would you still accept a pull request to fix this that doesn't rely on android APIs, or should i find another library?
EDIT: I've checked, and i can't see a separate listing for Android libraries on http://jwt.io/ .
This means the main landing page for searches about JWT doesn't make a distinction between Java and Android JWT libraries, even though for you there is.
Obviously, you don't have control of that site (unless you do), so you may wish to inform them of this.
hzalaz commentedon Jan 6, 2017
There are more than android libraries in jcenter and not all are usable in an app since the JVM of android has some restrictions compared to regular JVM.
I would accept a PR if it doesn't break any public API of the library and fixes the issue 😄
Also just a quick note, we are not relying on any Android API, the error might be caused by something else, probably our base64 dependency that is not compatible with Android
medavox commentedon Jan 6, 2017
I should really have put my above edit in another post, apologies.
Thanks for your quick replies, I'll see if there is a mutually satisfactory fix.
DuncanTyrell commentedon Jan 10, 2017
@medavox did you find a fix to this yet? I've just hit the same issue and glad I checked in here. I've used other libs for handling JWTs on Android in the past and am wondering whether to abandon this in favour of one that works, or try and fix this one. If you fancy a catchup about the options some time message me duncan@tyrell.digital. We're also local by the way - I'm based up the road in Leeds.
hzalaz commentedon Jan 10, 2017
@DuncanTyrell what do you need to do with the JWT? if it's only decode we already have a lib https://github.com/auth0/JWTDecode.Android to do that. It's unusual for an Android app to verify or even sign a token
DuncanTyrell commentedon Jan 10, 2017
Thanks for the swift response @hzalaz! I'll have a look at that library - much appreciated.
DuncanTyrell commentedon Jan 10, 2017
Yep that seems to do everything I need for now anyway @hzalaz - thanks again for your help and super-responsive turnaround.
Create a wrapper to access Base64 encode/decode to fix bug auth0#131 …
rakaadinugroho commentedon Dec 25, 2017
i have solution for @medavox your problem, i have same problem. and to Sign with RSA256 Algorithm you must have Private Key. the Private Key must be PKCS#8 format. and save to Private.der , because Java cannot read private key except PKCS#8.
and iam not using this library. i use this library https://github.com/jwtk/jjwt
qwertukg commentedon Jan 24, 2018
Still have it on Spring application:
lbalmaceda commentedon Jan 24, 2018
@qwertukg please provide a repro project so we can narrow down the problem.
qwertukg commentedon Jan 24, 2018
if u talking about repository of project, I can't to pass it. Maybe u need some more information ?
lbalmaceda commentedon Jan 24, 2018
The original issue on this post is related to the library being used on an Android environment. Android is known to have a different Base64 implementation, and Apache Commons can't be used there because of the JVM. If you say the issue appears also on Spring that worries me, but if I don't know what you're doing I can't help you.
I'm not talking about the original project where you're working on but a simple sample project you can create in the next few minutes and disclose to us where the issue can be reproduced, for us to narrow the cause. Please push it to a public repo. Without that I'll have to route you to https://support.auth0.com
qwertukg commentedon Jan 24, 2018
Ok. Will try to reproduce it on a simple project tomorrow. Now just can to say what this project have a lot of dependencies and it's based on spring 3
lbalmaceda commentedon Jan 24, 2018
Then it should work unless one of your project dependencies uses a different version of apache commons lib that doesn't have that class method. Try searching in the dependency tree if this is the case and see if removing that dependency fixes the problem.
qwertukg commentedon Jan 25, 2018
It was commons-codec-1.2 there is no method with signature
decodeBase64(String)onlydecodeBase64(Byte[])lbalmaceda commentedon Jan 25, 2018
@qwertukg Ah yes, that's from 2005. The latest version is the one we use.
trajkovski731 commentedon Jun 7, 2018
And did you fixed it? It has past a lot of time.
lbalmaceda commentedon Jun 7, 2018
@trajkovski731 this library is not meant to be used on Android (we don't support it up-front). Is that your case or are you having a different error? If so, please post the details either here (if related) or in a separate new issue.
nanangTriAndika commentedon Jun 8, 2018
For anyone who struggle using apache common codec inline with android SDK ( especially when got conflict when using Base64 function ), you can use this library. Just pull and compiled the code or download through release tab for lazy programmer =P
https://github.com/nanangTriAndika/customApacheCommonCodec
qwertukg commentedon Jun 11, 2018
@trajkovski731 yep, i was fix it by excluding this lib from my dependency tree
On device machine learning word to vector training
va26 commentedon Feb 12, 2019
I am facing the same problem while trying to use the Google Speech-to-Text API given here. This is what I get in the logs:
Please help me resolve this. Thank you.
lbalmaceda commentedon Feb 12, 2019
@va26 As you see in your logs this is not related at all with a class from this SDK. You will have to report it in google's issue tracker instead.