What is the best way to obtain a Microsoft Graph API token through an Azure B2C logged in user so to act upon the users context - azure

From the documentation it seems that using an application that is in the B2C tenant and thus hosts user accounts that there is no way to directly access Microsoft Graph API via a logged in user per their own context.
I want to establish the use case properly so that the solution is that which makes the most sense.
The use case is that if a user wants to edit claims for example such as permissions they would be able to do so while logged in through Azure B2C.
The flow would be. Logged in user -> can change certain claims information such as address, surname, and other custom policy fields (SEO contact permissions.)
Is the proper way to do this is to build a proxy that will take the application's AD application permissions which are allowed to call out to Microsoft Graph and pass along user context so that the scope will be limited to that user only?
For example. User logs into the app.
The app has AD permissions that are granted admin consent
Create a client secret to prove application identity upon request of a token
Now can access Microsoft Graph api
Ref of Registering an app with Microsoft Graph api
What's not clear here exactly is the next part. My user is logged in with Azure B2C. Should I just pass along their id token which has their claims to the application? How do I put in scope/context of the logged in user of the app permissioned access to Microsoft Graph?
This part is not clear in any documentation.
I don't want a logged in user to have access to everything.
Is a proxy the only way to do this?
If a proxy is the only way to do this what identifier or id is what should be used to pass along to the query to assure only that user is in context?
Am I thinking of this incorrectly and or is there a better way to do this other than a proxy?
The documentation says this.
Apps that have a signed-in user but also call Microsoft Graph with their own identity. For example, to use functionality that requires more elevated privileges than the user has.
That doesn't fit exactly into my use case above or address it really but I think it is related. The functionality should be considered to be an elevated permission but to the scope of the user. This user can change this claim via their own logged in entity. What do you call that and what is the best way to solution this?
Lastly, is there anything that should be known in the MSAL library including Angular and React that would be useful in this process? It seems like I will have to converge the 2 to obtain the access token of the app and of the person and proxy those out to a backend service (the proxy) to then do a body of work.
Am I thinking of this correctly?
This Stack is the closest to relevance but doesn't ask or solution the entire use case as I have here. But is useful for illustrating the confusion.

"Logged in user -> can change certain claims information such as address, surname, and other custom policy fields (SEO contact permissions.)"
Why can't you use the Profile Edit user flow? You can configure what attributes the user can change.

Related

Azure AD B2C personalised content after login

I'm building a web app (SPA) that is a case management system. Each user (mainly external to organisation) has a case on the system. I've been told by an architect we should be able to use Azure AD B2C to allow the users to login on this so I've been investigating this.
From what I can see I will get a token back from B2C saying the user is authenticated. What I don't understand is what use is that? Ok the user is authenticated but I have no idea who they are i.e. I will need to identify their case ref somehow so I can bring back their details...
If i was doing this in the old days when they login they'd be checked against a user table then their ID would be used to get their case details .. a token and data object would be returned from an api.. job done
I don't see how this would work in Azure AD B2C... am i missing something?
The JWT that is returned contains a configurable set of claims.
You can use these to identify the user. Typically, this would be email or UPN.
In your case, you need a userID. If this isn't one of the supported attributes, you can use an extension attribute to store it.
B2C can also call an API (if you use custom policies) so you could call an API to get the userID from e.g. a table and then return it as an extension attribute in the JWT.

Want to understand OAuth Code flow where Application passes the Access_Token on user's behalf to the API to get the resources

