TL:DR;
Details. We are in the process of integrating AAD SSO into a web app that has a React SPA front-end and an ASP.NET Core back-end API. We are using the Microsoft Identity platform for the authentication piece and are handling the authorization ourselves.
The problem is, we are having trouble figuring out which authorization code flow is most appropriate to use, as we are using both a SPA and web API in our app stack.
From all my research, I'm thinking that we need to register two apps in AAD - one for the SPA and the other for the web API, then set up each according to their respective docs.
I think what's adding to the confusion is that we're unclear what communication needs to take place between the SPA and the API to ensure that the user is properly authenticated on both sides. We are used to a more traditional implementation, where the user has a session cookie and sends a bearer token to the back-end, which is then validated against the SSO authority. In this case it appears that we will have two separate authentication contexts for the same user which won't be aware of each other (though the SSO authority should know the user state and info, and perhaps that is the answer).
Secondly, we are not sure if we need to set up any scopes in Azure, as we understand scopes to essentially be user permissions, which can be used to lock down the API to varying degrees based on user role. However, we are managing this ourselves by setting up user permissions and roles in our own database and using business logic to filter out what data is available to which users. Every article and post we've read seems to assume that we will be using AAD scopes for this, which makes us wonder if there needs to be at least one present for everything to work.
We did try setting up both the SPA and the API to use the Microsoft ID Platform authentication, but along the way got confused as to how the two sides would actually communicate with each other, if we needed multiple clients registered in AAD, and if setting up both was overkill or the right path.
Any help would be appreciated. Thanks in advance!
First of all, we have official sample here for guiding us how to integrate AAD authentication and authorization into React client app and asp.net core webapi backend.
The whole process should be, in the client app, we integrated MSAL so that we could sign in the app with microsoft account, then we can use this library to generate access token with different scopes. Here we are using the auth code flow which doesn't require us to handle the auth code manually, the library already done for us. In all of the flows from Azure AD, auth code flow is only recommended flow for users to use username + password to sign in(ROPC flow is not recommended). So we don't have any other options indeed. The next is calling API which is authorization. The API should validate the access token, to see if the token had enough permission and if its expired or not, but not including user roles
here. That's because access token doesn't contain a claim which is indicating the user role. The access token do have a property named roles but it's used to checking application role when the token is generated by client credential flow. Only id token contained user role claim but it's not used for authorization. If you want to check the user role, you can only do it before generating the access token. SSO is for user sign in but just like you know, web API project is a daemon app which doesn't have user to sign in.
So the next we need to have an Azure AD app which is used in your react app to integrate user sign in by microsoft identity platform. I trust you already did this. Then what we need to do can be called as protect web api by aad. We need to expose an Azure AD API and assign this API in API permission blade in Azure portal of an Azure AD app. Here we can use the app which is used in react app, we can also create a new AAD app, it doesn't matter, the important thing is exposing the API and assign it to the app. Let's say we create a new AAD app then already exposed the API permission named my_api_access
. Then we should go to the first AAD app -> API permission blade -> add API permission -> choose My API tab -> find my_api_access and add it. Now in our react app, we can set the API scope as api://aad_client_id_of_the_second_app/my_api_access
and generate an access token, if we decode the token, we should see it contains claim similar to scp: my_api_access
and that means the token is correct.
In our web api project, we need to add configurations as well then it will reject all the requests which don't have correct access token in Authoriaztion: Bearer {token}
request header.
I'm not an react expert here so I can only share a sample I write before with old version libraries. But they should be similar with latest version.