0

Thanks in advance. Actually, I wan to implement JWT refresh token in Angular 7 Application using HTTP Interceptor. I've implemented JWT using HTTP Message Handler (DelegatingHandler). On Unauthorized request I'm receiving HttpErrorResponse Status = 0 instead 401 to refresh the token.

Browser Window: 2:50191/api/test/testget:1 GET http://localhost:50191/api/test/testget 401 (Unauthorized) :4200/#/login:1 Access to XMLHttpRequest at 'http://localhost:50191/api/test/testget' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

.NET 4.5 Web API 2.0: CORS Added.

Angular: HTTP Interceptor intercept(req: HttpRequest, next: HttpHandler): Observable> {

    return next.handle(this.attachTokenToRequest(req)).pipe(
        tap((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                console.log("Success");
            }
        }), catchError((err): Observable<any> => {
            if (err instanceof HttpErrorResponse) {
                switch ((<HttpErrorResponse>err).status) {
                    case 401:
                        console.log("Token Expire,,, attempting 
refresh");
                        return this.handleHttpResponseError(req, next);
                    case 400:
                        return <any>this.authService.logout();
                }
            } else {
                return throwError(this.handleError);
            }
        })
    )
}

API:

WebApiConfig:

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        var cors = new EnableCorsAttribute("*", "*", "*", "*");
        config.EnableCors(cors);
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.MessageHandlers.Add(new TokenValidationHandler());

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

TokenValidationHandler:

protected override async Task<HttpResponseMessage> 
SendAsync(HttpRequestMessage request, CancellationToken 
cancellationToken)
    {
        HttpStatusCode statusCode;
        string token;
        //determine whether a jwt exists or not
        if (!TryRetrieveToken(request, out token))
        {
            statusCode = HttpStatusCode.Unauthorized;
            //allow requests with no token - whether a action method 
needs an authentication can be set with the claimsauthorization attribute
            var response = await base.SendAsync(request, 
cancellationToken);
            //response.Headers.Add("Access-Control-Allow-Origin", "*");
            return response;
        }

        try
        {
            const string sec = "5a65ed1";
            var now = DateTime.UtcNow;
            var securityKey = new 
SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));


            SecurityToken securityToken;
            JwtSecurityTokenHandler handler = new 
JwtSecurityTokenHandler();
            TokenValidationParameters validationParameters = new 
 TokenValidationParameters()
            {
                ValidAudience = "http://localhost:50191",
                ValidIssuer = "http://localhost:50191",
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                LifetimeValidator = this.LifetimeValidator,
                IssuerSigningKey = securityKey
            };
            //extract and assign the user of the jwt
            Thread.CurrentPrincipal = handler.ValidateToken(token, 
validationParameters, out securityToken);
            HttpContext.Current.User = handler.ValidateToken(token, 
 validationParameters, out securityToken);

            return await base.SendAsync(request, cancellationToken);
        }
        catch (SecurityTokenValidationException e)
        {
            statusCode = HttpStatusCode.Unauthorized;
        }
        catch (Exception)
        {
            statusCode = HttpStatusCode.InternalServerError;
        }
        return await Task<HttpResponseMessage>.Factory.StartNew(() => new 
  HttpResponseMessage(statusCode) { });
    }

I am expecting http status code 401 to refresh the jwt token.

1 Answer 1

0

You can use small helper libraries to validate the token expiration locally and then re-authenticate or obtain a refresh token if it is expired. This might be a little cleaner solution.

I have used JwtHelper from angular2-jwt in my auth-gard service with success.

import { JwtHelper } from 'angular2-jwt';
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private jwtHelper: JwtHelper, private router: Router) {
  }
  canActivate() {
    var token = localStorage.getItem("jwt");

    if (token && !this.jwtHelper.isTokenExpired(token)){
      console.log(this.jwtHelper.decodeToken(token));
      return true;
    }
    this.router.navigate(["login"]);
    return false;
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for answer. It's already implemented in Guard. I've solved the issue attaching a header (:Access-Control-Allow-Origin":"localhost:4200") in "TokenValidationHandler" before returning response and received the proper Status code (400, 401 etc). Now it's working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.