javascriptjwtwinston

More accurate JWT token regex in JavaScript


I wanted to encrypt JWT tokens in logs and to do that, I've configured winston.js to centralize this feature. For instance, if someone wants to log a JS object or string, they just log it and if that string contains a token, it will automatically be encrypted.

I am using the regex below:

const JWT_TOKEN_REGEX = /[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*/g;

However, when I get the query string from request

my-panel?issueId=10060&type=left&xdm_e=https%3A%2F%2Ftanriverdi.furkan.net&xdm_c=channel-abc.plugin.xyz__abc-issue-content-panel-3543924933333691153&cp=&xdm_deprecated_addon_key_do_not_use=abc.plugin.xyz&lic=none&cv=1001.0.0-SNAPSHOT&jwt=eyJ0eXAiOiJKV1QiOiJIUzI1NiJ9.eyJzdWIiOiI2MjQ2OWI5MDRmZTAxZDAwNmJhNzVjNDMiLCJxc2giOiI3YWE1YWVjN2NhOTM4Yzc0NmRmMmJkNmY2MTJiOTU4MmY5MzkxNWI1MzQzYmM1YTk4IiwiaXNzIjoiMzJmMTg4OTMtNzhkNi0zZmJiLWI3NzgtNmQ2OWU3YTU3NWM5IiwiY29udGV4dCI6e30sImV4cCI6MTY2NjYwMjkxMywiaWF0IjoxNjY2NjAyMDEzfQ.CpI-BZfqOM7Rmidv8e2L8G-rENSELnfEP96w

, all strings with two dots get encrypted.

enter image description here

How can I parse only JWT token values? They don't always appear in query strings, and it does not have to start with jwt=  or something like that.

I tried to customize the regex like

every capturing group must contain at least 1 uppercase letter, 1 lowercase letter and 1 digit.

I could not manage to successfully filter JWTs.

Any suggestions are much appreciated!


Solution

  • You can add to your rule that the first and second segment have to start with eyJ, because header and payload of a JWT are Base64URL encoded JSONs and start with {", which is eyJin Base64URL. In the following example I also removed the ? after the last ., so that it must have always 3 segments separated by .. The = is also not needed, because a JWT uses Base64URL encoding without padding:

    const isJWT = (jwt) => {
      return String(jwt)
        .match(/eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/]*/g);
    };
    
    
    const jwt = "eyJ0eXAiOiJKV1QiOiJIUzI1NiJ9.eyJzdWIiOiI2MjQ2OWI5MDRmZTAxZDAwNmJhNzVjNDMiLCJxc2giOiI3YWE1YWVjN2NhOTM4Yzc0NmRmMmJkNmY2MTJiOTU4MmY5MzkxNWI1MzQzYmM1YTk4IiwiaXNzIjoiMzJmMTg4OTMtNzhkNi0zZmJiLWI3NzgtNmQ2OWU3YTU3NWM5IiwiY29udGV4dCI6e30sImV4cCI6MTY2NjYwMjkxMywiaWF0IjoxNjY2NjAyMDEzfQ.CpI-BZfqOM7Rmidv8e2L8G-rENSELnfEP96w"
    
    if (isJWT(jwt)) console.log("it's a JWT!");