skip to Main Content

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?

2

Answers


  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?

    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.

    Login or Signup to reply.
  2.  // 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);
        }
    

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search