decoding with nodejs encoded jwt token make with flutter(dart)

1,533

When you encode JWTs, in most libraries, a "iat" (issued_at, basically the timestamp at which the token was created) field will be automatically added. Which means that the same payload with the same secret and algorithm, no matter the library, will not be the same if you encode it twice. This may explain why you get different encoded values.

This is how it is supposed to work by design. The only way to check if the jwt is valid is not by comparing it with the jwt you issued, but by decoding it with your secret (that only you, the server, knows).

Also, besides the fact that the dart jwt does not validate, the payload of your dart jwt is not the same as the payload from the node jwt. You may also want to check out why this is the case, because it also explains why the token is different!

As far as I can see your decode function is right. You should try this to see what is specifically wrong with your token:

try {
  const decoded = jwt.verify(code2,secret);
}
catch(err) {
  console.log(err);
}

Additionally, the token from dart looks base64 encoded, so the following code may solve your issue: jwt.verify(Buffer.from(code2, 'base64'), secret).

Share:
1,533
ufk
Author by

ufk

Updated on December 08, 2022

Comments

  • ufk
    ufk over 1 year

    I want to be able to encode a JWT token in flutter (dart) and to be to decode it in nodejs in order to use it as a google function for firebase.

    the problem is that the encoded string in flutter produces an invalid token when I try to decode it with nodejs.

    in both cases I use HS256 encryption.

    this is my flutter code:

    import 'package:jaguar_jwt/jaguar_jwt.dart';
    
    final String emailTrackingJwtSecret = '<SECRET>';
    
    String generateEmailTrackingJwtToken(String uid, String scanId, String composeId) {
      final claimSet = new JwtClaim(
          payload: {<PAYLOAD_DATA>}
      );
      final String token = issueJwtHS256(claimSet, emailTrackingJwtSecret);
      print(token);
      return token;
    } 
    

    and this is my nodejs code to decode it:

    const jwt = require('jsonwebtoken');
    const secret='<SECRET>';
    
    const decoded = jwt.verify(code2,secret);
    

    when I try to encode the same data with same secret in flutter I get the following token:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDU5MjMwNTgsImlhdCI6MTU0NTgzNjY1OCwicGxkIjp7ImNvbXBvc2VJZCI6ImEyIiwic2NhbklkIjoiYTEiLCJ1aWQiOiJrZmlyIn19.INf2n8J3yA4KPlYToARNCJnDvDQWcobWs-abaPCn_FE=
    

    in nodejs when I encode the same data I get:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJrZmlyIiwic2NhbklkIjoiYTEiLCJjb21wb3NlSWQiOiJhMiIsImlhdCI6MTU0NTgzNzEwM30.DWfGOppzqnmGmfP3OFY81S_0l2qR1ATH0nqMG7vcWMw
    

    so the tokens are different.. and I read on https://github.com/auth0/node-jsonwebtoken and the default encryption is HS256 so what am I missing?

    thank you

  • ufk
    ufk over 5 years
    thanks.. the "iat" explains that changes.. the exception that I get is JsonWebTokenError: invalid token
  • frsechet
    frsechet over 5 years
    Everything looks alright. Make sure that code2 is not empty or does not have trailing spaces, same with secret...
  • ufk
    ufk over 5 years
    it must be something else.. maybe jsonwebtoken package doesn't use hs256 by default or something.. there key variable contain no spaces and it's not empty
  • frsechet
    frsechet over 5 years
    It does, but you can force it anyway as well (check the docs). Only other solution is secret is not the same during encode/decode (check for \n, whitespace...)
  • ufk
    ufk over 5 years
    no whitespaces or new lines.. confirmed again and again the secrets are the same.. it's a simple code that I try to run in flutter app and on nodejs.. it's not a mistake from my side.. i think something is being encoded differently. whenever I encode with flutter it somehow ends with '='. with nodejs it doesn't
  • ufk
    ufk over 5 years
    ahh removing '=' solves the problem.. but why does it adds the '=' in the first place ?
  • frsechet
    frsechet over 5 years
    Ah. In that case I would guess that there is base64 involved somewhere. Can you try in nodejs jwt.verify(code2, Buffer.from(secret, 'base64'))?
  • ufk
    ufk over 5 years
  • ufk
    ufk over 5 years
    so fluter does base64urlencode on the resulted token, because of that I installed base64url npm package and used base64url.fromBase64() on the token to get back a proper string to be used with jwt.verify()