Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the mixed Authentication and Authorization of Cookie and JWT by .NET Core

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of ".NET Core how to achieve mixed authentication and authorization of Cookie and JWT". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Preface

In order to prevent JWT Token from being stolen, we put Token in Cookie, but if we dock with a third party and call our interface for authentication and authorization, we still need to put Token in the request header at this time. Through practice and theory, we continue to work! First we implement Cookie authentication, then we introduce JWT again, and finally we contact other things that we may need to pay attention to when using the two together.

Cookie certification

In startup, we add cookie authentication service as follows:

Services.AddAuthentication (options = > {options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;}) .AddCookie (options = > {options.ExpireTimeSpan = TimeSpan.FromMinutes (1); options.Cookie.Name = "user-session"; options.SlidingExpiration = true;})

The next step is to use authentication and authorization middleware, which is placed between the route and the endpoint, otherwise there will be a clear exception prompt for startup.

App.UseRouting (); app.UseAuthentication (); app.UseAuthorization (); app.UseEndpoints (endpoints = > {.})

We give the test view page and require authentication that is, the controller to add features

Public class HomeController: Controller {public IActionResult Index () {return View ();}}

When you enter the home page and enter account/login by default without authentication, then create the view.

Public class AccountController: Controller {[AllowAnonymous] public IActionResult Login () {return View ();}.}

Let's start the program and see how it works.

As shown in the figure above, we automatically jump to the login page. At this time, we click the simulated login button to initiate a request to simulate the login (the code for initiating the ajax request is not given)

/ simulated login / [HttpPost] [AllowAnonymous] public async Task TestLogin () {var claims = new Claim [] {new Claim (ClaimTypes.Name, "Jeffcky"),}; var claimsIdentity = new ClaimsIdentity (claims, "Login"); await HttpContext.SignInAsync (CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal (claimsIdentity)); return Ok ();}

The above is nothing more than the construction of the identity and the identity attributes under that identity, similar to the personal ID card that uniquely identifies the individual, and each information on the ID card represents the above declaration. At the same time, the context must be called to log in. Before the whole session expires, the corresponding processing method is obtained according to the authentication scheme, and finally the relevant information is stored, and so on. Interested children's shoes can learn about its implementation details.

When we visit the home page again after the request, we will see that the current session information is generated. At the same time, we set the session expiration to 1 minute, and if we do not have a session within 1 minute, we will automatically redirect to the login page. Note that there is no value marked above. So can this value be set? Of course, we didn't give it at the beginning of the configuration, so what does this property mean?

Options.Cookie.MaxAge = TimeSpan.FromMinutes (2)

So what does it mean when used in combination with ExpireTimeSpan and MaxAge? Let's put aside the sliding expiration setting for a while.

ExpireTimeSpan represents the life cycle of the user's authentication ticket, it is the payload of the authentication cookie, and the stored cookie value is an encrypted string, which is decrypted by the web application on each request.

MaxAge controls the life cycle of cookie, and if cookie expires, the browser will automatically clear it. If this value is not set, its life cycle is essentially ExpireTimeSpan, so what is the point of it?

Above we set the life cycle of the ticket to 1 minute, while we control the life cycle of cookie to 2 minutes. If the browser is closed or the web application is restarted within 2 minutes, the cookie life cycle has not expired, so it will still be in the session state, that is, there is no need to log in. If MaxAge is not set, the value of the browser will be cleared automatically after restart. Of course, all the premise is that the browser cookie has not been manually cleared.

Here's the problem again. In the configuration cookie option, there is another property that can also be set to expire.

Options.Cookie.Expiration = TimeSpan.FromMinutes (3)

When configuring ExpireTimeSpan or configuring MaxAge at the same time, you do not need to set Expiration because an exception is thrown

JWT certification

The above has achieved Cookie authentication, so when docking with third parties, we want to use JWT authentication, how should we deal with it? First, let's add JWT authentication service.

.AddJwtBearer (options = > {options.TokenValidationParameters = new TokenValidationParameters {ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey (Encoding.UTF8.GetBytes ("1234567890123456")), ValidateIssuer = true, ValidIssuer = "http://localhost:5000", ValidateAudience = true, ValidAudience =" http://localhost:5001", ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes (5)};})

Put JWT Token in cookie, which has been explained in the previous article. Here we give the code directly. Sir, it is Token.

