Realization of JWT Decryption of IdentityServer4 Client Based on. net4.0
- 2021-10-27 06:59:53
- OfStack
Scenario: The company project is based on. net4.0. web client needs to decrypt id_token by itself to realize single sign-on. For jwt decryption,. net provides IdentityModel class library, but this class library is not available in 4.0, so it implements the decryption method by itself.
Class library used: link address
Stick the code directly below, just call the DecodeJWT method directly, the parameter is id_token, and key defaults to the empty string "".
Code
public static IDictionary<string, object> DecodeJWT(string jwttoken,string key)
{
// From /.well-known/openid-configuration Path acquisition jwks_uri
var webClient = new WebClient();
var endpoint = "http://localhost:5000/.well-known/openid-configuration";
var json = webClient.DownloadString(endpoint);
JObject metadata = JsonConvert.DeserializeObject<JObject>(json);
var jwksUri = metadata["jwks_uri"].ToString();
// From jwks_uri Get keys
json = webClient.DownloadString(jwksUri);
var keys = JsonConvert.DeserializeObject<CustomJWKs>(json);
// From jwt Get header kid, And from keys A match was found in kid Adj. key
string[] tokenParts = jwttoken.Split('.');
byte[] bytes = FromBase64Url(tokenParts[0]);
string head= Encoding.UTF8.GetString(bytes);
string kid = JsonConvert.DeserializeObject<JObject>(head)["kid"].ToString();
var defaultkey=keys.keys.Where(t => t.kid == kid).FirstOrDefault();
if(defaultkey==null)
{
throw new Exception(" No matching was found kid");
}
//jwt Decryption
return RS256Decode(jwttoken, key, defaultkey.e, defaultkey.n);
}
public static IDictionary<string, object> RS256Decode(string token, string secret, string exponent,string modulus)
{
try
{
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
RSAlgorithmFactory rS256Algorithm = new RSAlgorithmFactory(() =>
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(
new RSAParameters()
{
Modulus = FromBase64Url(modulus),
Exponent = FromBase64Url(exponent)
});
byte[] rsaBytes = rsa.ExportCspBlob(true);
X509Certificate2 cert = new X509Certificate2(rsaBytes);
return cert;
});
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, rS256Algorithm);
var json = decoder.DecodeToObject(token, secret, verify: false);
return json;
}
catch (TokenExpiredException)
{
throw new Exception("token Expired ");
//Console.WriteLine("Token has expired");
//return null;
}
catch (SignatureVerificationException)
{
throw new Exception("token Validation failed ");
//Console.WriteLine("Token has invalid signature");
//return null;
}
}
public static byte[] FromBase64Url(string base64Url)
{
string padded = base64Url.Length % 4 == 0
? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
string base64 = padded.Replace("_", "/")
.Replace("-", "+");
return Convert.FromBase64String(base64);
}