I'm using the following code to issue my JWEs:
var signCreds = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Jwt:SigningKey"])), SecurityAlgorithms.HmacSha256);
var encryptionCreds = new EncryptingCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Jwt:Encryptionkey"])), SecurityAlgorithms.Aes128KW, SecurityAlgorithms.Aes128CbcHmacSha256);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.CreateJwtSecurityToken(
Configuration["Jwt:Issuer"],
Configuration["Jwt:Audience"],
new ClaimsIdentity(claims),
DateTime.UtcNow,
expiresIn,
DateTime.UtcNow,
signCreds,
encryptionCreds);
But it doesn't specify "cty" header of the token - just only alg, enc and typ. If I understand correctly, the header must be set for encrypted JWT so I have an issue while parsing the token in golang because of the headers absence.
I also tried the following ways to issue JWE:
var signCreds = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Jwt:SigningKey"])), SecurityAlgorithms.HmacSha256);
var encryptionCreds = new EncryptingCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Jwt:Encryptionkey"])), SecurityAlgorithms.Aes128KW, SecurityAlgorithms.Aes128CbcHmacSha256);
var handler = new JwtSecurityTokenHandler();
var tokenDescriptor1 = new SecurityTokenDescriptor
{
Audience = "you",
Issuer = "me",
Subject = new ClaimsIdentity(claims),
EncryptingCredentials = encryptionCreds
};
var tokenDescriptor2 = new SecurityTokenDescriptor
{
Audience = "you",
Issuer = "me",
Subject = new ClaimsIdentity(claims),
EncryptingCredentials = encryptionCreds,
SigningCredentials = signCreds
};
var tokenDescriptor3 = new SecurityTokenDescriptor
{
Audience = "you",
Issuer = "me",
Subject = new ClaimsIdentity(claims),
EncryptingCredentials = encryptionCreds,
SigningCredentials = signCreds,
AdditionalHeaderClaims = new Dictionary<string, object> { { "cty", "JWT" } }
};
var enc = handler.CreateEncodedJwt(tokenDescriptor1);
var encSigned = handler.CreateEncodedJwt(tokenDescriptor2);
var encSignedWithCty = handler.CreateEncodedJwt(tokenDescriptor3);
But have the same result:
I scanned the library but have not found the code that set the Cty header for token.
Maybe anyone knows what I missed or what is the problem?
Thanks!
It seems to be a library issue
Related
I'm trying to load a private key to sign a JWT token. I got following code and failed with exceptions:
string key =#"-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCTLOQaZ3D0ayC1BSW4LCs3gYmu
eYiWDGRT491PJt/4
-----END PRIVATE KEY-----";
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha512);
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha512);
var header = new JwtHeader(signingCredentials);
var t = DateTime.UtcNow - new DateTime(1970, 1, 1);
int iat = (int)t.TotalSeconds;
var payload = new JwtPayload
{
{ "iss", "1234-5678-9012-1221-11111"},
{ "iat", iat },
{ "exp", iat + 900},
{ "sub", "aaaaaaaaaaa" }
};
var secToken = new JwtSecurityToken(header, payload);
var tokenString = new JwtSecurityTokenHandler().WriteToken(secToken);
===============Answer===============================
Just for anyone facing the same problem, here is the solution. You need read the post down the bottom to get it work:
http://www.donaldsbaconbytes.com/2016/08/create-jwt-with-a-private-rsa-key/
Your problem is with below line
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha512);
you are trying to use symmetric key with asymmetric algorithm (RSA algorithm).
You can look for other symmetric algorithm to generate signingCredentials something like below
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature);
I'm generating and validating a JWT with the following code.
static string GenerateToken()
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"Test.pfx", "123");
var rsa = certificate.GetRSAPrivateKey();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(),
Issuer = "Self",
IssuedAt = DateTime.Now,
Audience = "Others",
Expires = DateTime.MaxValue,
SigningCredentials = new SigningCredentials(
new RsaSecurityKey(rsa),
SecurityAlgorithms.RsaSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
static bool ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"Test.cer");
var rsa = certificate.GetRSAPublicKey();
var validationParameters = new TokenValidationParameters
{
ValidAudience = "Others",
ValidIssuer = "Self",
IssuerSigningKey = new RsaSecurityKey(rsa)
};
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
if (principal == null)
return false;
if (securityToken == null)
return false;
return true;
}
I have this code in a library which targets .net standard 2.0 and net46.
When I use the library in an .net core app 2.0 project everything is working as expected. I use the following nuget packages.
System.IdentityModel.Tokens.Jwt => 5.1.4
System.Security.Cryptography.Csp => 4.3.0
But when I build the same code with .net46 I get the following exception when trying to generate a token.
var token = tokenHandler.CreateToken(tokenDescriptor);
System.NotSupportedException: 'NotSupported_Method'
The the following exception is throw when I try to validate a token.
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: 'IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.RsaSecurityKey , KeyId:
'.
Instead of using an RsaSecurityKey I directly use an X509SecurityKey now. This works for both netstandard2.0 and net46.
static string GenerateToken()
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"Test.pfx", "123");
var securityKey = new X509SecurityKey(certificate);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(),
Issuer = "Self",
IssuedAt = DateTime.Now,
Audience = "Others",
Expires = DateTime.MaxValue,
SigningCredentials = new SigningCredentials(
securityKey,
SecurityAlgorithms.RsaSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
static bool ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"Test.cer");
var securityKey = new X509SecurityKey(certificate);
var validationParameters = new TokenValidationParameters
{
ValidAudience = "Others",
ValidIssuer = "Self",
IssuerSigningKey = securityKey
};
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
if (principal == null)
return false;
if (securityToken == null)
return false;
return true;
}
Also I only need the System.IdentityModel.Tokens.Jwt nuget package and can remove the System.Security.Cryptography.Csp package.
Thank you NtFrex ..
I just put minor changes to NtFrex's answer to make it work for me. And this works with .net 4.5.1 as well & I thought it might help someone. Here is the final code but first create a certificate. I've used openssl to create one with RSA512.
Create Token :
private string GenerateToken1()
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"C:\Users\myname\my-cert.pfx", "mypassword");
var securityKey = new X509SecurityKey(certificate);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(),
Issuer = "Self",
IssuedAt = DateTime.Now,
Audience = "Others",
Expires = DateTime.Now.AddMinutes(30),
SigningCredentials = new SigningCredentials(
securityKey,
SecurityAlgorithms.RsaSha512Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
Validate Token :
private bool ValidateToken1(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var certificate = new X509Certificate2(#"C:\Users\myname\my-cert.pfx", "mypassword");
var securityKey = new X509SecurityKey(certificate);
var validationParameters = new TokenValidationParameters
{
ValidAudience = "Others",
ValidIssuer = "Self",
IssuerSigningKey = securityKey
};
SecurityToken securityToken;
var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
if (principal == null)
return false;
if (securityToken == null)
return false;
return true;
}
i want to generate jwt token which should be verified by google firebase. below is my code to generate jwt token, it works fine until i change algorithm to "RsaSha256Signature" it then gives me error
"Exception: 'System.InvalidOperationException: Crypto algorithm 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' not supported in this context.
"
If i dont change it and use it as "HmacSha256Signature" it works fine
var plainTextSecurityKey = "-----BEGIN PRIVATE KEY-----;
var signingKey = new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
var signingCredentials = new SigningCredentials(signingKey,
SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);
var claimsIdentity = new ClaimsIdentity(new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, email),
new Claim(ClaimTypes.Role, role),
}, "Custom");
var securityTokenDescriptor = new SecurityTokenDescriptor()
{
AppliesToAddress = "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
TokenIssuerName = "serviceemail",
Subject = claimsIdentity,
SigningCredentials = signingCredentials,
};
var tokenHandler = new JwtSecurityTokenHandler();
var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);
var tokenValidationParameters = new TokenValidationParameters()
{
ValidAudiences = new string[]
{
"https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
"https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
},
ValidIssuers = new string[]
{
"service email",
"service email"
},
IssuerSigningKey = signingKey
};
SecurityToken validatedToken;
tokenHandler.ValidateToken(signedAndEncodedToken,
tokenValidationParameters, out validatedToken);
return validatedToken.ToString();
Your signingKey is not a RSA key, so you can not use RsaSha256Signature. HmacSha256Signature works because you are creating a HMAC symmetric key with a fixed passphrase
var plainTextSecurityKey = "-----BEGIN PRIVATE KEY-----;
var signingKey = new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextSecurityKey));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);
I am not expert in C#, but probably you need something like this
// NOTE: Replace this with your actual RSA public/private keypair!
var provider = new RSACryptoServiceProvider(2048);
var parameters = provider.ExportParameters(true);
// Build the credentials used to sign the JWT
var signingKey = new RsaSecurityKey(parameters);
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256);
you will need a keystore which contains your private and public key. Note that HMAC is a symmetric algorithm and the key to sign and verify is the same, but RSA needs a keypair
I've been trying to create and sign a JwtSecurityToken using a simple key. And after a lot of research it seems that all the examples I find use the InMemorySymmetricSecurityKey class but unfortunately this class doesn't seem to exist in the newest versions of the System.IdentityModel libraries.
These are the dependencies I'm using:
"System.IdentityModel.Tokens": "5.0.0-rc1-211161024",
"System.IdentityModel.Tokens.Jwt": "5.0.0-rc1-211161024"
I also tried using it's base class SymmetricSecurityKey but then I get the following exception when trying to create the token:
"Value cannot be null.\r\nParameter name: IDX10000: The parameter 'signatureProvider' cannot be a 'null' or an empty object."
This is the code that throws the exception:
public static string CreateTokenHMAC()
{
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String("test"));
var key = new SymmetricSecurityKey(hmac.Key);
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
JwtSecurityToken token = _tokenHandler.CreateJwtSecurityToken(new SecurityTokenDescriptor()
{
Audience = AUDIENCE,
Issuer = ISSUER,
Expires = DateTime.UtcNow.AddHours(6),
NotBefore = DateTime.Now,
Claims = new List<Claim>()
{
new Claim(ClaimTypes.Email, "johndoe#example.com")
},
SigningCredentials = signingCredentials
});
return _tokenHandler.WriteToken(token);
}
It's the first time I'm using JwtSecurityToken so my guess is that I'm probably missing a step somewhere
I was unable to get it to work using the RsaSecurityKey example provided in the accepted answer, but this did work for me (using System.IdentityModel.Tokens.Jwt v5.1.3).
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("test"));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
var securityTokenDescriptor = new SecurityTokenDescriptor()
{
Subject = new ClaimsIdentity(new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, "johndoe#example.com"),
new Claim(ClaimTypes.Role, "Administrator"),
}, "Custom"),
NotBefore = DateTime.Now,
SigningCredentials = signingCredentials,
Issuer = "self",
IssuedAt = DateTime.Now,
Expires = DateTime.Now.AddHours(3),
Audience = "http://my.website.com"
};
var tokenHandler = new JwtSecurityTokenHandler();
var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);
and to verify
var validationParameters = new TokenValidationParameters()
{
ValidateAudience = true,
ValidAudience = "http://my.website.com",
ValidateIssuer = true,
ValidIssuer = "self",
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
try
{
SecurityToken mytoken = new JwtSecurityToken();
var myTokenHandler = new JwtSecurityTokenHandler();
var myPrincipal = myTokenHandler.ValidateToken(signedAndEncodedToken, validationParameters, out mytoken);
} catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Authentication failed");
}
This should work (note this requires RC2 packages > 304180813)
var handler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(
new Claim[] { new Claim(ClaimTypes.NameIdentifier, "bob") }),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(new byte[256]),
SecurityAlgorithms.HmacSha256)
};
var jwt = handler.CreateEncodedJwt(tokenDescriptor);
I managed to reach the exact same exception. I worked around the problem by generating the key another way:
RSAParameters keyParams;
using (var rsa = new RSACryptoServiceProvider(2048))
{
try
{
keyParams = rsa.ExportParameters(true);
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
RsaSecurityKey key = new RsaSecurityKey(keyParams);
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
Here is a great post about token-based authentication on ASP.NET 5 RC1 by Mark Hughes
I need to secure my web-token with signing and encryption. I wrote the next lines of code:
var tokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, owner.Name),
new Claim(ClaimTypes.Role, owner.RoleClaimType),
new Claim("custom claim type", "custom content")
}),
TokenIssuerName = "self",
AppliesToAddress = "http://www.example.com",
Lifetime = new Lifetime(now, now.AddSeconds(60 * 3)),
EncryptingCredentials = new X509EncryptingCredentials(new X509Certificate2(cert)),
SigningCredentials = new X509SigningCredentials(cert1)
};
var token = (JwtSecurityToken)tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
So, I am using some certificates, generated with makecert.exe. Then I read token string with another JwtSecurityTokenHandler:
var tokenHandlerDecr = new JwtSecurityTokenHandler();
var tok = tokenHandlerDecr.ReadToken(tokenString);
And token content is not encrypted (I can see json in tok variable under debugger). What am I doing wrong? How to encrypt token data?
I know this an old post, but I am adding my answer in case if someone is still searching for the answer.
This issue is addressed in Microsoft.IdentityModel.Tokens version 5.1.3.
There is an overloaded method available in the CreateJwtSecurityToken function which accepts the encrypting credentials to encrypt the token.
If the receiver does not validate the signature and tries to read JWT as is then the claims are empty. Following is the code snippet:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
const string sec = "ProEMLh5e_qnzdNUQrqdHPgp";
const string sec1 = "ProEMLh5e_qnzdNU";
var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec));
var securityKey1 = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec1));
var signingCredentials = new SigningCredentials(
securityKey,
SecurityAlgorithms.HmacSha512);
List<Claim> claims = new List<Claim>()
{
new Claim("sub", "test"),
};
var ep = new EncryptingCredentials(
securityKey1,
SecurityAlgorithms.Aes128KW,
SecurityAlgorithms.Aes128CbcHmacSha256);
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.CreateJwtSecurityToken(
"issuer",
"Audience",
new ClaimsIdentity(claims),
DateTime.Now,
DateTime.Now.AddHours(1),
DateTime.Now,
signingCredentials,
ep);
string tokenString = handler.WriteToken(jwtSecurityToken);
// Id someone tries to view the JWT without validating/decrypting the token,
// then no claims are retrieved and the token is safe guarded.
var jwt = new JwtSecurityToken(tokenString);
And here is the code to validate/decrypt the token:
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
const string sec = "ProEMLh5e_qnzdNUQrqdHPgp";
const string sec1 = "ProEMLh5e_qnzdNU";
var securityKey = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec));
var securityKey1 = new SymmetricSecurityKey(Encoding.Default.GetBytes(sec1));
// This is the input JWT which we want to validate.
string tokenString = string.Empty;
// If we retrieve the token without decrypting the claims, we won't get any claims
// DO not use this jwt variable
var jwt = new JwtSecurityToken(tokenString);
// Verification
var tokenValidationParameters = new TokenValidationParameters()
{
ValidAudiences = new string[]
{
"536481524875-glk7nibpj1q9c4184d4n3gittrt8q3mn.apps.googleusercontent.com"
},
ValidIssuers = new string[]
{
"https://accounts.google.com"
},
IssuerSigningKey = securityKey,
// This is the decryption key
TokenDecryptionKey = securityKey1
};
SecurityToken validatedToken;
var handler = new JwtSecurityTokenHandler();
handler.ValidateToken(tokenString, tokenValidationParameters, out validatedToken);
Try the following example
Updated Jul-2019: .NET Core, Asp.net Core
1.Create JWT
private string CreateJwt(string sub, string jti, string issuer, string audience)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, sub),
new Claim(JwtRegisteredClaimNames.Jti, jti),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var encryptingCredentials = new EncryptingCredentials(key, JwtConstants.DirectKeyUseAlg, SecurityAlgorithms.Aes256CbcHmacSha512);
var jwtSecurityToken = new JwtSecurityTokenHandler().CreateJwtSecurityToken(
issuer,
audience,
new ClaimsIdentity(claims),
null,
expires: DateTime.UtcNow.AddMinutes(5),
null,
signingCredentials: creds,
encryptingCredentials: encryptingCredentials
);
var encryptedJWT = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
return encryptedJWT;
}
2.Add to ConfigureServices(IServiceCollection services) in Startup.cs
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Issuer"),
ValidAudience = (string)Configuration.GetSection("JwtToken").GetValue(typeof(string), "Audience"),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecretKeySecretKeySecretKeySecretKeySecretKeySecretKeySecretKeyS")),
ClockSkew = TimeSpan.FromMinutes(0),
};
});
My understanding is that Microsoft's JWT implementation doesn't currently support encryption (only signing).
Hung Quach's answer worked just fine for .NET 5 on Blazor for me. Although I changed it a bit to for my style.
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name,userRequestDTO.Email)
};
var secret = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_APISettings.SecretKey));
var signingCredentials = new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
var encryptionCredentials = new EncryptingCredentials(secret, JwtConstants.DirectKeyUseAlg, SecurityAlgorithms.Aes256CbcHmacSha512);
var tokenOptions = new JwtSecurityTokenHandler().CreateJwtSecurityToken(new SecurityTokenDescriptor()
{
Audience= _APISettings.ValidAudience,
Issuer= _APISettings.ValidIssuer,
Subject= new ClaimsIdentity(claims),
Expires= DateTime.Now.AddMinutes(10),
EncryptingCredentials= encryptionCredentials,
SigningCredentials = signingCredentials
});
return new JwtSecurityTokenHandler().WriteToken(tokenOptions);
then I am reading the token as follows :
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
var secret = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_APISettings.SecretKey));
var signingCredentials = new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
tokenHandler.ValidateToken(tokenOTP,new TokenValidationParameters
{
ValidIssuer = _APISettings.ValidIssuer,
ValidAudience = _APISettings.ValidAudience,
ValidateIssuerSigningKey=true,
ValidateLifetime = true,
RequireExpirationTime = true,
ValidateIssuer = true,
ValidateAudience = true,
IssuerSigningKey= secret,
TokenDecryptionKey=secret,
ClockSkew = TimeSpan.Zero
},out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;