I like to know my understanding is correct and also like to clarify my doubts further.
1) Confirm my Understanding:
In the below image, I have explained my understanding of protecting the application and api using Azure AD. I have exposed the API with the SCOPE and the Application has consumed the same through the permission module.
Can someone please confirm my understanding is correct?
2) Should we pass Role in ACCESS_TOKEN?
This is where I require someone to help me. This is a code flow where the User login into the Application and while he tries to get the Todo list, an application sends a request to the API.
In this communication, an application gets the ACCESS_TOKEN for the login-in user and passes it to the request going to the API.
At the API side, we have the policy where it checks the Scope coming through IHttpContextAccessor.HttpContext.User.Identity and make sure the Claim has scp/scope and it has the right value.
Now, all are going well. The questions here are:
Should we not have Role (User's role) in the ACCESS_TOKEN? (When I said Role - I mean User's role not Application's role)
following the link at Microsoft documentation I am getting the role in claim when user login to the Application but to call the API I have to use ACCESS_TOKEN which I am getting through TokenAcquisition.GetAccessTokenForUserAsync and it doesn't include Role. It includes SUB, userPreferedName, email and Scope kind of detail (have checked in jwt.io)
If the answer of Question #1 is "NO, we should not" what is the way for API to check the user's role and give the result? Is that something we need to stuff in SCOPE only?
REF: https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-add-app-roles-in-azure-ad-apps
To give better context, I have added my Azure Configuration as well here.
Confirm my Understanding:
Based on your screenshot, your understanding is basically accurate.
Microsoft identity platform issues you an access token after you sign in, and then you use this access token to call your web API. The API will validate the access token and the permissions / roles, which determines whether you can access its data.
This Protocol diagram is clearer for your understanding.
Should we pass Role in ACCESS_TOKEN?
Firstly, the link you shared is related to Application Roles. But you are not talking about that. What you are talking about is the AAD role (eg. Global admin, Group admin). Correct me if there is any understanding.
Honestly, AAD role should not be included in the access token because it's meaningless. To access your web API, you should define your own roles to control the permissions of users. AAD roles only work when you try to perform AAD or Microsoft Graph operations.
If the answer of Question #1 is "NO, we should not" what is the way
for API to check the user's role and give the result?
You have found the correct guide: Add app roles to your application and receive them in the token.
You should use Application Roles. Define the User app role in the Azure AD app which represents your API and assign your users to the role. Then your API can check the user's role by verifying scopes and app roles.
There is another method to control the user's role: using Group Claims which is also mentioned in the link you shared. The detailed steps are listed here.

Synchronize AD user groups with backend service

I am not sure if the question is descriptive enough for what i am trying to accomplish so let me try to elaborate. Because even i am not sure how to properly set the question. So i will tell more about the big picture of what i am trying to do.
I am building an application that uses AWS Cognito for user authentication and authorization. But authorization part is in a way not directly done via Cognito (more about it a bit later)
In Cognito i added as a third part identity provider Azure AD via OIDC. I also have backend service that will hold user's roles in its own database. Now, for users that are going to be added to user pool via AD i need to replicate their groups in AD as a role in my service database. (So if i have a user in AD that is part of the group ADMIN I need to get that group and put it in my own db as a role for that specific user).
Now the idea is to use MS Graph for syncing groups with roles in my service. But the point is that then i would need credentials of the AD user that has the rights to see that info in AD. Which is not really what i am trying to accomplish.
My guess is that this can be done in all at once scenario (which would require the "GODs" user in AD credentials, which is not an option), or one by one (as they login to Cognito via AD as Idp).
So to sum it up, my question is can i integrate the call to MS Graph when user logs in with its ad (microsoft) credentials, that in a way i get the info about his group when he tries to log in to Cognito userpool?
I understand that this probably is very unclear, but i am not quite sure how to put it in a simple way.
If anyone can help me out, i would appreciate it.
Thanks
You don't need to integrate the call to MS Graph.
Just include Groups claim in your token as instructed here. You just need to modify the "groupMembershipClaims" field in application manifest:
"groupMembershipClaims": "SecurityGroup"
Then the token will contain the Ids of the groups that the use belongs to like below :
{
"groups": ["{group id}"]
}

Authentication vs Authorization?

I'm new to Azure ADB2C, and am confused by some of the terminology.
I am building a motorcycle ride monitoring website that I would like users to be able to log in to by verifying a social media identity (Google & Microsoft Account, for now).
But I only want users who are members of the site to be able to use certain features. For example, I'd like everyone who authenticates to be able to apply for membership, read about the benefits of membership, etc., but I only want members to be able to initiate ride monitoring.
Is the recommended approach here to only authorize (rather than authenticate, if I'm understanding the terminology correctly) certain authenticated users (i.e., members) to use the ride monitoring services?
If so, what's the best way to authorize a member? Look up their email (which I require to be returned from the authentication process) in a standalone database and proceed accordingly? If I go that way, what's the simplest way of adding their membership status to their credential, so I can access it throughout the site?
Apologies for not providing code here. I've got a bit of it hanging around :) but this is more of a design question than a coding one.
Azure AD B2C is primarily Authentication as a Service. There are ways in which it can be used for what you are trying to achieve here.
You can use custom (extension) attributes in AADB2C (https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-custom-attr) in combination with AAD Graph apis (https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet). So when user authenticates and applies for membership, you can call AAD graph api to set the custom attribute on user object. You can get the extension attribute in a the token after the authentication happens. This token will give you membership of the user.
You can also use AAD Groups instead of custom attributes. In the tenant, create membership groups. Once user authenticates, call AADGraph to set/get user's membership of a group and that will give the authorization information.
You can also do what you described, maintaining the info in a database store of your application. But the first two functionalities provide in-built functionalities for user management.

What use are 'Scopes' in Azure B2C Authentication?

I don't understand how the 'Scopes' in Azure B2C are supposed to be used. They are associated with an API, but not a user. I'm sure I'm missing something, but I see no practical use for something associated with an API. I've used and implemented Claims-based authentication based on a user's role in the database.
For example: ordinary users of an API should not have the authority to delete an object, but administrators should have the authority. Does someone have a practical example of how these B2C 'Scopes' can be used to limit a users access to the API?
They are associated with an API, but not a user.
That is correct. I like to think of the association to the API as defining the 'surface area' of the API. For example, this API defines 2 scopes
read
write
Now, you could define two applications. One application that only has read permissions and one that has read and write permissions.
For the common use case of one Web App and one Web API it adds no value. I've been using a scope of no-op for such cases.
I've used and implemented Claims-based authentication based on a user's role in the database
You can use custom attributes to assign "role(s)" to the user. You can set them via the Azure AD Graph API to keep the setting of them secure. You can also set them during sign-up (this is much more involved though).
When you request an access token for that user, the custom attirbute(s) you defined and set will be readable in the API to check permission(s).
Comment Feedback
If I promote or demote a user, I need to change the endpoints (policies) they access at the client.
No need to change the policies. You would update the custom attribute for that user via the Azure AD Graph API.
My problem is that I'm mystified at the an authentication system that authorizes endpoints ("scopes") instead of users
Yeah, me too! I think it might have to do w/ the purpose of the product. B2C is about self-service sign-up, password reset and federating w/ other IDPs (like FB, Google, etc). Maybe Azure AD is a better solution when you want to control permissions on a user. Not sure, still learning!
I still don't see the practicality of splitting your API into several different parts based on the security. An API should be a collection of functionally related services
You don't split your API. You can split your app(s) that utilize the API. See above.
Documentation Reference: Requesting access tokens, GitHub Issue to improve the documentation.
Roles and scopes provide the two halves for this user access control.
Roles -- such as Administrator, Member, and Guest -- determine whether an authenticated user is permitted to delete objects.
Scopes -- such as read, write, and delete -- determine whether an authorized application can delete objects on behalf of an authorizing/consenting user if this user, through their role assignment/s, is permitted to do so.
Azure AD B2C doesn't have any current support for managing roles and assignments of them to users.
It does, however, have support for managing scopes and assignments of them to applications.

Resources