简体   繁体   中英

.net core 2.0 JWT token

I have a web Api built with .net core 2.0 and a mobile app built with xamarin. To login the mobile app make a call to the web api by passing (username and password). If the credentials are valid web Api provide back a JWT token. The mobile app has a feature that keep the user logged in even when you close the app, like (facebook, Instagram etc...).

The question are these:

  1. How to keep the JWT token valid until the user is logged-In in the app without ask him/her again the login credentials to give him/her another valid JWT token?
  2. How to make the JWT token invalid after the user decide to logout from the app?

How to keep the JWT token valid until the user is logged-In in the app without ask him/her again the login credentials to give him/her another valid JWT token?

You can set a token expiry date and keep track of that.

How to make the JWT token invalid after the user decide to logout from the app?

  • If you keep the expiry time short and keep refreshing the token expiry until the user logs out.
  • You can save some kind of blacklist of invalid tokens so you can validate against that.

Update:

The JWT consists of the Header, Payload and Signature. You can read all about it here In the payload you can set an claim called: "exp".

The docs: The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim.

Also, while researching to clarify my answer I found this SO answer: JSON Web Token expiration .

 // This code tested with dotnet core 2.1 ( WebApi + Jwt )  with sample structure 

//Add One class Auth to your project

public static class Auth
{
    private static string salt = "jnyanendra_sethi"; // u can chose any key satisfying the length 
    private static int timeoutInMinute = 1;
    private static string _issuer = "http://localhost:5000";
    private static string _audience = "http://localhost:5000";

    //Generate Token
    public static string GenerateToken(Customer customer, List<SupplierInfo> lstSpplierInfo)
    {
        var securitykey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
        var credential = new SigningCredentials(securitykey, SecurityAlgorithms.HmacSha256);

        // var suppliers = any json string e.g. [{"SupplierId":1001,"SupplierName":"RateHawk"},{"SupplierId":1002,"SupplierName":"Hotelbeds"}]
        var suppliers = JsonConvert.SerializeObject(lstSpplierInfo);//"ur json object to store in claim";
        var claims = new List<Claim> {
           new Claim("CustomerName", customer.CustomerName),
           new Claim("Suppliers",suppliers )
       };

        var mytoken = new JwtSecurityToken(issuer: _issuer, audience: _audience,
            claims: claims, notBefore: DateTime.Now, expires: DateTime.Now.AddMinutes(timeoutInMinute), signingCredentials: credential);
        var tokenValue = new JwtSecurityTokenHandler().WriteToken(mytoken);
        return tokenValue;
    }

    //Validate token

    public static void ValidateJwtToken(this IServiceCollection services)
    {
        var securitykey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
        var credential = new SigningCredentials(securitykey, SecurityAlgorithms.HmacSha256);

        var tokenParam = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            ValidIssuer = _issuer,
            ValidAudience = _audience,
            ValidateIssuer = true,
            ValidateAudience = true,
            RequireSignedTokens = true,
            IssuerSigningKey = credential.Key,
            ClockSkew = TimeSpan.FromMinutes(timeoutInMinute)
        };

        services.AddAuthentication(
            options =>
            {
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(
            options =>
            {
                options.TokenValidationParameters = tokenParam;
            });

    }
}

[Route("api/[controller]")]
[ApiController]
public class HotelController : ControllerBase
{

    [HttpGet("Search")]
    public SearchReponse Search()// u can take search parameters for input
    {
        // based on apikey or username, call db for first time
        // get customername / supplierinfo from db
        Customer customer = new Customer() { CustomerId = "CUS001", CustomerName = "TestCust" };// dummy
        if (customer == null)
        {
            this.HttpContext.Response.StatusCode = 401;
            return new SearchReponse()
            {
                ErrorInfo = new ErrorInfo()
                {
                    Code = "0",
                    Description = "No Customer Found"
                }
            };
        }

        string token = Auth.GenerateToken(customer, GetDummyDataToStoreInClaim());

        SearchReponse reponse = new SearchReponse()
        {
            GeneralInfo = new GeneralInfo()
            {
                Token = token,
                Duration = 0
            },
            Hotels = "Hotels Data",
        };
        return reponse;
    }

    [Authorize]
    [HttpGet("Get/{id}")]
    public ActionResult<string> Get(int id)
    {//// Getting the data stored in claim that required for further process
        var CustomerName = HttpContext.User.Identities.FirstOrDefault().Claims.FirstOrDefault(x => x.Type == "CustomerName").Value;
        var strSuppliers = HttpContext.User.Identities.FirstOrDefault().Claims.FirstOrDefault(x => x.Type == "Suppliers").Value;
        return CustomerName;
    }
}

Models I have used:

 public class SearchReponse
{
    public GeneralInfo GeneralInfo { get; set; }
    public ErrorInfo ErrorInfo { get; set; }
    public string Hotels { get; set; }
}
public class GeneralInfo
{
    public string Token { get; set; }
    public long Duration { get; set; }
}
public class ErrorInfo
{
    public string Code { get; set; }
    public string Description { get; set; }
}

In Startup.cs

public void ConfigureServices(IServiceCollection services)
    {

        services.ValidateJwtToken();
        services.AddAuthorization(Options => {
            Options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
        });
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

--

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM