I have been around and around on the Internet trying various solutions and all of them have broken in various ways. I am writing in hopes that either someone on StackOverflow familiar with a similar workflow or someone from the Microsoft.IdentityModel.JsonWebTokens team can step in to help.
What I am trying to do is to decrypt an OAuth Access token encrypted by a JSONWebKey (JWK) so that I can read the claims data. Right now I am stuck on the decryption step. I am using C# on OS X with Visual Studio for Mac. Among the approaches I have tried are using the older JWT library and trying to create all sorts of RSA objects via round-about ways. However, what I would LIKE to do is something like the following:
using System;
using System.Linq;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
using Microsoft.AspNetCore.WebUtilities;
namespace jwtdecoder {
class Program {
static void Main(string[] args) {
/* Exact string of a token retrieved from the IDP/OAuth server. */
String token = "BASE64EncodedTokenGoesHere";
/* Trust me that we have a valid JWKS string here that has all the properties mentioned in the RSA params below
* and uses RSA OAEP 256 */
String jwks = "JWKSSTRINGGOESHERE";
/* Get our basic objects from the Strings above. */
JsonWebKeySet exampleJWKS = new JsonWebKeySet(jwks);
JsonWebKey exampleJWK = exampleJWKS.Keys.First();
JsonWebToken exampleJWT = new JsonWebToken(token);
/* Create RSA from Elements in JWK */
RSAParameters rsap = new RSAParameters{
Modulus = WebEncoders.Base64UrlDecode(exampleJWK.N),
Exponent = WebEncoders.Base64UrlDecode(exampleJWK.E),
D = WebEncoders.Base64UrlDecode(exampleJWK.D),
P = WebEncoders.Base64UrlDecode(exampleJWK.P),
Q = WebEncoders.Base64UrlDecode(exampleJWK.Q),
DP = WebEncoders.Base64UrlDecode(exampleJWK.DP),
DQ = WebEncoders.Base64UrlDecode(exampleJWK.DQ),
InverseQ = WebEncoders.Base64UrlDecode(exampleJWK.QI)
};
RSA rsa = RSA.Create();
rsa.ImportParameters(rsap);
RsaSecurityKey rsakey = new RsaSecurityKey(rsa);
/* Create a JSON Token Handler and Try Decrypting the Token */
JsonWebTokenHandler exampleHandler = new JsonWebTokenHandler();
TokenValidationParameters validationParameters = new TokenValidationParameters {
ValidateAudience = false,
ValidateIssuer = false,
RequireSignedTokens = false, /* Have also tried with this set to True */
TokenDecryptionKey = rsakey
};
String clearToken = exampleHandler.DecryptToken(exampleJWT, validationParameters);
/* The line above results in an error
* "IDX10609: Decryption failed. No Keys tried: token: 'System.String'."
*/
}
}
}
My IDP/OAuth Server is Micro Focus / NetIQ Access Manager using a JSON Web Key that I generated outside of it (and imported as a new Resource Server). However, I do not think that detail has much to do with the problem. When I create the JSONWebKey and JSONWebToken objects in C# I see the properties I expect to see and I get no exceptions. I can also decode (not decrypt) the token string with non-C# tools and see the header properties etc. that I expect.
Specifically, for the exampleJWT object in the code above the header is as follows:
{{ "alg": "RSA-OAEP-256", "enc": "A128CBC-HS256", "typ": "JWT", "cty": "JWT", "zip": "DEF", "kid": "5BbVY7F77gz9LWE4tUjXwNFt9qhINvWBR7Pkm1ZJlEA" }}
The exampleJWT object also has the following properties with values that look either encoded or encrypted: EncodedHeader, EncodedToken, EncryptedKey, CipherText, and AuthenticationTag There is no plaintext claims data or date data in the object at present.
My thinking is that I have not set up my code correctly for the Decrypt method to apply the JSONWebToken RSA information properly so that the token can be turned into clear text. However, as I say, I tried a bunch of different methods using other C# classes and approaches and none of them has been any more successful. I would love to know what I am fundamentally misunderstanding about this process. Thank you in advance.
To answer Michal's question below: Four dots (when base-64 encoded), so five sections.