Swapping SymmetricSecurityKey for AsymmetricSecurityKey for JWT - c#

A penetration test has recommended that we change our JWT implementation to use asymmetric signing instead of symmetric signing, which is working well.
The current (perfectly working) code to Create the symmetric token is below: (inspiration originally taken from How to encrypt JWT security token?)
private string CreateToken(string Username)
{
//Set issued at date
DateTime issuedAt = DateTime.UtcNow;
//set the time when it expires
DateTime expires = DateTime.UtcNow.AddHours(1);
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
//create a identity and add claims to the user which we want to log in
ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, Username)
});
DateTime now = DateTime.UtcNow;
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
//create the jwt
JwtSecurityToken token = tokenHandler.CreateJwtSecurityToken(issuer: "issuer",
audience: "audience",
subject: claimsIdentity,
notBefore: issuedAt,
expires: expires,
signingCredentials: signingCredentials);
return tokenHandler.WriteToken(token);
}
}
The code to check the request of any API calls looks similar to the below:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpStatusCode StatusCode;
string token;
//determine whether a jwt exists or not
if (!TryRetrieveToken(request, out token))
{
StatusCode = HttpStatusCode.Unauthorized;
//allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
return base.SendAsync(request, cancellationToken);
}
try
{
DateTime now = DateTime.UtcNow;
SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
SecurityToken securityToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
TokenValidationParameters validationParameters = new TokenValidationParameters()
{
ValidAudience = "audience",
ValidIssuer = "issuer",
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
LifetimeValidator = this.LifetimeValidator,
IssuerSigningKey = SecurityKey
};
//extract and assign the user of the jwt
Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);
return base.SendAsync(request, cancellationToken);
}
catch (SecurityTokenValidationException e)
{
StatusCode = HttpStatusCode.Forbidden;
}
catch (Exception ex)
{
StatusCode = HttpStatusCode.Forbidden;
}
return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(StatusCode) { });
}
I've tried quite a few examples online and read quite a few posts, but haven't gotten anything working as yet, each with a whole host of different issues. Probably the closed I've got is following some of the examples at: RS256 vs HS256: What's the difference?
One example that seemed to work in creating the code is below, but this wouldn't have worked when comparing the token with incoming API calls.
RSA _rsaa;
_rsaa = new RSACryptoServiceProvider(2048);
var r = _rsaa.ExportParameters(true);
SigningCredentials signingCredentials3a = new SigningCredentials(new RsaSecurityKey(_rsaa), SecurityAlgorithms.RsaSha256Signature);
Finally the option below felt right, but was getting a 'Bad Version of provider.' error due to the encryption key contents held in the string.
byte[] Key256Bytes = Encoding.ASCII.GetBytes(Key256);
rsa.ImportCspBlob(Key256Bytes);
SigningCredentials signingCredentials5 = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256Signature);
I'm having difficulty getting the various options working.

Found the solution, to convert the above into Assymmetric encryption, swap:
SymmetricSecurityKey securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
SigningCredentials signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
with
var rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(Convert.FromBase64String(SecurityConstants.ConstAsyncSecurityEncryptionKey));
SigningCredentials signingCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha512Signature);
The encryption key was generated by using the below.
var rsa = new RSACryptoServiceProvider(2048);
var key = Convert.ToBase64String(rsa.ExportCspBlob(true));
Then when checking the incoming JWT:
SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(SecurityConstants.ConstSecurityEncryptionKey));
With
var rsa = new RSACryptoServiceProvider();
rsa.ImportCspBlob(Convert.FromBase64String(SecurityConstants.ConstAsyncSecurityEncryptionKey));
RsaSecurityKey SecurityKey = new RsaSecurityKey(rsa);
Hope that helps someone in the future.

Related

Authentication with JWT Bearer doesn't work the debug says the problem is inside the GetToken() function

I've a code using JWT Bearer to authenticate some tokens as below.
private string GetToken()
{
var issuer = _factory.Configuration.GetValue<string>("JwtSettings:Issuer");
DateTime expiryDate = DateTime.UtcNow.Add(TimeSpan.FromMinutes(1));
var jwtSecurityToken = new JwtSecurityToken(
issuer: issuer,
claims: new List<Claim>()
{
new Claim("a claim", "a claim value")
},
expires: expiryDate,
signingCredentials: new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_factory.Configuration.GetValue<string>
("JwtSettings:Secret"))),
SecurityAlgorithms.RsaSha256Signature
)
);
return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
}
private HttpClient GetClient()
{
var client = _factory.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});
var token = GetToken();
client.DefaultRequestHeaders.Add(HttpRequestHeader.Authorization.ToString(), $"Bearer {token}");
return client;
}
But it doesn't work and I don't have any idea cuz I'm new to C-sharp and .Net
It gives me the error of couldn't create the signature
Please Help.
In your code, you have specified SecurityAlgorithms.RsaSha256Signature which is asymmetric key algorithm which requires two keys (private and public key)
For code to work, change SecurityAlgorithms.RsaSha256Signature to SecurityAlgorithms.HmacSha256Signature

