Verify token with API in Angular8 canActivate method of AuthGuard

半城伤御伤魂 提交于 2020-11-29 10:23:46

问题


I want to do some validation on each refresh request for some routes. So I'm using Angular AuthGuard. The problem is in canActivate method I want to perform validation with online API.

API is /token/verify which simply gets token variable (jwt) and verify if it's true or false. Then if verify is not complete will route to /login page else do the rest.

Here is the code:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
let token = this.auth.getToken();
let url = '/token/verify/';
if (!token) {
  this.router.navigate(['/login']);
  return false;
}
this.auth.verifyToken().then(res => {
  return true;
}).catch(err => {
  this.router.navigate(['/login']);
  return false;
})

and the verifyToken method is like this:

verifyToken(): Promise<boolean> {
    let token = this.getToken();
    return !token ?
        new Promise<boolean>(resolve => {
            resolve(false);
            return false;
        }) :
        this.http.post(this.url + '/token/verify/', { 'token': token })
            .toPromise()
            .then((res) => {
                localStorage.data = JSON.stringify(res);//(res.json());
                return true;
            }
            ).catch((error) => {
                return false
            });
}

Problem is that the promise call doesn't work and will be passed. I mean the first part that does check it from localstorage works fine. But the next part that checks it with online API will not work. and authGuard doesn't wait for its response to do the routing.

I guess it should be in some async/await manner. But I did some tests and none of them worked. Will be glad if anyone could help me.


回答1:


I think you'll be able to simplify the whole implementation if you use Observables instead.

If you do consider that proposal, then your verifyToken method could be refactored to this:

import { of, Observable } from 'rxjs';

verifyToken(): Observable<boolean> {
  const token = this.getToken();
  return token ? this.http
    .post(this.url + '/token/verify/', {
      'token': token
    })
    .pipe(
      tap(res => localStorage.data = JSON.stringify(res)),
      map(
        res => true,
        error => false
      )
    ) : of(false)
}

And then in your Guard, you'd simply do this:

canActivate(
  next: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): Observable < boolean > | Promise < boolean > | boolean {
  const token = this.auth.getToken();
  const url = "/token/verify/";

  if (!token) {
    this.router.navigate(['/login']);
    return false;
  }

  return this.auth.verifyToken().pipe(
    catchError(err => {
      console.log('Handling error locally and rethrowing it...', err);
      this.router.navigate(['/login']);
      return of(false);
    })
  );

}

Here's a Working Demo for your ref.



来源:https://stackoverflow.com/questions/59442021/verify-token-with-api-in-angular8-canactivate-method-of-authguard

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!