ms-identity-javascript-angular-tutorial: When using the MSALGuard and RoleGuard on a route, the Role guard will allow access even if the user does not have the correct role

Issue

When using the MSALGuard and RoleGuard on a route, the Role guard will allow access even if the user does not have the correct role! This is due to the fact that there is no guard sequence in Angular.

This issue is for the sample

    - [ ] 1-1) Sign-in with Azure AD
    - [ ] 1-2) Sign-in with Azure AD B2C
    - [ ] 2-1) Acquire a Token and call Microsoft Graph
    - [ ] 3-1) Protect and call a web API on Azure AD
    - [ ] 3-2) Protect and call a web API on Azure AD B2C
    - [ ]   4) Deploy to Azure Storage and App Service
    - [x] 5-1) Call a web API using App Roles
    - [ ] 5-2) Call a web API using Security Groups
    - [ ] 6-1) Call a multi-tenant web API
    - [ ] 7-1) Call Microsoft Graph using on-behalf-of flow
    - [ ] 7-2) Call a web API using Proof of Possession tokens

This issue is for a

    - [ ] bug report -> please search issues before submitting
    - [x] question
    - [ ] feature request
    - [ ] documentation issue or request

Minimal steps to reproduce

Change the sample so that the root of the app also needs the MSALGuard, this will trigger the login sequence as soon as someone uses the website. In other words no need for the LOGIN button. Open a new InPrivate windows and navigate straight to an URL that has both guards active. If there was no previous login, the user is redirected to the Azure AD login flow, BUT the RoleGuard already finished it’s check and returned TRUE ( https://github.com/Azure-Samples/ms-identity-javascript-angular-tutorial/blob/main/5-AccessControl/1-call-api-roles/SPA/src/app/role-guard.service.ts#L34 ). Due to the fact that there were no accounts available yet.

After the login flow of Azure AD the Role guard is no longer checked and the user is presented with the URL he typed in, although he should not be able to see it.

Expected/desired behavior

Role checks can only be done after an account has been acquired AND should be done each time!

Library version

msal-angular: ^2.1.2 angular 13 & 14

Browser and version

Edge

Mention any other details that might be useful

I know this is a limitation of Angular ( there is no guard replay or guard order ), but this Role check example should compensate for this somehow. Because if we want to use role guarding, it should always be checked when we have the user roles available.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 22 (10 by maintainers)

Most upvoted comments

Sounds great! Still working on making this extensible by default, hopefully will get this in to msal-angular

@derisen just wanted to circle back that this works great! But true, now having that baseGuard directly in our code would be nice to get rid off once the base lib has a guard that is extendable.

Thanks! Will take a look as soon as I find some time!

@Depechie of course, my bad. Right now the updated sample is using a custom guard based on MsalGuard (pretty much copy/paste), and then extending it in a role guard. Ideally the MsalGuard itself should be extensible, and I’m separately working on a PR to msal-angular for doing just that. That could take a while so for the moment, I think this is the way forward, but I’m open to suggestions.

That’s fair enough. What I’m thinking is that it might be better to use a single custom guard that combines MsalGuard and RoleGuard, though I can also see the merit of getting multiple guards to work in tandem. There’s an understanding that MsalGuard will not only be able to cover all use cases, so this repo should have at least one example of a custom guard to replace it. Let me look into these. I’ll keep this issue open until then -and thank you for all the feedback!

@Depechie apologies for the late response, we’ve been unusually busy these days. I can reproduce this with the repo you shared. It seems this is simply not a scenario we’ve considered i.e. enabling RoleGuard for the main route where the user signs into.

My understanding is that, in the sample from this repo, when a user hits a component route that has MsalGuard and RoleGuard enabled (like http://localhost:4200/dashboard), she will prompted for sign-in via MsalGuard, and then after sign-in will be redirected to the main route first http://localhost:4200/ (which doesn’t have RoleGuard), and then will be redirected back to http://localhost:4200/dashboard, which at that point account info will be available to RoleGuard.

I don’t have a solution right now but I will put this to backlog and pick it up first when we start updating the samples in this repo. I’m also not entirely sure if this is a legitimate use case, or rather, the best approach to handle this use case. If the user is simply needed to be in a particular role to sign-in to the application, perhaps requiring user assignment would be a better way to handle it?

Nevertheless, if you come up with a solution please feel free to make a PR.

Hey @derisen I will try to create a sample app and put it up on GitHub and list steps I did.

Maybe I did something wrong and that way you can spot it.

I will get back later this week!

Thx for the info by the way!

@Depechie thank you so much for catching this. Let me try to reproduce it and get back to you.