CanActivate returned true but still got 401 Unauthorize error in component

355 views Asked by At

I am true that CanActivate returned true but in my component when I call the database still get 401 error.

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private route: ActivateRouteSnapshot, private tokenService: TokenService) {}

  public canActivate = (
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean => {
    const token = this.tokenService.token; // get jwt token 
    if (!token || this.isTokenExpired(token)) {
        this.route.navigateByUrl('/login');
        return false;
    }   
    return true;
  }
}

isTokenExpired method:

private isTokenExpired = (token: any): boolean => {
   return Number(token.issued_at) + Number(token.expires_in) >= new Date().getTime();
}

I set a break point and found it returned true. However in my component I hit the database I got 401 error.

My component

async ngOnInit() {
    await this.myService.getInformation('url').then(() => this.loading()).catch(this.showing = false;));}

The getInformation method in another class.

public getInformation = (url: string): Promise<void> => {
    return new Promise(resolve, reject) => {
       this.subscription.get().subscribe(response => {
            this.data = response;
            resolve();
       },
          error => {
              console.log(error); // 401 error here
              reject();
          });
    });
}
2

There are 2 answers

0
Hello On BEST ANSWER

Found it.

I used apigee for my OAuthV2 policy. By this:

issued_at The date the access token was issued expressed in Unix epoch time in milliseconds.

expires_in The expiration time for the access token. Expressed in seconds. Although the ExpiresIn element sets the expiration in milliseconds, in the token response and flow variables, the value is expresed in seconds.

So I have to match the data format when calculate the sum.

private isTokenExpired = (token: any): boolean => {
    return Number(token.issued_at) + Number(token.expires_in*1000) < new Date().getTime();
}

Which means

Number(token.issued_at) + Number(token.expires_in)

==>

Number(token.issued_at) + Number(token.expires_in*1000)
3
Austin T French On

From what you have posted, you are missing the HttpInterceptor to inject the authentication token into the Http requests.

A good example:

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
    constructor(public auth: AuthService) {}
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

request = request.clone({
  setHeaders: {
    Authorization: `Bearer ${this.auth.getToken()}`
  }
  });
   return next.handle(request);
 }
}

This would wire up the Http injection through out the application to insert the token into the request headers. Once it's also added to Angular's providers for DI at least.

Then using it would automatiically work like:

// service method
return this.http.get('myApi/mymethod');