user8564782
user8564782

Reputation:

Refresh token angular 8

I have an app using Angular 8 that works with .NET core. I would like to know how I can refresh a JWT token.

I have an integration that allows users to validate and return a token. This token has a duration of 30 minutes.

What I want to achieve is that, from the Angular app, I can detect when the token has 5 minutes left before it expires and, if so, it goes to the web API and generates it again.

Upvotes: 1

Views: 1541

Answers (3)

Gustavo Lopes
Gustavo Lopes

Reputation: 4174

There is an extreme helpful library to work with JWT inside an Angular application.

You should give it a try. https://github.com/auth0/angular2-jwt

With this library, you don't need to manage the token yourself, you can simply configure it to send the token for every http request you make.

You can even request a refresh token in case of an expired token.

All builtin in the library. Simpler and safer than managing the token yourself.

Upvotes: 1

JeePakaJP
JeePakaJP

Reputation: 840

Check this link It's a great explanation to refresh JWT token.

Check server side code

Create token

        [HttpPost("Authenticate")]
        [AllowAnonymous]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(typeof(TokenResponse), StatusCodes.Status200OK)]
        public async Task<IActionResult> Authenticate([FromBody]LoginModel model)
        {

            // get current user
            var user = await _accountService.FindByEmailAsync(model.Email);

            if (user != null)
            {
                var result = await _accountService.CheckPasswordSignInAsync(user, model.Password, false);

                if (result.Succeeded)
                {
                    // check refresh token delete if exits and recreate new
                    var refreshToken = await _refreshTokenService.GetRefreshToken(user);
                    if (refreshToken != null)
                        await _refreshTokenService.DeleteRefreshToken(refreshToken);

                    var newRefreshToken = new RefreshToken
                    {
                        UserId = user.Id,
                        Token = Guid.NewGuid().ToString(),
                        IssuedUtc = DateTime.Now.ToUniversalTime(),
                        ExpiresUtc = DateTime.Now.ToUniversalTime().AddMinutes(Convert.ToDouble(_appSettings.ExpireMinutesTokenRefresh))
                    };

                    await _refreshTokenService.CreateRefreshToken(newRefreshToken);


                    // generate jwt token
                    var token = GenerateJwtToken(model.Email, user, out DateTime expires);

                    var response = new TokenResponse
                    {
                        AccessToken = token,
                        RefreshToken = newRefreshToken.Token,
                        FirstName = newRefreshToken.User.FirstName,
                        LastName = newRefreshToken.User.LastName,
                        TokenExpiration = expires,
                    };

                    return Ok(response);
                }
                else
                {
                    return BadRequest("Login or password incorrect");
                }
            }
            else
            {
                return BadRequest("Login or password incorrect");
            }
        }

Refresh token

        [HttpPost]
        [AllowAnonymous]
        [Route("Token/Refresh")]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesResponseType(StatusCodes.Status401Unauthorized)]
        [ProducesResponseType(typeof(TokenResponse), StatusCodes.Status200OK)]
        public async Task<IActionResult> RefreshToken([FromBody] RefreshToken refreshToken)
        {
            var refreshTokenFromDatabase = await _refreshTokenService.GetRefreshToken(refreshToken);

            if (refreshTokenFromDatabase == null)
                return BadRequest();

            if (refreshTokenFromDatabase.ExpiresUtc < DateTime.Now.ToUniversalTime())
                return Unauthorized();

            if (!await _accountService.CanSignInAsync(refreshTokenFromDatabase.User))
                return Unauthorized();

            //if (_accountService.SupportsUserLockout && await _accountService.IsLockedOutAsync(refreshTokenFromDatabase.User))
            //    return Unauthorized();

            var token = GenerateJwtToken(refreshTokenFromDatabase.User.Email, refreshTokenFromDatabase.User, out DateTime expires, true);

            var response = new TokenResponse
            {
                AccessToken = token,
                RefreshToken = refreshTokenFromDatabase.Token,
                FirstName = refreshTokenFromDatabase.User.FirstName,
                LastName = refreshTokenFromDatabase.User.LastName,
                TokenExpiration = expires
            };

            return Ok(response);
        }

Upvotes: 1

Tony
Tony

Reputation: 20082

From this sample you can do like this.

login(user: LoginModel): Observable<any> {
        return this.getTokens(user, 'password')
            .catch(res => Observable.throw(res.json()))
            .do(res => this.scheduleRefresh());
    }

private scheduleRefresh(): void {
    this.refreshSubscription$ = this.tokens$
        .first()
        // refresh every half the total expiration time
        .flatMap(tokens => Observable.interval(tokens.expires_in / 2 * 1000))
        .flatMap(() => this.refreshTokens())
        .subscribe();

So when we login we will run scheduleRefresh to automatically refresh token in the background

Upvotes: 1

Related Questions