I feel like I may be going a little mad here.
I have basic architecture that features a frontend react app (SPA Auth) which communicates with a backend GraphQL Nodejs API service (Protected Web API Auth), hosted in Azure and authenticating with Azure AD.
- Frontend access token requires User.Read access to azure graph, and access to Backend exposed scope
- Backend exposes an API and single scope for access
- Backend also requires User.Read access to azure graph on behalf of the user
I have been trying to configure the authentication to use the On-Behalf-Of Flow.
- The react app successfully retrieves an access token using it's own app registration details
- The access token is supplied to the backend service with each GraphQL request
- The backend service verifies the access token provided to it
- The backend service requests it's own access token via the On-Behalf-Of grant_type
urn:ietf:params:oauth:grant-type:jwt-bearer
This all works EXCEPT I cannot get past this issue -
The user or administrator has not consented to use the application with ID '9b56c153-be42-499a-a41a-20176ed2ce69' named 'service-cbcity-api'. Send an interactive authorization request for this user and resource.
Basically I have not been able to successfully configure the app registrations and token requests to ensure that when the backend requests it's token it is allowed to call User.Read on behalf of the originally authenticated user.
In the On-Behalf-Of documentation it states the following regarding using /.default
scope -
/.default and combined consent
The middle tier application adds the client to the known client applications list in its manifest, and then the client can trigger a combined consent flow for both itself and the middle tier application. On the Microsoft identity platform endpoint, this is done using the /.default scope. When triggering a consent screen using known client applications and /.default, the consent screen will show permissions for both the client to the middle tier API, and also request whatever permissions are required by the middle-tier API. The user provides consent for both applications, and then the OBO flow works.
I have tried all sorts of combinations of configuration in the App Registrations as well as different combinations of scope requests and I simply cannot get this to function as expected; the prompt doesn't seem to include the combined consent. The only way I have gotten it to function is by manually providing admin consent to the Backend app for User.Read, this just seems like a hack and I would prefer to correctly configure this to ask for users consent.
If anyone has configured something similar before (seems like an expected use case) please let me know how you got it working, including configuration like
- App registration config for Frontend service (eg api permissions set)
- App registration config for Backend service (eg exposed scope, api permissions, authorized client applications)
- Scopes requested on various auth requests
At this stage I am going to have to revert to possibly using the one App Registration and sharing the same access token between frontend and backend, even though personally this seems like a poorer solution to me.