I've a simple .Net Core 3.1 Web API example here:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(o =>
{
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
This is the controller:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly IConfiguration _configuration;
public WeatherForecastController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpGet]
[Route("generate-token")]
public string GenerateToken()
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Sub, "admin"),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Key"]));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token= new JwtSecurityToken(
_configuration["JWT:Issuer"],
_configuration["JWT:Audience"],
claims,
expires: DateTime.Now.AddMinutes(Convert.ToInt32(_configuration["JWT:ExpireInMinutes"])),
signingCredentials: credentials);
return token.EncodedPayload;
}
[Authorize]
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
This is the appsettings:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"JWT": {
"Key": "e89b7555-ef37-457e-a6a8-90d149927548",
"Issuer": "test",
"Audience": "https://localhost:5001/",
"ExpireInMinutes": "60000"
},
"AllowedHosts": "*"
}
If you try to generate the token calling the endpoint
https://localhost:5001/weatherforecast/generate-token
and then use it to make a call with Postman or similar client to the [Autorize] method https://localhost:5001/weatherforecast
, you'll receive a 401 invalid_token
.
> GET /weatherforecast HTTP/2
> Host: localhost:5001
> user-agent: insomnia/2022.4.2
> content-type: application/json
> authorization: Bearer eyJqdGkiOiJiMDI2OWY0ZS1mODhmLTRmN...
> accept: */*
< HTTP/2 401
< date: Fri, 08 Jul 2022 17:28:27 GMT
< server: Kestrel
< www-authenticate: Bearer error="invalid_token"
< content-length: 0
I'm stuck with this and I know I'm missing something but I cannot figure what!
Can someone give me an hint?
CodePudding user response:
You only returned the Payload of jwt whereas jwt consists of 3 parts. these are Header, Payload and Signature.
return token.EncodedPayload;
you can use WriteToken()
var token= new JwtSecurityToken(....)
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(token);
return jwt;