Hi,
I am trying to use the Web Api and System.IdentityModel.Token.Jwt to do the following:
- Create a JWT signed with an x509 Certificate.
- Consume and validate the JWT signature.
I am new to the Web Api world so my terminology may be slightly off. I'm getting errors on the validation of the token.
Here is the error I'm encountering trying to provide the SigningCredentials
{"IDX10618: AsymmetricSecurityKey.GetHashAlgorithmForSignature( 'HS256' ) threw an exception.\n AsymmetricSecurityKey: 'System.IdentityModel.Tokens.X509AsymmetricSecurityKey'\n SignatureAlgorithm: 'HS256', check to make sure the SignatureAlgorithm is supported.\nException:
'System.NotSupportedException: Crypto algorithm 'HS256' not supported in this context.\r\n at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetHashAlgorithmForSignature(String algorithm)\r\n at System.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(AsymmetricSecurityKey
key, String algorithm, Boolean willCreateSignatures)'."}
Here is the code to "try" to generate the JWT.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace WebApiClient1
{
class resttest2
{
private String GetJWTToken()
{
//Claim
var claimsIdentity = new ClaimsIdentity(new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, "myemail@myprovider.com"),
new Claim(ClaimTypes.Role, "Administrator"),
}, "Custom");
//create the token
System.IdentityModel.Tokens.SecurityToken token;
System.IdentityModel.Tokens.JwtSecurityTokenHandler handler = new System.IdentityModel.Tokens.JwtSecurityTokenHandler();
System.IdentityModel.Tokens.SecurityTokenDescriptor descriptor = new System.IdentityModel.Tokens.SecurityTokenDescriptor();
descriptor.TokenIssuerName = "MikeTokenIss";
descriptor.Subject = claimsIdentity;
descriptor.SigningCredentials = GetSigningCredentials();
descriptor.Lifetime = new System.IdentityModel.Protocols.WSTrust.Lifetime(DateTime.Now, null);
token = handler.CreateToken(descriptor);
var tokenstr = handler.WriteToken(token);
return tokenstr;
}
private SigningCredentials GetSigningCredentials()
{
X509Certificate2 cert = new X509Certificate2("C:\\mike.pfx", "passwordforpfx");
SigningCredentials creds = new X509SigningCredentials(cert, JwtAlgorithms.HMAC_SHA256, cert.GetKeyAlgorithm());
return creds;
}
private AuthenticationHeaderValue GetAuthHeader()
{
AuthenticationHeaderValue authHeader = new AuthenticationHeaderValue("Bearer", GetJWTToken());
return authHeader;
}
public class LoggingHandler : DelegatingHandler
{
public LoggingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
Console.WriteLine("Request:");
Console.WriteLine(request.ToString());
if (request.Content != null)
{
Console.WriteLine(await request.Content.ReadAsStringAsync());
}
Console.WriteLine();
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
Console.WriteLine("Response:");
Console.WriteLine(response.ToString());
if (response.Content != null)
{
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Console.WriteLine();
return response;
}
}
public async Task LocalRunAsync()
{
//using (var client = new System.Net.Http.HttpClient())
using (
var client = new HttpClient(new LoggingHandler(new HttpClientHandler()))
)
{
Console.WriteLine("In RunAsync");
client.BaseAddress = new Uri("http://localhost/RestTestMike20160825/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = GetAuthHeader();
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", GetToken().ToString());
Console.WriteLine("Added Headers");
// HTTP GET
System.Net.Http.HttpResponseMessage response = await client.GetAsync("api/products");
Console.WriteLine("Called api/products/1");
if (response.IsSuccessStatusCode)
{
List<Product> output = default(List<Product>);
var jsonAsString = await response.Content.ReadAsStringAsync();
output = JsonConvert.DeserializeObject<List<Product>>(jsonAsString);
foreach (Product p in output)
{
Console.WriteLine("{0}\t${1}\t{2}", p.name, p.price, p.category);
}
}
else
{
Console.WriteLine("Failure: " + response.ReasonPhrase);
}
}
}
}
}
Thanks in advance.