AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.64k stars 2.65k forks source link

MsalGuard - Support RBAC with CanActivateFn #5804

Open dirthsj opened 1 year ago

dirthsj commented 1 year ago

Core Library

MSAL.js v2 (@azure/msal-browser)

Wrapper Library

MSAL Angular (@azure/msal-angular)

Public or Confidential Client?

Public

Description

Starting with Angular 14.2, you can pass a CanActivateFn to the canActivate array. This function can contain inject calls and can be created dynamically at runtime very easily.

I have created a wrapper for MsalGuard which implements RBAC using this feature, but it would be nice if it was officially supported. Here is a sample of my implementation:

  static forRole(role: string): CanActivateFn {
    return (route, state) => {
      const msalGuard = inject(MsalGuard);
      const authGuardBase = new RoleAuthGuard(msalGuard, role);
      return authGuardBase.canActivate(route, state);
    }
  }

RoleAuthGuard handles waiting for MsalGuard to succeed, then acquires a token from Msal using acquireTokenSilent and verifies the idTokenClaims contain the specified role. This could be much more efficient if MsalGuard could verify the idTokenClaims internally.

Example Usage:

const routes: Routes = [
  {
    component: AdminComponent,
    path: 'admin',
    canActivate: [RoleAuthGuard.forRole('Administrator')],
  }
}

PS: Also of note, class and InjectionToken guards and resolvers, such as the current MsalGuard impelmentation, are scheduled for removal in Angular 17. CanActivateFn is the replacement. I would appreciate it if this feature was included when the necessary changes to support Angular 17 are made.

Source

External (Customer)

derisen commented 1 year ago

@dirthsj @sameerag possibly related to #3406

dirthsj commented 1 year ago

@dirthsj @sameerag possibly related to #3406

Exposing activateHelper etc. as proposed in this issue would not change the implementation of my wrapper (I would still prefer composition over inheritance).

However, it may be possible to provide a much more configurable MsalGuard using a similar approach to the one I requested; for example accepting callback functions for additional validation rather than just scopes.

Perhaps something like an MsalGuard.withTokenValidator((token) => ...)) would be better if the overall goal is flexibility.

sameerag commented 1 year ago

cc @EmLauber @jo-arroyo Can we track this as a feature request?

ghost commented 1 year ago

@dirthsj This issue has been automatically marked as stale because it is marked as requiring author feedback but has not had any activity for 5 days. If your issue has been resolved please let us know by closing the issue. If your issue has not been resolved please leave a comment to keep this open. It will be closed automatically in 7 days if it remains stale.

dirthsj commented 1 year ago

This comment exists to avoid the bot closing this issue. If any further information on my request is desired, I have not received that impression from the comments above.

EmLauber commented 1 year ago

Assigning to myself as this is a feature enhancement we will take under consideration. At this time, we are still evaluating MSALGuard enhancements.

miguellira commented 1 year ago

@dirthsj I have a similar situation/need. However, rather than simply verifying the idTokenClaims to determine access, I need to grab a custom claim and make an API call to resolve roles & permissions for the successfully authenticated user.

Can you share or explain how your RoleAuthGuard implementation waits for the MsalGuard to complete?

dirthsj commented 1 year ago

I'm away from work at the moment, so I can't get at my source code, but it's basically just calling msalGuard.canActivate, then using rxjs switchMap on the result, passing through the error cases and handling the success case with additional logic.

RaicuRobert commented 10 months ago

Hello, I am also currently writing a wrapper for msal to add rbac. Luckily the current implementation still works with angular 17. Any news on the enhancement?