I have a jwt token like this
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
How can I decode this so that I can get the payload like this
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
I have used this library, but can't find a way to do what I want
you should split string: If you pass the first two sections through a base 64 decoder, you'll get the following (formatting added for clarity):
header
{
"alg": "HS256",
"typ": "JWT"
}
body
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Code example:
public class JWTUtils {
public static void decoded(String JWTEncoded) throws Exception {
try {
String[] split = JWTEncoded.split("\\.");
Log.d("JWT_DECODED", "Header: " + getJson(split[0]));
Log.d("JWT_DECODED", "Body: " + getJson(split[1]));
} catch (UnsupportedEncodingException e) {
//Error
}
}
private static String getJson(String strEncoded) throws UnsupportedEncodingException{
byte[] decodedBytes = Base64.decode(strEncoded, Base64.URL_SAFE);
return new String(decodedBytes, "UTF-8");
}
}
Call method for example
JWTUtils.decoded("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ");
library reference: https://github.com/jwtk/jjwt
jwt test: https://jwt.io/
I used a third-party library named JWTDecode.Android https://github.com/auth0/JWTDecode.Android . The documentation is reasonably good. From your question, The sub, name, etc are a part of the body and are called Claims. You could get them like this using the above library:
JWT parsedJWT = new JWT(jwtToken);
Claim subscriptionMetaData = parsedJWT.getClaim("name");
String parsedValue = subscriptionMetaData.asString();
This works using Java 8's Base64 class:
public String getDecodedJwt(String jwt)
{
String result = "";
String[] parts = jwt.split("[.]");
try
{
int index = 0;
for(String part: parts)
{
if (index >= 2)
break;
index++;
byte[] partAsBytes = part.getBytes("UTF-8");
String decodedPart = new String(java.util.Base64.getUrlDecoder().decode(partAsBytes), "UTF-8");
result += decodedPart;
}
}
catch(Exception e)
{
throw new RuntimeException("Couldnt decode jwt", e);
}
return result;
}
If the project is already using AWSCognito SDK then CognitoJWTParser
class can be used. It has static methods getHeader()
, getPayload()
, getSignature()
.
I've used it in a Java web application and the code will look something like the below:-
Jwts.parser().setSigningKey('secret-key').parseClaimsJws(token).getBody()
It will return claims which contain the required values.
Based partially on the code provided by Brad Parks , adapted for use with lower versions of Android by using Apache Commons and converted to Kotlin:
In build.gradle
:
implementation 'apache-codec:commons-codec:1.2'
In a Kotlin class:
fun decodeToken(token: String): String{
val tokenParts: Array<String> = token.split(".").toTypedArray()
if(tokenParts.isEmpty()) return token
var decodedString = ""
for(part: String in tokenParts){
val partByteArray: ByteArray =
stringToFullBase64EncodedLength(part).toByteArray(Charsets.US_ASCII)
val decodedPart = String(Base64.decodeBase64(partByteArray))
decodedString+=decodedPart
// There are a maximum of two parts in an OAuth token,
// and arrays are 0-indexed, so if the index is 1
// we have processed the second part and should break.
if(tokenParts.indexOf(part) == 1) break
}
return decodedString
}
private fun stringToFullBase64EncodedLength(string: String): String{
// A properly base64 encoded string must be divisible by 4
// We'll pad it to the nearest multiple of 4 without losing data:
val targetLength: Int = ( 4 * ceil( string.length.toDouble()/4 ) ).toInt()
// Now, we get the difference, and add it with a reserved character (`=`)
// to the end of the string. It will get removed later.
val requiredPadding: Int = targetLength-string.length
return string+"=".repeat(requiredPadding)
}
A no dependency version in Kotlin with Android SDK 26+ (Oreo):
fun extractJwt(jwt: String): String {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return "Requires SDK 26"
val parts = jwt.split(".")
return try {
val charset = charset("UTF-8")
val header = String(Base64.getUrlDecoder().decode(parts[0].toByteArray(charset)), charset)
val payload = String(Base64.getUrlDecoder().decode(parts[1].toByteArray(charset)), charset)
"$header\n$payload"
} catch (e: Exception) {
"Error parsing JWT: $e"
}
}
If you are using the library io.jsonwebtoken.Jwts
, then use the following snippet. It works for me.
try {
val claims: Claims =
Jwts.parser().setSigningKey(secretKey.toByteArray()).parseClaimsJws(token).body
return ConnectionClaim(claims["uid"].toString(), claims["key"].toString())
} catch (e: JwtException) {
e.printStackTrace()
}
this code convert JWT
to String
and work on any API
public static String getDecodedJwt(String jwt)
{
StringBuilder result = new StringBuilder();
String[] parts = jwt.split("[.]");
try
{
int index = 0;
for(String part: parts)
{
if (index >= 2)
break;
index++;
byte[] decodedBytes = Base64.decode(part.getBytes("UTF-8"), Base64.URL_SAFE);
result.append(new String(decodedBytes, "UTF-8"));
}
}
catch(Exception e)
{
throw new RuntimeException("Couldnt decode jwt", e);
}
return result.toString();
}
Example :
JWTUtils.getDecodedJwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c")
And finally the resulting conversion
{"alg":"HS256","typ":"JWT"}{"sub":"1234567890","name":"John Doe","iat":1516239022}
Almost all forgot to add imports and select android.util.Base64 !
import android.util.Base64
import org.json.JSONException
// Json data class
data class Data(
val name: String?,
val nonce: String?,
// Other access_token fields
)
fun parseAccessToken(token: String): Data? {
return try {
val part = token.split(".")[1]
val s = decodeJwt(part)
// obj is an object of Gson or Moshi library
obj.fromJson(s)
} catch (e: Exception) {
null
}
}
@Throws(JSONException::class)
private fun decodeJwt(text: String): String {
val s = Base64.decode(text, Base64.URL_SAFE)
return String(s)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.