
. : Header , Payload , Signature and usually looks like this aaaaaaa.bbbbbb.cccccc . More information can be found at jwt.io or RFC 7519 .{ "alg": "HS256", "typ": "JWT" }{ "email": "temp@jwt.ru", "user_id": "57dc51a3389b30fed1b13f91" }HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)project.json file: "Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0", "Microsoft.AspNetCore.Mvc.Core": "1.0.0", "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.0" Microsoft.AspNetCore.Mvc.Core assembly instead of Microsoft.AspNetCore.Mvc in order not to drag unnecessary (for our rest service) dependencies in the form of Razor , TagHelper , etc.Startup.cs file, slightly correcting it: public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvcCore(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseMvc().UseMvcWithDefaultRoute(); } } Startup.cs and add the following: public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvcCore() .AddAuthorization(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { var key = Encoding.UTF8 .GetBytes("401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1"); var options = new JwtBearerOptions { TokenValidationParameters = { ValidIssuer = "ExampleIssuer", ValidAudience = "ExampleAudience", IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuerSigningKey = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero } }; app.UseJwtBearerAuthentication(options); app.UseMvcWithDefaultRoute(); } } ConfigureServices method, everything is pretty obvious, we add the use of the authorization service, and also register the HttpContextAccessor . For what we needed explicit registration HttpContextAccessor, we will find out a little later. Let us turn to the Configure method, in which the parameters are set up to validate the JWT token. Now, we are most interested in three parameters:IssuerSigningKey is the key with which our token should be signed. For example, choose SymmetricSecurityKey , but you can also specify X509SecurityKey () or JsonWebKey if you have a lot of love for JSON.ValidateIssuerSigningKey - we indicate that we will verify the key with which the JWT token was signed.ValidateLifetime - set to true , because we want to control the lifetime of the token.HomeController.cs controller: [Route("/")] public class HomeController { private readonly IHttpContextAccessor _context; public HomeController(IHttpContextAccessor context) { _context = context; } [HttpGet("token")] public dynamic GetToken() { var handler = new JwtSecurityTokenHandler(); var sec = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1"; var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(sec)); var signingCredentials = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256Signature); var identity = new ClaimsIdentity(new GenericIdentity("temp@jwt.ru"), new[] { new Claim("user_id", "57dc51a3389b30fed1b13f91") }); var token = handler.CreateJwtSecurityToken(subject: identity, signingCredentials: signingCredentials, audience: "ExampleAudience", issuer: "ExampleIssuer", expires: DateTime.UtcNow.AddSeconds(42)); return handler.WriteToken(token); } [Authorize, HttpGet("secure")] public dynamic Secret() { var currentUser = _context.HttpContext.User; return currentUser.Identity.Name; } } AspNetCore.Mvc.Core , the only way (although there may be another one) is to get to HttpContext - just through IHttpContextAccessor , which we registered earlier.signingCredentials - we create a key with which we sign our token, it should be the same as the one we specified in Startup.cs when setting up JWT parameters.identity - create our payload . Of course, in a real application we will get data from the repository, having checked them before, and now we will build some hardcode.expires: DateTime.UtcNow.AddSeconds(42) , rather trivial and flexible. curl -X GET "http://localhost:<your_port>/token" eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InRlc3RAdGVzdC5ydSIsInVzZXJfaWQiOiI1N2RjNTFhMzM4OWIzMGZlZDFiMTNmOTEiLCJuYmYiOjE0NzQyMTU4MDAsImV4cCI6MTQ3NDIxNTgzNSwiaWF0IjoxNDc0MjE1ODAwLCJpc3MiOiJFeGFtcGxlSXNzdWVyIiwiYXVkIjoiRXhhbXBsZUF1ZGllbmNlIn0.9NhOkoalaE70nIb-erH_waWx8rk6QJta5N19EiBLETQ curl -X GET "http://localhost:<your_port>/secure" 401 Unauthorized will be returned, as expected. curl -X GET -H "Authorization: Bearer token_should_be_here" "http://localhost:<your_port>/secure" GenericIdentity .401 Unauthorized and the WWW-Authenticate header will have the value: Bearer error="invalid_token", error_description="The token is expired" telling us about expired token.blacklist that will contain invalid tokens. But now we still have to make an extra request to check our token.refresh - a token for a longer time. Not a beautiful decision in my opinion.
Source: https://habr.com/ru/post/311594/
All Articles