Jwtbearer authentication based on. Netcore3.1 series — authentication and authorization scheme

Time:2020-12-3

1. Preface

reviewA preliminary understanding of JWT

In modern web application, it is divided into two parts: front end and back end. At present, the trend of front-end and back-end is increasing rapidly, and front-end devices (mobile phones, tablets, computers, and other devices) emerge in endlessly. Therefore, in order to facilitate the communication between front-end devices and back-end devices, there must be a unified mechanism. So it leads to the popularity of API architecture. andRESTful APIThis API design theory has become a popular way for Internet applications.

The introduction of this API architecture, therefore, we need to consider using a standard, general, stateless, language independent authentication method to achieve API interface authentication.

HTTP provides a standard set ofAuthentication framework: the server can be used to send a challenge to the client’s request, and the client can provide the authentication certificate according to the challenge.

Inquiry and response workflowAt least one of the authentication codes is added to the www-401, and the authentication status is returned in the www-401. Then the client can add authorization header to the request for authentication, and its value is the authentication credential information.

In this article, we will introduce authentication in JWT bearer mode.
JwtBearer

2. Bearer certification

This article will introduceBearerAuthentication also belongs to HTTP protocol standard verification, which is popular with OAuth protocol. For detailed definition, see RFC 6570.

+--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        || Authorization |
     | Client |                               |     Server    |
     |        ||    Resource   |
     |        |                               |     Server    |
     |        |

A security token with the property that any party in possession of the token (a “bearer”) can use the token in any way that any other party in possession of it can. Using a bearer token does not require a bearer to prove possession of cryptographic key material (proof-of-possession).

Therefore, the core of bearer authentication is token, which is called tokenBEARER_TOKENOraccess_tokenIts issuance and verification are completely controlled by our own application program, and do not depend on the system and web server. The standard request mode of bearer authentication is as follows:

Authorization: Bearer [BEARER_TOKEN]

So what are the benefits of using bearer validation?

  • CORS: cookies + CORS cannot cross different domain names. Bearer authentication can use HTTP header header to transmit user information under any domain name.
  • Mobile friendly: when you’re on a native platform (IOS, Android, Windows Phone, etc.), using cookie verification is not a good idea, because you have to deal with cookie containers, and bearer verification is much easier.
  • CSRF: because bearer authentication no longer relies on cookies, cross site request attacks are avoided.
  • Standard: in Cookie authentication, when the user is not logged in, a302To the login page, which is difficult to handle in non browser situations, the bearer validation returns standard401 challenge

3.JWT

The core of bearer authentication described above isBEARER_TOKENHow to ensure the security of token is the top priority. One is through HTTPS, the other is through encryption, encoding and signing token. The most popular token encoding and signing method is JSON web token.

JSON web token (JWT) is an open standard based on JSON (RFC 7519) for the purpose of passing statements between network application environments. The token is designed to be compact and secure, especially suitable for single sign on (SSO) scenarios of distributed sites. Additional information that can be claimed by the service provider and can also be used to authenticate the service provider.

JWT is supported by.It is divided into three parts as follows:

Header.Payload.Signature

JwtBearer

Do you remember the initial understanding of JWT in the previous article? No, we can have a look. We can further understand the features and basic principles of JWT.

After studying the previous articles, we can find that the advantages of using JWT are versatility, compactness and extensibility.

  • generality: because of the universality of JSON, JWT can support cross language, such as Java, JavaScript, nodejs, PHP and many other languages.
  • Compactness: JWT is very simple in structure and occupies a small number of bytes. It is put in the HTTP header through get and post, which is convenient for transmission.
  • ScalabilityJWT is self-contained because it contains some non sensitive information necessary for other business logic because it has the payload part. It stores itself and does not need to save session information on the server side. It is very easy to expand the application.

4. Start

1. Registration and certification services

Here, we use the jwtbearer authentication method provided by Microsoft to register the authentication service.