JwtSecurityTokenHandler NotSupportedException at EncryptValue

I have a JsonWebTokenFormat class which creates a JWT token and signs it with a X.509 RSA SSH 256 certificate.
internal class JsonWebTokenFormat : ISecureDataFormat<AuthenticationTicket>
{
private readonly string _issuer;
private readonly ICertificateStore _store;
public JsonWebTokenFormat(string issuer, ICertificateStore store)
{
_issuer = issuer;
_store = store;
}
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
RSA rsaPrivateKey = _store.GetCurrentUserPrivateCertificate(_issuer);
SigningCredentials signingCredentials = new SigningCredentials(new RsaSecurityKey(rsaPrivateKey), SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);
DateTimeOffset? issued = data.Properties.IssuedUtc;
DateTimeOffset? expires = data.Properties.ExpiresUtc;
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
issuer: _issuer,
claims: data.Identity.Claims,
notBefore: issued.Value.UtcDateTime,
expires: expires.Value.UtcDateTime,
signingCredentials: signingCredentials);
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
string jwtAuthToken = jwtSecurityTokenHandler.WriteToken(jwtSecurityToken);
return jwtAuthToken;
}
public AuthenticationTicket Unprotect(string jwtToken)
{
// read the issuer from the token
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(jwtToken);
RSA rsaPublicKey = _store.GetPublicCertificateForClient(jwtSecurityToken.Issuer);
TokenValidationParameters tokenValidationParams = new TokenValidationParameters
{
ValidIssuer = _issuer,
RequireExpirationTime = true,
ValidateIssuer = true,
RequireSignedTokens = true,
ValidateLifetime = true,
ValidateAudience = false,
IssuerSigningKey = new RsaSecurityKey(rsaPublicKey),
ValidateIssuerSigningKey = true
};
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
SecurityToken tempToken;
ClaimsPrincipal principal = jwtSecurityTokenHandler.ValidateToken(jwtToken, tokenValidationParams, out tempToken);
AuthenticationTicket authenticationTicket = new AuthenticationTicket(new ClaimsIdentity(principal.Identity), new AuthenticationProperties());
return authenticationTicket;
}
}
And the ICertificateStore implementation looks like this:
class MockCertificateStore : ICertificateStore
{
private readonly X509Certificate2 _certificate;
public MockCertificateStore()
{
_certificate = new X509Certificate2(
#"C:\certs\test-client.pfx",
"12345",
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.Exportable);
}
public RSA GetCurrentUserPrivateCertificate(string subject)
{
return _certificate.GetRSAPrivateKey();
}
public RSA GetPublicCertificateForClient(string clientId)
{
return _certificate.GetRSAPublicKey();
}
}
So I have this unit test that tests this class and it works fine on my local machine (and other developers' local machines) but it fails on our Jenkins build environment.
It fails with the following exception:
Test method AuthCore.Tests.Token.JsonWebTokenFormatTests.EnsureProtectGeneratesCorrectAuthToken threw exception:
System.NotSupportedException: Method is not supported.
Stack Trace:
at System.Security.Cryptography.RSA.DecryptValue(Byte[] rgb)
at System.Security.Cryptography.RSAPKCS1SignatureFormatter.CreateSignature(Byte[] rgbHash)
at System.IdentityModel.Tokens.AsymmetricSignatureProvider.Sign(Byte[] input) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\AsymmetricSignatureProvider.cs:line 224
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.CreateSignature(String inputString, SecurityKey key, String algorithm, SignatureProvider signatureProvider) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 854
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.WriteToken(SecurityToken token) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 815
at AuthCore.Token.JsonWebTokenFormat.Protect(AuthenticationTicket data) in C:\Jenkins\workspace\AuthCore\Token\JsonWebTokenFormat.cs:line 38
at AuthCore.Tests.Token.JsonWebTokenFormatTests.EnsureProtectGeneratesCorrectAuthToken() in C:\Jenkins\workspace\AuthCore.Tests\Token\JsonWebTokenFormatTests.cs:line 34
Any help is appreciated. I've looked at a bunch of SO questions and none of them helped.
Solved!
The problem was that the RsaSecurityKey class has been deprecated since .NET 4.6.0. For some reason, this class is throwing when used in a computer that doesn't have older version of .NET installed, but it was fine on computer with older versions of .NET. Instead, just use X509SecurityKey class.
Refer to the following article for potential solution:
https://q-a-assistant.com/computer-internet-technology/338482_jwt-generation-and-validation-in-net-throws-key-is-not-supported.html
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;
}

Verifying/validating a JWT token created in PHP in .NET

