I have a jhipster spring boot application which accepts a token generated by a third party which has been encrypted with our public key. I have a JWTFilter which decrypts the token using our private key and creates an authentication object which is stored in the security context. Once execution reaches the controller, I intend to pull the username and password from the security context so I can make API calls back to the third party application.
This is working to some degree in our integration environment where the third-party has a link to a running instance of our application. To test locally, I am hitting the link in the integration environment, and copying the token. Then I make a request from Postman to an instance of our application I'm running locally with the token added in the headers, the same as our js client would.
I am using "com.nimbusds:nimbus-jose-jwt:4.23" for decryption, and I am getting a 'MAC check failed' error. I can change the value of macCheckPassed to true in the debugger, and the decryption will complete, allowing me to see the claims and load them into the security context. However, some other filter is catching my hack, and the request gets rejected with an authorization error.
public static byte[] decryptAuthenticated(final SecretKey secretKey,
final byte[] iv,
final byte[] cipherText,
final byte[] aad,
final byte[] authTag,
final Provider ceProvider,
final Provider macProvider)
throws JOSEException {
// Extract MAC + AES/CBC keys from input secret key
CompositeKey compositeKey = new CompositeKey(secretKey);
// AAD length to 8 byte array
byte[] al = AAD.computeLength(aad);
// Check MAC
int hmacInputLength = aad.length + iv.length + cipherText.length + al.length;
byte[] hmacInput = ByteBuffer.allocate(hmacInputLength).
put(aad).
put(iv).
put(cipherText).
put(al).
array();
byte[] hmac = HMAC.compute(compositeKey.getMACKey(), hmacInput, macProvider);
byte[] expectedAuthTag = Arrays.copyOf(hmac, compositeKey.getTruncatedMACByteLength());
boolean macCheckPassed = true;
if (! ConstantTimeUtils.areEqual(expectedAuthTag, authTag)) {
// Thwart timing attacks by delaying exception until after decryption
macCheckPassed = false;
}
byte[] plainText = decrypt(compositeKey.getAESKey(), iv, cipherText, ceProvider);
if (! macCheckPassed) {
throw new JOSEException("MAC check failed");
}
return plainText;
}
What is this MAC check? I thought it had to do with the origin of the token. Something along the lines of the token being encrypted with the MAC id of the source system, which throws an error when it doesn't synch up with my current host.
What other filter would be rejecting the request if the decryption passed? Is there some other flag I'm supposed to be setting so the framework will honor the request?