To introduce the nuget package: Microsoft.AspNetCore.Authentication .JwtBearer

Register the service, add the service to the container,

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        var Issurer = " JWTBearer.Auth "; // publisher
        var Audience = " api.auth "; // audience
        Var secretcredentials = "q2xiarx $4x3tkqbj"; // key

        //Configure authentication service
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(o=>{
            o.TokenValidationParameters = new TokenValidationParameters
            {
                //Verify the issuer
                ValidateIssuer = true,
                Validis = issuer, // publisher
                //Is the audience verified
                ValidateAudience = true,
                Valideaudience = audience, // audience
                //Verify key
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretCredentials)),
                
                Validatelifetime = true, // validation lifecycle
                Requireexpirationtime = true, // expiration time
            };
        });
    }

Note:

1、 Default value of tokenvalidationparameters:
1. Validateaudience = true, ---- if set to false, audience will not be verified
2. Validateissuer = true, ---- if set to false, the issuer publisher will not be verified, but it is not recommended to set this setting
3. ValidateIssuerSigningKey = false,
4. Validatelifetime = true, ---- whether to verify the validity period of token. Compare the current time with notbefore and expired in claims of token
5. Requireexpirationtime = true, ---- whether the claims of token must contain expires
6. ClockSkew =  TimeSpan.FromSeconds (300), --- the server time offset is allowed to be 300 seconds, that is, the expiration time configured by us plus the allowed offset time value is the real expiration time (expiration time + offset value). You can also set it to 0, clockskew= TimeSpan.Zero

Call the method to configure the HTTP request pipeline:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        //1. Turn on authentication first
        app.UseAuthentication();
        //2. Re open authorization
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

stayJwtBearerOptionsIn the configuration ofIssuersigningkey, Validis (token authority), Valideaudience (to whom)Three parameters are required, and the latter two are used with theIssuerandAudienceIf not, the verification fails.

2. Interface resource protection

Create a resource controller that needs authorization protection. Here, we use the build API to generate the controller that comes with the project, weather erForecastController.cs On the controllerAuthorizethat will do

[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger _logger;

    public WeatherForecastController(ILogger logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IEnumerable 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();
    }
}

3. Generate token

Because Microsoft has built-in jwtbearer verification for us, but it does not provide token distribution, we need to implement the method of generating token here

To introduce the nugets package: System.IdentityModel.Tokens .Jwt

Here we are based on IdentityModel.Tokens.Jwt The help class provided by the document provides the method writetoken to create a token. According to the parameter securitytoken, you can instantiate jwtsecuritytoken to specify the class with optional parameters.

/// 
        /// Initializes a new instance of the  class specifying optional parameters.
        /// 
        /// If this value is not null, a { iss, 'issuer' } claim will be added, overwriting any 'iss' claim in 'claims' if present.
        /// If this value is not null, a { aud, 'audience' } claim will be added, appending to any 'aud' claims in 'claims' if present.
        /// If this value is not null then for each  a { 'Claim.Type', 'Claim.Value' } is added. If duplicate claims are found then a { 'Claim.Type', List<object> } will be created to contain the duplicate values.
        /// If expires.HasValue a { exp, 'value' } claim is added, overwriting any 'exp' claim in 'claims' if present.
        /// If notbefore.HasValue a { nbf, 'value' } claim is added, overwriting any 'nbf' claim in 'claims' if present.
        /// The  that will be used to sign the . See  for details pertaining to the Header Parameter(s).
        /// If 'expires' <= 'notbefore'.
        public JwtSecurityToken(string issuer = null, string audience = null, IEnumerable claims = null, DateTime? notBefore = null, DateTime? expires = null, SigningCredentials signingCredentials = null)
        {
            if (expires.HasValue && notBefore.HasValue)
            {
                if (notBefore >= expires)
                    throw LogHelper.LogExceptionMessage(new ArgumentException(LogHelper.FormatInvariant(LogMessages.IDX12401, expires.Value, notBefore.Value)));
            }

            Payload = new JwtPayload(issuer, audience, claims, notBefore, expires);
            Header = new JwtHeader(signingCredentials);
            RawSignature = string.Empty;
        }

