Search code examples
javascriptnode.jsauthenticationjwtexpress-jwt

JWT sub claim gets ignored during verification


Well, this question maybe naive as I am implementing JWT in my node app for the first time and I have too many questions about it.

Firstly I am not clear about the iss, sub and aud claims. From my basic understanding I understand that iss is the issuer of the token, so I can assume it to be the company name of the app. sub is the subject of the token or in easy terms probably the user identity/username. And lastly the aud is for audience or in easy terms the api server url/resource server. Please let me know if I got this terms correctly.

Now, with my limited knowledge I have set up the basic JWT signing and verification. A small snippet is as follows:

JWT.js

module.exports = {
sign: (payload, options) => {
    let signOptions = {
        issuer: config.JWT_ISSUER,
        subject: options.subject,
        audience: config.JWT_AUDIENCE,
        expiresIn: "24h",
    };

    return jwt.sign(payload, config.JWT_SECRET, signOptions);
},
verify: (token, options) => {
    let verifyOptions = {
        issuer: config.JWT_ISSUER,
        subject: options.subject,
        audience: config.JWT_AUDIENCE,
        expiresIn: "24h",
    };

    try {
        return jwt.verify(token, config.JWT_SECRET, verifyOptions);
    }
    catch (err){
        return false;
    }
},

Now token is issued as follows:

// Issue JWT token
let userData = {
    user_name: user.userName,
    client_id: user.clientId
};
const token = jwt.sign({ userData }, { subject: user.userName });

Verfication is as follows:

// Verify the token
const authData = jwt.verify(token, { subject: req.body.subject });  

MAIN ISSUE

When I send a request to an api endpoint for verification and if I send it without a subject field in the body(the token is issued with a sub field), the token is verified successfully. But if I send the subject field in the body with an correct/incorrect value, it gets success/forbidden respectively.

  • Why does it happen so?
  • Why does'nt the token get forbidden when no sub field is passed in the request?
  • Do I need to manually verify this?

Solution

  • According to JWT standard,

    4.1.2. "sub" (Subject) Claim

    The "sub" (subject) claim identifies the principal that is the subject of the JWT. The claims in a JWT are normally statements about the subject. The subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique. The processing of this claim is generally application specific. The "sub" value is a case-sensitive string containing a StringOrURI value. Use of this claim is OPTIONAL.

    Thus, when you don't have it, it passes but an incorrect value leads to failure. The jwt package follows the standard.

    Now if you plan to make it mandatory, you will have to make it custom but be warned that you may not be then able to use 3rd party authentication (if that's your use case) who do not consider it mandatory. (I don't know if in real life that really is the case)