Lakie
Lakie

Reputation: 15

How to collect the signature, header and body from JWT on Android

I recently got to know about Json Web Token (JWT). Since I liked how it works I have started to implement it on my project. My project involves two apps to communicate. One is an android app and the other is Laravel web application.

The mobile app logs in after the user credential is authenticated from the server side.

I have sent the username and password to server from the mobile app and I have got the JWT in string format. But from this point onward I couldn't find a way to collect the JWT content.

I have gone through almost all possible shown (googled results) but I couldn't manage to get the contents, signature and header.

One of the method I have got a little bit further with, was using the following code, notice I have removed the setSigningKey():

try {
  Claims claims = Jwts.parser().parseClaimsJwt(jwtHeaderAndClaim).getBody();
  System.out.println("ID of the claims: " + claims.getId().toString());
  }catch (Exception e){
    Log.e("Exception: ", e.toString());
}

The above code generates the following error:

Exception: io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before 2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´ 

the jwtHeaderAndClaim is the JWT String after removing the signature part only (i.e: "xxxxxx.yyyyyyyy."). if i put the jwtString (xxxxxxx.yyyyyyyy.ccccccc) instead of jwtHeaderAndClaim the following error will occur:

Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported

If I put the setSigningKey as shown in stormpath example:

Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret())).parseClaimsJwt(jwtString).getBody();. 

The above code will not work for two reasons: 1. I don't have the library import javax.xml.bind.DatatypeConverter; 2. I don't know how to get the key.

But know that I don't need the key since this time I am trying to login and collect the user information's (like firstname, lastname, phone, etc), and the signature (token) so that the next time I send data to be stored to the server side I have the token to get access to the backend.

Can anyone please help me?

Upvotes: 1

Views: 8488

Answers (1)

pedrofb
pedrofb

Reputation: 39291

You have many questions. I try to answer some of them

io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before 2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´

You are using nbf (not before) attribute in JWT. Do not use it (it is optional) or sets a range of validity given that the clocks of the devices will not be synchronized

From RFC 7519

The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value. Use of this claim is OPTIONAL.

Signed JWS

Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported

Do you want to validate the signing key at client side or at server side? If you use the JWT for authentication replacing user & password, and you are sending token in each request, you can validate the signature at server side.

If you want to validate the key on the app, do not use a symmetric key, because it could be a big vulnerability if it fell into the wrong hands. See. You can use and asymmetric key pair. Sign the JWT in server with the private key and validate on device with public key.

  1. I don't have the library import javax.xml.bind.DatatypeConverter
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
byte[] data = Base64.decode(base64, Base64.DEFAULT); 
  1. I don't know how to get the key.

Your key probably was generated on server side in this way

 Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);
 byte data[] = key.getEncoded();

Make available the key data[] to client in the way you prefer. Using assymetric keys, you only need to make available the public key.

 KeyPair keyPair = RsaProvider.generateKeyPair();
 byte data[] = keyPair.getPublic().getEncoded();

Upvotes: 1

Related Questions