In this way, we can specify the content according to the parameters:

1. string iss = " JWTBearer.Auth "; // define the publisher
2. string aud = " api.auth "; // define audience
3. IEnumerable claims = new Claim[]
{
new Claim(JwtClaimTypes.Id,"1"),
new Claim(JwtClaimTypes.Name,"i3yuan"),
}; // define many kinds of claims, such as claims, information storage parts, and the entities of claims generally contain users and some metadata
4. var nbf =  DateTime.UtcNow ; // notbefore
5. var Exp =  DateTime.UtcNow.AddSeconds (1000); // expiration
6. String sign = "q2xiarx $4x3tkqbj"; // the length of SecurityKey must be greater than or equal to 16 characters
 var secret = Encoding.UTF8.GetBytes(sign);
 var key = new SymmetricSecurityKey(secret);
 var signcreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

OK, you can get the value by filling the parameter content above. The complete code is as follows:

newly added AuthController.cs controller:

[HttpGet]
    public IActionResult GetToken()
    {
        try
        {
            //Define issuer
            string iss = "JWTBearer.Auth";
            //Audience definition
            string aud = "api.auth";

            //Many kinds of claims are defined, such as claims, information storage parts, and the entities of claims generally contain users and some metadata
            IEnumerable claims = new Claim[]
            {
                new Claim(JwtClaimTypes.Id,"1"),
                new Claim(JwtClaimTypes.Name,"i3yuan"),
            };
            //Notbefore effective time
            // long nbf =new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
            var nbf = DateTime.UtcNow;
            //Expires // expiration time
            // long Exp = new DateTimeOffset(DateTime.Now.AddSeconds(1000)).ToUnixTimeSeconds();
            var Exp = DateTime.UtcNow.AddSeconds(1000);
            //Signingcredentials
            String sign = "q2xiarx $4x3tkqbj"; // the length of SecurityKey must be greater than or equal to 16 characters
            var secret = Encoding.UTF8.GetBytes(sign);
            var key = new SymmetricSecurityKey(secret);
            var signcreds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwt = new JwtSecurityToken(issuer: iss, audience: aud, claims:claims,notBefore:nbf,expires:Exp, signingCredentials: signcreds);
		    var JwtHander = new JwtSecurityTokenHandler();
            var token = JwtHander.WriteToken(jwt);
            return Ok(new
            {
                access_token = token,
                token_type = "Bearer",
            });
        }
        catch (Exception ex)
        {
            throw;
        }
    }
be careful:
1. The length of the SecurityKey must be greater than or equal to 16 characters, otherwise an error will be generated. (key can be randomly generated online)

5. Operation

Access the token method to get access_ token:

JwtBearer

After visiting and authorizing the resource interface, it can be found that 401 is returned without permission without adding the token value of the request header.

JwtBearer

This time, after the request header adds the token value previously obtained through authorization, it is found that the access resource controller can be obtained and the corresponding data is returned.

JwtBearer

6. Extended description

In the HTTP standard authentication scheme, we are familiar with “basic” and “digest”. The former takes the user name and password encoded by Base64 as the authentication certificate, while the latter is the upgraded version of basic, which is more secure because basic transmits password information in plaintext, while digest transmits encrypted password information.

1、 Basic certification

Basic authentication is a relatively simple HTTP authentication method. The client transmits the user name and password to the server for authentication through plaintext (Base64 encoding format). Usually, it needs to cooperate with HTTPS to ensure the security of information transmission.

The client request needs authorization request header, the value is “basic XXX”, and XXX is the value generated after Base64 encoding of “user name: password”. If the client is a browser, the browser will provide a dialog box to enter the user name and password. After the user enters the user name and password, the browser will save the user name and password to construct the authorization value. When the browser is closed, the user name and password will no longer be saved.