Private string GenerateToken (Claim [] claims) {var key = new SymmetricSecurityKey (Encoding.UTF8.GetBytes ("1234567890123456")); var token = new JwtSecurityToken (issuer: "http://localhost:5000", audience:" http://localhost:5001", claims: claims, notBefore: DateTime.Now, expires: DateTime.Now.AddMinutes (5), signingCredentials: new SigningCredentials (key, SecurityAlgorithms.HmacSha256)); return new JwtSecurityTokenHandler (). WriteToken (token);}

In the login method, write it to the response cookie, as follows

/ simulated login / [HttpPost] [AllowAnonymous] public async Task TestLogin () {var claims = new Claim [] {new Claim (ClaimTypes.Name, "Jeffcky"),}; var claimsIdentity = new ClaimsIdentity (claims, "Login") Response.Cookies.Append ("x-access-token", GenerateToken (claims), new CookieOptions () {Path = "/", HttpOnly = true}); await HttpContext.SignInAsync (CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal (claimsIdentity)); return Ok ();}

So how does JWT validate Token? The default is to get the Bearer token value from the request. If you successfully get this value, assign it to the following context.Token, so we need to manually extract the token from the cookie and assign it.

Options.Events = new JwtBearerEvents {OnMessageReceived = context = > {var accessToken = context.Request.Cookies ["x-access-token"]; if (! string.IsNullOrEmpty (accessToken)) {context.Token = accessToken;} return Task.CompletedTask;}}

Now that everything is in place, let's write an api interface test to verify it.

[Authorize ("Bearer")] [Route ("api/ [controller] / [action]")] [ApiController] public class JwtController: ControllerBase {[HttpGet] public IActionResult Test () {return Ok ("test jwt");}}

Think about it, if we pass the Postman simulation test, will we return 401? What will be the result?

It is not a big problem, mainly because the feature parameter specifies the policy for the declaration, but we need to specify the authentication scheme, namely scheme, which is modified as follows:

In this way, when docking with a third party, the request returns token, and then the token is placed in the request header to verify and pass. At the same time, taking the token from the cookie and manually assigning the value is redundant for the third party, but for many other reasons.

[Authorize (AuthenticationSchemes = "Bearer,Cookies")]

Note that there is an order in which the hybrid authentication scheme is set, and the latter will override the former, that is, the above setting. At this time, the cookie authentication will be adopted.

Sliding out of date thinking extension

If we implement sliding expiration based on Cookie and using signalr for data push, there is bound to be a problem, because the session will be refreshed all the time, which will lead to the problem that the session will never expire. From a security point of view, how should we deal with it?

We know that the bill life cycle is stored in the context AuthenticationProperties property, so we can do custom processing in configuring the Cookie option event

Public class CookieAuthenticationEventsExetensions: CookieAuthenticationEvents {private const string TicketIssuedTicks = nameof (TicketIssuedTicks); public override async Task SigningIn (CookieSigningInContext context) {context.Properties.SetString (TicketIssuedTicks, DateTimeOffset.UtcNow.Ticks.ToString ()); await base.SigningIn (context);} public override async Task ValidatePrincipal (CookieValidatePrincipalContext context) {var ticketIssuedTicksValue = context .Properties. GetString (TicketIssuedTicks) If (ticketIssuedTicksValue is null | |! long.TryParse (ticketIssuedTicksValue, out var ticketIssuedTicks) {await RejectPrincipalAsync (context); return;} var ticketIssuedUtc = new DateTimeOffset (ticketIssuedTicks, TimeSpan.FromHours (0)); if (DateTimeOffset.UtcNow-ticketIssuedUtc > TimeSpan.FromDays (3)) {await RejectPrincipalAsync (context); return } await base.ValidatePrincipal (context);} private static async Task RejectPrincipalAsync (CookieValidatePrincipalContext context) {context.RejectPrincipal (); await context.HttpContext.SignOutAsync ();}}

When adding a Cookie service, there is a corresponding event option, using the following

Options.EventsType = typeof (CookieAuthenticationEventsExetensions)

The extended event implementation indicates that when the first session to the current time expires more than 3 days, it will be automatically redirected to the login page, and finally the above extended event can be registered.

This is the end of the content of "how to achieve mixed authentication and authorization of Cookie and JWT in .NET Core". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report