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?
If 'yes' to all then use the token from the session storage for your http transactions.
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);
}
}