The certificate is “ywxhzgrpbjpvcgvvcvuc2vzywl1”, which is obtained by Base64 encoding the string in the format of “user name: password”. Base64 does not belong to the category of encryption and can be decoded reversely, which is equivalent to plaintext. Therefore, it is not safe for basic to transmit authentication information.

Basic certification diagram:

JwtBearer

Defect summary
1. User name and password plaintext (Base64) transmission needs to cooperate with HTTPS to ensure the security of information transmission.
2. Even if the password is strongly encrypted, the third party can still replay the encrypted user name and password.
3. No protection measures are provided for agents and intermediate nodes.
4. Fake server is easy to cheat authentication and induce users to input user name and password.

2、 Digest digest authentication

Digest authentication is designed to repair the serious defects of the basic authentication protocol. It adheres to the principle of “never send password through plaintext on the network”, and uses “password digest” for authentication, which greatly improves the security.

Digest authentication steps are as follows:
Step 1: client access HTTP resource server. Because digest authentication is required, the server returns two important fields, nonce (random number) and realm.
Step 2: the client constructs the authorization request header, and the value contains the field information of username, realm, nouce, URI and response. Where, realm and nouce are the values returned in the first step. Nouce can only be used by the server once. Uri (digest URI) is the value of request URI. However, considering that the value of request URI may be modified after being forwarded by proxy, a copy will be copied and saved in the URI. Response can also be called request digest, which stores the cipher string after MD5 operation to form response code.
Step 3: the server validates the request containing the authorization value. If the validation passes, the resource can be accessed.
Digest authentication can prevent password disclosure and request replay, but it can’t prevent counterfeiting. So the security level is low.
Digest, like basic authentication, sends the authorization request header every time, which is equivalent to reconstructing this value. So both of them are not easy to use.

Digest authentication diagram:
JwtBearer

7. Attention

  1. During jwtbearer authentication, after the token is generated, it needs to be used together with the refresh token. When the user exits or modifies the password, the token needs to be invalid and cannot be used again. Therefore, access is given_ Token set a short validity period. (jwtbearer authentication will verify the validity period by default, and pass thenotBeforeandexpiresTo verify)access_tokenAfter expiration, users can use therefresh_tokenRecaptureaccess_tokenHowever, this does not belong to the category of bearer authentication, but we can implement it through identityserver in another way. We will explain identityserver in detail in the following.
  2. When generating a token, the secret is mainly used to prevent the token from being forged and tampered with. Because when the token is robbed, you can get some personal unimportant information plaintext in your token, but don’t worry. As long as you don’t release the private personal information in the token generation, even if the person with bad motivation gets it, he can’t do anything. However, you may think that if users generate a token and bring your information, they can not visit your resource server at will. Therefore, you need to use secret to generate token to ensure the correctness of digital signature. In addition, when authenticating authorized resources and parsing token, Microsoft’s source code discovery has helped us encapsulate methods and verify secret to ensure the security of token and thus ensure the security of API resources.

8. Summary

  1. Jwttoken authentication does not require the participation of the security token service security token server. It is all based on claim. By default, the validity period will be verifiednotBeforeandexpiresThis provides great convenience in distributed computing.
  2. Jwttoken has nothing to do with platform and wordless. Claims can also be directly resolved in the front end.
  3. If there is something wrong or incomprehensible, I hope you can point out more, ask questions, discuss together, keep learning and make progress together.
  4. The authorization in authentication and authorization scheme will be explained and shared later.
  5. This example source code address
    Reference jwtbearer source code

Recommended Today

Regular expression sharing for checking primes

This regular expression is shown as follows: Regular expressions for checking prime numbers or not To use this positive regular expression, you need to convert the natural number into multiple 1 strings. For example, 2 should be written as “11”, 3 should be written as “111”, 17 should be written as “11111111111”. This kind of […]