private async Task <bool> VerifySignatureAsync(string jws, string payload) { var jwsElements = jws.Split("."); var joseHeaderBase64 = jwsElements[0]; var signatureBase64 = jwsElements[2]; var signature = Base64Url.Decode(signatureBase64); var joseHeaderBytes = Base64Url.Decode(joseHeaderBase64); var joseHeaderString = Encoding.UTF8.GetString(joseHeaderBytes); var joseHeader = JsonConvert.DeserializeObject <JoseHeader>(joseHeaderString); if (!Uri.TryCreate(joseHeader.JsonWebKeySetUri, UriKind.Absolute, out var jwksUri) || jwksUri != _expectedJwksUri) { return(false); } using var httpClient = _httpClientFactory.CreateClient(); var jwksResponse = await httpClient.GetAsync(_expectedJwksUri); var jwksString = await jwksResponse.Content.ReadAsStringAsync(); var jwks = JsonConvert.DeserializeObject <JsonWebKeySet>(jwksString); var key = jwks.Keys.Single(s => s.KeyId == joseHeader.KeyId); var rsaPublicKey = new RSACryptoServiceProvider(); rsaPublicKey.ImportParameters( new RSAParameters { Modulus = Base64Url.Decode(key.Modulus), Exponent = Base64Url.Decode(key.Exponent) }); var payloadBase64 = Base64Url.Encode(Encoding.UTF8.GetBytes(payload)); var securedInput = $"{joseHeaderBase64}.{payloadBase64}"; var jwtSettings = new JwtSettings(); var jwsAlgorithmValue = jwtSettings.JwsAlgorithmFromHeader(joseHeader.Algorithm); var jwsAlgorithm = jwtSettings.Jws(jwsAlgorithmValue); return(jwsAlgorithm.Verify(signature, Encoding.UTF8.GetBytes(securedInput), rsaPublicKey)); }