Search code examples
angularauthenticationjwtangular-router-guards

Wait until a subscribe is called in angular


Good morning, I created an angualr app and I need to check users role in routing. I created a service "RoleGuardService" with a method canLoad that read the JWS token and check the user permission:

import * as JWT from 'jwt-decode';
...
   const tokenPayload: App = JWT(token);
   if(tokenPayload.UserType == expectedRole){
      return true;
   }
   return false;

So far so good, but this force me to declare the permission hard coded:

{ path: 'xxx', component: yyy, canLoad: [RoleGuardService], data: { expectedRole: 'Admin' } },

Is possible to create a method that requires authorization directly from the web API? like:

    var isAllowed = false;
    this.http.get('https://xxx/check_user/').subscribe(result: bool) => {
        isAllowed = result;
    }
    ///wait until the subscribe is called
    return isAllowed;

Solution

  • You can use the canActivate parameter for route from Core angular which has been created for that type of usecase https://angular.io/api/router/CanActivate

    exmaple:

      {
        path: 'protectedRoute',
        component: SecureComponent,
        data: {
          authorities: ['ROLE_ADMIN'],
        },
        canActivate: [UserRouteAccessService]
      }
    
    
    
    
    
    @Injectable({ providedIn: 'root' })
    export class UserRouteAccessService implements CanActivate {
      constructor(
        private router: Router,
        private accountService: AccountService,
      ) {}
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
        const authorities = route.data['authorities'];
        return this.accountService.identity().pipe(
          map(account => {
            if (!account) {
              return false;
            }
    
            if (!authorities || authorities.length === 0) {
              return true;
            }
    
            const hasAnyAuthority =   authorities.some((authority: string) => account.authorities.includes(authority));
            if (hasAnyAuthority) {
              return true;
            }
            this.router.navigate(['accessdenied']);
            return false;
          })
        );
      }
    
    }
    

    where AccountService is your service to get current login user