Azure-Samples / ms-identity-javascript-react-tutorial

A chapterwise tutorial that will take you through the fundamentals of modern authentication with Microsoft identity platform in React using MSAL React
https://github.com/AzureAD/microsoft-authentication-library-for-js
MIT License
306 stars 275 forks source link

How to assign permissions to app roles from Azure Ad Portal instead of hardcoding it on application level? #203

Closed kevinvugts closed 1 year ago

kevinvugts commented 1 year ago

Issue

Azure AD provides us with a nice mechanism of assigning users to a app role defined in the Azure AD portal. However there is no mechanism which defines the permissions each app role has. For example what if we want to control the CRUD operations on a role called TaskUser (as defined in the docs). What if we only want to allow POST and GET for that role.

How can we do this without hardcoding the correlation between an app role and it's permissions. Currently this is hardcoded in the following example created by Microsoft: https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/tree/main/5-AccessControl

Please provide us with the following information:

This issue is for the sample

https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/tree/main/5-AccessControl

    - [ ] 1-1) Sign-in with Azure AD
    - [ ] 1-2) Sign-in with Azure AD B2C
    - [ ] 2-1) Acquire a Token and call Microsoft Graph
    - [x] 3-1) Protect and call a web API on Azure AD
    - [ ] 3-2) Protect and call a web API on Azure AD B2C
    - [ ] 4-1) Deploy to Azure Storage and App Service
    - [ ] 4-2) Deploy to Azure Static App Service
    - [x ] 5-1) Call a web API using App Roles
    - [ ] 5-2) Call a web API using Security Groups
    - [ ] 6-1) Call Microsoft Graph using on-behalf-of flow
    - [ ] 6-3) Call a web API using Conditional Access Auth Context
    - [ ] 6-4) Sign-in with Hybrid SPA flow

This issue is for a

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

Minimal steps to reproduce

  1. Follow the steps as stated in the example tutorial

Any log messages given by the failure

Expected/desired behavior

No hardcoding permissions like (PUT, POST, UPDATE, DELETE) but manageable in the Azure Portal. Otherwise we have to maintain this on application level, which is not desired.

Also the possibility for Deviating settings per role per api pathname.

App Role: TaskUser API Path: /api/todolist Allowed Operations: POST, GET

App Role: TaskAdmin API path: /api/todolist Allowed Operations: POST, GET, UPDATE, DELETE

Library version

"@azure/msal-browser": "^2.31.0", "@azure/msal-react": "^1.4.10",

Browser and version

Chrome Versie 108.0.5359.94 (Officiële build) (arm64)

Chrome, Edge, Firefox, Safari?

Mention any other details that might be useful

In my opinion the app roles are not a true RBAC system for our applications. We are missing control from the Azure portal for granularly control over permissions for each app role. We simply can't apply permissions to roles from the Azure portal. What is the point of having app roles if a role without a specific set of permissions assigned to them?

Take this example screenshot from the opensource headless CMS called Strapi. This is something I have no clue of if this even possible with Azure Add app roles. Hopefully someone has the answer to it!

roles-and-permissions

Lastly, in term of security, we can just change the app roles in sessions storage or local storage in the front-end, so what's the point anyway of having a RouteGuard which is useless in terms of security?

In terms of security we have to add this on API level of course. (as described per docs) However, right now I don't feel comfortable hard coding this like shown in the example below. What if we want to give TaskAdmin GET and POST permission and TaskUser only PUT permission?

Sample code from: https://github.com/Azure-Samples/ms-identity-javascript-react-tutorial/blob/main/5-AccessControl/1-call-api-roles/API/authConfig.js

 accessMatrix: {
        todolist: {
            path: '/todolist',
            methods: ['GET', 'POST', 'PUT', 'DELETE'],
            roles: ['TaskUser', 'TaskAdmin'],
        },
        dashboard: {
            path: '/dashboard',
            methods: ['GET'],
            roles: ['TaskAdmin'],
        },
    },

Thanks! We'll be in touch soon.

salman90 commented 1 year ago

Hi @kevinvugts , Thanks for reaching out. If you're implementing app roles for your own apps (API, SPA, WebApp...), you will need to code the permissions your users can access in your apps as shown in the sample. The app roles' purpose is to give the application developer power to customize authorization as they see fit.

If it's an Azure resource, you can utilize Azure AD roles for the recourses, and you can use a UI that can specify the permission based on the operation (GET, POST, DELETE, PUT).

Regarding the RouteGuards. If you don't want the roles hardcoded, you can keep them on a server and have the backend app fetch them for you. Unfortunately, there's no way around coding the logic you need to implement in the apps.

github-actions[bot] commented 1 year ago

This issue has not seen activity in 14 days. If your issue has not been resolved please leave a comment to keep this open. It will be closed in 7 days if it remains stale.

github-actions[bot] commented 1 year ago

This issue has been closed due to inactivity. If this has not been resolved please open a new issue. Thanks!

kevinvugts commented 1 year ago

Hi @kevinvugts , Thanks for reaching out. If you're implementing app roles for your own apps (API, SPA, WebApp...), you will need to code the permissions your users can access in your apps as shown in the sample. The app roles' purpose is to give the application developer power to customize authorization as they see fit.

If it's an Azure resource, you can utilize Azure AD roles for the recourses, and you can use a UI that can specify the permission based on the operation (GET, POST, DELETE, PUT).

Regarding the RouteGuards. If you don't want the roles hardcoded, you can keep them on a server and have the backend app fetch them for you. Unfortunately, there's no way around coding the logic you need to implement in the apps.

Hi @salman90

Thanks for your clarification and excuse me for my delayed response. Luckily we still have a bot the reminded me, haha.

I am going to try to integrate this as specified and closing this issue for now. Thanks again for your help and time.

Best Regards,

kevinvugts commented 1 year ago

@salman90

Regarding my query above, this is part of a bigger whole. I am building a platform a customer who wants to have the following flow.

In short the user navigates from a website to a subdomain called sso.customer.com which handles the authentication for the platform. It's basically the gateway to all. When the user navigates to the subdomain MSAL or another library (if you advice) will redirect to the login.

  1. When logged in the user will go through a couple of steps before it's granted access.
  2. When it's granted, it will have a screen with 3 options to navigate to: LMS, Community and tool
  3. Based on the selection it will be redirect to another subdomain where these subsystems are hosted
  4. It should share the same session like the one which was made in the sso.customer.com

Do you have any advice in how we can share the authentication session from sso.customername.com with the sub systems involved in the whole platform? Is this possible with MSAL / Azure AD? And is it even advisable?

I am looking forward to your response. Thanks in advance!

user-flow-globaal-Pagina-7 (1)

kevinvugts commented 1 year ago

@salman90 I see you haven't got back to my query above. If by any chance you got some spare time, could you please elaborate more on the above?

Thanks in advance!