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);
}

Related articles: