angulartokenreloadangular17

How to change the token expiry time after page refresh in angular?


After login, I am generating a token and I am saving it in the session storage . The expiry time of the token is 8 minutes and everything is fine. The problem I am having is, when I upload a photo, for example, the page is refreshed and the token is still expiring exactly after 8 minutes, but what I want is when refreshed the token expiry is reset to 8 minutes again or generate a new token is generated. How to do that?

This is how I am generating a token in the API:

loginRes.Token = CreateJWT(user);

private string CreateJWT(User user)
    {
        var secretKey = configuration.GetSection("AppSettings:Key").Value;
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

        var claims = new Claim[] {
            new Claim(ClaimTypes.Name, user.Username),
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
        };

        var signingCredentials = new SigningCredentials(
                                key, SecurityAlgorithms.HmacSha256Signature);

        var tokenDescriptor = new SecurityTokenDescriptor{
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.UtcNow.AddMinutes(8),
            SigningCredentials = signingCredentials
        };

        var tokenHandler = new JwtSecurityTokenHandler();
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

Where it says Expires = DateTime.UtcNow.AddMinutes(8),.

Now in the frontend I have a page to upload photos and when I do, the page is refreshed to show the uploaded photos:

initializeFileUploader() {
    this.uploader = new FileUploader({
    url: this.baseUrl + '/familydocuments/add/photo/' + this.thefolder,
    authToken: 'Bearer ' + sessionStorage.getItem('token'),
    isHTML5: true,
    removeAfterUpload: true,
    autoUpload: true,
    maxFileSize: this.maxAllowedFileSize
});
    
this.uploader.onAfterAddingFile = (file) => {
    file.withCredentials = false;
};
    
this.uploader.onSuccessItem = (item,respose,status, header) => 
    {
        if (respose) {
            const photo = JSON.stringify(respose);
            const photos = JSON.parse(photo);
            this.allPhotos.push(photos);
        }
    
        // setTimeout(()=>
        // {
        //   window.location.reload();
        //   this.router.navigate(["familydocuments"])
        // }, 15000);
    };
});

either I need to generate new token or show the photo without reloading the page, How to do that?


Solution

    1. When you refresh your page and your application is reloaded you need to check few things:

    If 'yes' to all then use the token from the session storage for your http transactions.

    1. Refresh your token when it's close to expiration. When you receiev or read the token from the session storage, then you need to run some job based on your expiration time to send new request to your API and get new token. Some people simply run setTimeout with 1 minute before token expiration. When you received new token, then update in other places (session storage, etc.)

    Simply saying, every time when you need to save new token or restore the token you need to run a function that calculates the expiration time and sets a timer to refresh the token. Example below:

    someservice.ts

    ...
    public yourLogin() {
      // your logic
      ...
      // start the timer
      refreshToken();
    }
    
    public restoreToken() {
      // your logic to restore from the sessions storage
      ...
      // start the timer
      refreshToken();
    }
    
    public logout() {
      ...
      // clear leftovers
      clearTokenTimer();
    }
    
    private refreshToken() {
        const myToken = jwt_decode<TokenDataModel>(token);
        // example calculate token
        const tokenTimeout = (myToken.exp * 1000 ) - Date.now() - 60000; // where 60000 - 1 min. timeout will be set to execute token refresh logic 1 min before timeout expiration
        // Initialize token refresh timer
        this.yourTokenTimer = setTimeout(() => {
          // refresh token
          ...
          // save token
          ...
        }, tokenTimeout );
    }
    
    private clearTokenTimer() {
        clearTimeout(this.yourTokenTimer);
    }
    ...
    

    Your API side will be next way:

    public class YourLoginController
    {
      // login
      ...
    
      // refresh token
      [HttpGet("myrefreshtoken")]
      [Authorize]
      public async Task<IActionResult> RefreshMyToken()
      {
         // add try catch and validation as needed
         // where MyTokenDto custom data model with string Token and other prop based on your needs
         MyTokenDto newRefreshedToken = await yourUserTokenService.GetNewTokenAsync(HttpContext.User.Claims);
         return Ok(newRefreshedToken);
      }
    }