tokenreloadangular17

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


After login I am generating a token and I am saving that in storage session. 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 I want to reset the token expiry time back to 8 minutes or generate a new token. How to do that?

in login I am generating token in 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 in 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);
      }
    }