Azure / static-web-apps

Azure Static Web Apps. For bugs and feature requests, please create an issue in this repo. For community discussions, latest updates, kindly refer to the Discussions Tab. To know what's new in Static Web Apps, visit https://aka.ms/swa/ThisMonth
https://aka.ms/swa
MIT License
322 stars 54 forks source link

[QUESTION] How to take custom roles on UI with custom auth by AAD? #525

Open yzapara opened 3 years ago

yzapara commented 3 years ago

Hi,

I'm using SWA with custom auth by AAD. AAD configured to have custom appRoles for the users.

"auth": { "identityProviders": { "azureActiveDirectory": { "registration": { "openIdIssuer": "https://login.microsoftonline.com/278XXXX27/v2.0", "clientId": "a5eXXXX5ca", "clientSecretSettingName": "ClientSecretSetting" } } }

Wasn't able to configure custom user attribute "userRoles" to have roles like they are supported in OOTB SWA auth approach. So after succesfull login .auth/me returns only standart predefined userRoles for any account "userRoles": [ "authenticated", "anonymous" ]

After succesfull login I retrieve id_token in request to ... /auth/login/aad/callback

image

AAD has several custom Roles which can be encoded from the id_token like this: "roles": [ "Admin", "AppUser" ],

How to set up AD to support userRoles in SWA style? Or are there any way to catch id_token in JS code for further encoding to get appRoles?

Thanks

mkarmark commented 3 years ago

Hi, we currently don't have support for AAD roles in the SWA environment; however, that is something we are working on bringing to Azure Static Web Apps in the future!

AverageCakeSlice commented 3 years ago

Hey @mkarmark, is there anywhere we can see what features are in progress/on the backlog/etc? I'm really interested in this feature as well as it feels like securing the managed API with a custom provider is a lot more complex than it needs to be because of this issue. Is there something like a Trello board or Github Projects board that's publicly visible?

karthikbhyresh commented 3 years ago

I have created an Azure Static Website and followed the instructions on how to add a basic Azure Authentication identity provider. I have a custom auth section and added groups to the ID Token. Now how to tell the auth process to include the group details in the claim that is returned by making a http request to /.auth/me following a successful authentication

anthonychu commented 2 years ago

We released a feature to programmatically assign roles with a function. Within the function, you have access to the token from the IdP. See the documentation for more details. There's also a tutorial with a sample app that calls Microsoft Graph to map AAD group membership to Static Web Apps roles. You should be able to do this with appRoles too.

Currently you can use this function to assign roles. If you'd like to also store claims that you can access in the /.auth/me endpoint or in the user principal in a function app, let us know.

bartusz01 commented 2 years ago

LGTM, managed to authorize users from specific AAD groups only on my SWA.

johschmidt42 commented 11 months ago

Adding to that @anthonychu, instead of using AAD groups to define roles as in the provided tutorial, it is much simpler with appRoles. These can be extracted from the bodies claims property within the roles endpoint that needs to be configured in the staticwebapp.config.json with rolesSource.

Here's a minimal example with fastAPI (Python) running in a Azure web app linux container:

# staticwebapp.config.json
{
  "auth": {
    "rolesSource": "/api/GetRoles",
    "identityProviders": {
      "azureActiveDirectory": {
        "registration": {
          "openIdIssuer": "https://login.microsoftonline.com/<TENANT_ID>/v2.0",
          "clientIdSettingName": "AZURE_CLIENT_ID",
          "clientSecretSettingName": "AZURE_CLIENT_SECRET"
        }
      }
    }
  }
}
@app.post(path="/api/GetRoles", status_code=status.HTTP_200_OK)
async def extract_roles(request: Request) -> dict:
    body: dict = await request.json()
    identity_provider: str = body["identityProvider"]
    user_id: str = body["userId"]
    claims: dict = body["claims"]

    role_claim_schema: str = (
        "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
    )

    roles: List[str] = [
        claim["val"] for claim in claims if claim["typ"] == role_claim_schema
    ]

    print(f"Body: {body}")

    print(
        f"Adding roles: {roles} "
        f"to the user: {user_id} "
        f"from the identity provider: {identity_provider}"
    )
    return {"roles": roles}

Bummer that there is no built-in functionality from SWA to do this mapping. Are there any plans to provide such a feature?