I have a JWT token created using PHP that I need to then use in a .NET app (framework version 4.5.1). The token is generated in PHP using the following code (relies on https://github.com/lcobucci/jwt library):
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
$tokenBuilder = new Builder();
$tokenSigner = new Sha256();
$token = (string)$tokenBuilder
->setIssuer('localhost:8081')
->setAudience('myaudience')
->setIssuedAt(time())
->setExpiration(time() + 86400)
->sign($tokenSigner, '710VWV0zby')
->getToken();
return $token;
I've been able to read the token fine in C#, but am struggling mightily to figure out how to validate and verify the token signature.
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidateIssuer = true
};
var tokenHandler = new JwtSecurityTokenHandler();
// THIS IS TO TEST IF TOKEN CAN BE READ
/*var jwtToken = tokenHandler.ReadJwtToken(token);
HttpContext.Current.Response.Write(jwtToken.Issuer);*/
SecurityToken validatedToken = null;
try
{
tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
}
catch (Exception)
{
HttpContext.Current.Response.Write("Invalid! :(");
}
if (validatedToken != null) {
HttpContext.Current.Response.Write("Valid! :)");
}
Obviously, my code can't verify any signature, given that there's not even any mention of a SHA-256 key anywhere. I'm assuming I need to include that somehow in the TokenValidationParameters there's a property I need to set, and I'm guessing SigningToken would be the one, but I don't really know where to start to specify an HMAC SHA 256 key.
You need somehow export certificate that was using for token creation. It can be file in .pem format for example. After that create crypto provider using data from that certificate
public static RSACryptoServiceProvider CreateRsaCryptoProviderFromX509Certificate()
{
byte[] certData = Convert.FromBase64String(_CERTIFICATE);
X509Certificate2 x509Cert = new X509Certificate2();
x509Cert.Import(certData);
var x509PublicKeyXml = x509Cert.PublicKey.Key.ToXmlString(false);
RSACryptoServiceProvider RsaProvider = new RSACryptoServiceProvider();
RsaProvider.FromXmlString(x509PublicKeyXml);
return RsaProvider;
}
where _CERTIFICATE store data from .pem file without leading coments
string _CERTIFICATE = #" DD5NYXRyaXg0Ml9mNThlMzdkLWU2ZjktNGU0Yi05MzVlLTNhMDFi
NzU2N2I5YjAeFw0xNjEyMzExNTE1MjNaFw00MjAxMDcxNTE1MjNaMEkxRzBFBgNVBAMMPk1hdHJp
eDQyX0FDU19SZWx5aW5nUGFydHlfZmY1OGUzN2QtZTZmOS00ZTRiLTkzNWUtM2EwMWI3NTY3Yjli
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAho5G6pY9QJs/945aQ1w8oiF/17ZNGsNY
ul5G/+TprN7KfgzT9u+A588f4Z4B8z5QJlwIUeH33iuRcV0AIHd9MnEKR56IdOLLlNWNPvRAG5FJ
Wt4XPlaG+bE/oyuqxqpQM1KJ0iN74K/WLXM8ZdQlq7gTgtLS+icZH3i2arC8rdobh3zRk1wbUVXn
kjR4CASy+07LZwbVVp2g3pOsuy5AWBURIynQ7z3zj+u7NMF42htLOEzISl3Qb3BMOoXFMm93UGwp
B/Ae+zpWFWeh6190ipcUMXoAOfdh9VZUZX9C7OI/3plOiwKUvwfBQyLR8C/4uiTcCTp1i8fS0bta
jkPhdQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA3fmwEgej+BhB7dkw+0TWEDiIC9cXR4uW7kElM
7+L7ARmUYVpAx05Z8oarsR0zm1u3ZYR00y3eLhw5RcXN6hC5jb5HYSQZERdqlzvS6bU6xJ57H7tC
KuPADkYmuPnRM/cdMKPeSG3ZHnHcTgJx62hFloPWbGPr9VLVp4R4coUgtuZMtlFvXamjpCNYSpob
N9wzk36r/4c+Nd/n+4DwqIaVzgEXHXkOUtOZhTYh7SG5WJVUSep5cIq3SBGzLn8oXCjiqn72zJ7C
vn5/ekaC1nzMDMcga5qWQNdLd/rXt65ZMbB/JhM+Ee9TIvmrrDXlvRh2cv7GtoTtPYEbIdVvrF+W";
for validation create token handler, validation parameters and validate token with cryptoprovider
public static bool ValidateJwt(string jwt)
{
JwtSecurityTokenHandler securityTokenHandler = new JwtSecurityTokenHandler();
RSACryptoServiceProvider rsa = CreateRsaCryptoProviderFromX509Certificate();
TokenValidationParameters validationParameters = new TokenValidationParameters()
{
ValidAudience ="urn:6c23aaa7-6da8-4941-98b0-62f63cd146",
ValidIssuer = "https://accounts.issuer.com",
IssuerSigningKey = new RsaSecurityKey(rsa)
};
SecurityToken token;
ClaimsPrincipal claimsPrincipal = securityTokenHandler.ValidateToken(jwt, validationParameters, out token);
return claimsPrincipal.IsInRole("Admin");
}

error while generating jwt SignatureAlgorithm is not supported

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

dnx451 RC1 What happened to InMemorySymmetricSecurityKey?

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

Categories