Open CoranH opened 2 years ago
I am seeing a similar error when trying to validate an KMS-signed JWT. The error message I'm getting back however is:
"ES256" signatures must be "64" bytes, saw "71"
This is the code I'm using to construct my JWT:
const header64 = base64url.encode(JSON.stringify(header));
const payload64 = base64url.encode(JSON.stringify(payload));
const message = Buffer.from(`${header64}.${payload64}`);
const command = new SignCommand({
KeyId: 'mrk-1234567890',
Message: message,
SigningAlgorithm: SigningAlgorithmSpec.ECDSA_SHA_256
});
const client = new KMSClient({});
const response = await client.send(command);
const signature64 = base64url.encode(Buffer.from(response.Signature), 'base64');
const jwt = `${header64}.${payload64}.${signature64}`;
Then if I try and verify that token using jsonwebtoken
and the public PEM file I get the above error.
@CoranH I'm not sure if this helps but I was able to fix my issue with my KMS-generated signature by using the ecdsa-sig-formatter package when creating my JWT. If you take the above code and modify it slightly to convert the AWS DER-encoded signature into a JOSE-compatible format.
const header64 = base64url.encode(JSON.stringify(header));
const payload64 = base64url.encode(JSON.stringify(payload));
const message = Buffer.from(`${header64}.${payload64}`);
const command = new SignCommand({
KeyId: 'mrk-1234567890',
Message: message,
SigningAlgorithm: SigningAlgorithmSpec.ECDSA_SHA_256
});
const client = new KMSClient({});
const response = await client.send(command);
const signature64 = base64url.encode(Buffer.from(response.Signature), 'base64');
const signatureJose = derToJose(signature64, 'ES256');
const jwt = `${header64}.${payload64}.${signatureJose}`;
I think the issue I was experiencing was ultimately because AWS was returning a URL encoded JWT (which apparently is non-standard) and jsonwebtoken strictly follows the standard and chokes on this. AWS support have said they will fix this, but there's no ETA.
@CoranH I also faced the exact same issue. While getting the token from AWS it is sending with "==" in all header, payload and signature which jwt.verify() fail to verify and return invalid token. While Python library is returning the correct payload. Did you get any resolution for this ?
Description
I have some JWTs obtained from AWS/Cognito with the Elastic Load Balancer performing authentication for me. I also have the associated public key from the documented endpoints for the Cognito userpool. However the jsonwebtoken library says the signature is invalid (JsonWebTokenError: invalid signature), except when I use the same input (same JWT and public key in PEM format) in PyJWT Python code, this decodes/verifies without issue. There is no information to point to why jsonwebtoken is unable to verify the JWT/PEM when another library (PyJWT) can. I have tried ignoring any expiration checking in case this is the cause of the "invalid signature", such as ignoreExpiration, clockTolerance, and maxAge, without success. The only discrepancy I can see is the jsonwebtoken library must remove the base64 padding (=) from the JWT first. Is there any known reason why jsonwebtoken would be unable to verify a signature which can be verified with another library? Perhaps some assumptions about the format/layout/syntax of the inputs which AWS/Cognito is not respecting.
Reproduction
Python code:
TypeScript code:
Environment