Adding custom scopes programmatically to Azure B2C - azure

I'm evaluating Azure B2C but can't work out whether it will be fit for the following scenario:
We have a single UI and and a single Web API. The API has two scopes defined: read and write.
The UI has two types of users: standard and admin. When a user logs in and gets an access token they both get a read scope but only an admin user should get write.
From what I've read Azure B2C doesn't support group based application, but is it possible to hook in to the token generation (e.g. a Function) and add a custom scope programmatically? I was thinking that if I can call a Function then this could check something to see if they should have the write scope added.
Thanks

Scope o scp claims cannot be manipulated in B2C. However you can use custom policies and add (in a base policy) and output (in your relying party policy) a roles claim type so what your webapi do role base authorization (.NET core sample here). You can fill the roles values from the output claims provided by any technical profile which in turn relay on any configured Idp, AAD or even REST apis).

Related

Difference between an application role and scope in Azure AD app registrations

I have created an API that is protected by OAuth using an app registration in Azure.
My app registration does not require assignment, but it exposes a number of roles that the underlying API verifies. To my understanding, this accomplishes almost the same thing as requiring approval.
So far I've only had user/group roles but now I've added an application role intended for integrators, and I want other application owners to be able to request permission to my API. I, as the API owner, would like to review these and either reject or consent to the request. E.g. I don't want everyone to be able to access my API within the tenant without my knowledge, just like all users/groups don't have access with me assigning them to a role.
The Role-based access control for application developers documentation makes it very clear who manages access:
...an application developer defines roles rather than authorizing individual users or groups. An administrator can then assign roles to different users and groups to control who has access to content and functionality.
However, if you create a role with allowed member types set to application, things are not quite as clear and it seems to behave more like a scope, where I give up any access management. Also from my limited understanding, a scope is used when the API needs to request data from the user (e.g. wanting to read their username), whereas a role is used for the application developer to control access to what they are developing.
This is what it looks like when I request access to my API from another app:
This same page mentions the following information:
The "Admin consent required" column shows the default value for an organization. However, user consent can be customized per permission, user, or app. This column may not reflect the value in your organization, or in organizations where this app will be used.
As well as:
Applications are authorized to call APIs when they are granted permissions by users/admins as part of the consent process
However, from my reading, it sounds like this never gives me, as the API owner, any insight into who has access to the API I own. I want to control application access the same way I'd assign a group or user to a role in the enterprise application.
Can this be achieved when it's an application on the other end, not a user? If not, how would I allow applications to integrate in a controlled manner?
I want to explain the feature Azure ad provided to protect web api here.
As you know, we usually use a token in the request header to let the api check if the request had correct permission to visit the api. Such as if the request from an allowed user role, right? So to whole progress should be authentication and authorization. Users sign in first then try to generate an access token to visit an api. Azure AD has similar architecture.
If you had a web application(e.g. web mvc app) you can integrate Azure AD into it then you can allow users use their user1#xx.onmicrosoft.com account to sign in. If you had a web api project, you can also integrate Azure ad and add [Authorize] attribute above the controller so that the incoming request should contain a correct Bearer token which we call it access token.
For Azure AD, we usually have 2 options, verification scopes or app roles. That results from the different flows we used to generate the access token. For example, we use auth code flow to sign in users and generate access token containing scp claim which is granted delegated api permissions. And we use client credential flow to let an application to generate access token containg roles claim which representing it's granted application api permissions. In short, when we set [Authorize] + [RequiredScope(scopeRequiredByApi)] in the controller, it allows requests from a user(user sign in the app and call api), when we set [Authorize(Roles = "roleRequiredByApi")], it allows requests from the application(no user signed in and the app call api by itself).
Here scopeRequiredByApi and roleRequiredByApi is what you exposed and then added to App Registration > Permissions. Just like Integrator you marked in the screenshot, it can be recognized as roleRequiredByApi because its type is Application.
And I'm afraid the roles is not what you want but to be honest what I said is what AAD can do for you... And I think the document I mentioned above about verification scopes or app roles will be a good sample for you.
The App Registration > Permissions section has a great feature for reviewing and limiting the access provided for your app registration:
enter link description here
In addition you should always define the scope of your permissions and limit it to the least required for your app. eg. NEVER set scope at the subscription level! Always set it at the resource group or lower.
Also note that Microsoft now provides Defender for APIs and you can use Sentinel to monitor a lot of the activities related to your app registration. Always always enable logging wherever possible and configure some method of alerting/reporting so you can better understand the activities for your app.

Azure ADB2C access without a user

I am using an Azure ADB2C tenant to sign-up/in users with custom policies and rest api claims exchanges. This works fine.
Now I would like to start a service (daemon) that runs in a cloud environment for each user that signs-up with my service. This background service will access resources on other servers. Accessing these resources require a token and the service should only have access to the resources that the user has (i.e.: the access token used by the background service should also include the custom REST API claims). For the common users, this is taken care of by my REST API claims server, which enriches the token in such a way that it gives users' access only to the allowed resources.
I have found this page describing how to get access without a user. But this page assumes that the background service is a single instance that has access to all users' data that it needs. My background service is a 1-to-1 mapping to the signed up user.
Ideally this is how I see it working:
A new user signs up.
My REST API claims exchange gets called for this user.
Call Azure ADB2C to create a token for the background service. (Token should also contain my custom claims)
Start a new instance of the background service using the token created at step 3.
Return the custom claims for the new user.
This will happen for every new user, so every user in my system will have a corresponding background service running in the cloud.
Is this possible with Azure ADB2C? If yes, how?
The link you provide to get access without a user is only suitable for calling ms graph api and not for calling custom api.
If you are calling ms graph api, then you can indeed use the daemon-based client credential flow to obtain an access token (that is, without user involvement). This flow is usually used in Azure AD, but if it is used to call ms graph api, then it is also applicable to Azure AD B2C.
But if you are calling a custom api, then you must use a user login flow. Azure AD B2C obtains tokens in a different way from Azure AD. To use Azure AD B2C, you must first create a policy to enable users to sign up and sign in to your application.

Azure AD B2C - Multiple Identity Experience Framework custom policies can be used interchangibly

For multiple applications. we are using AAD B2C for our authentication system.
We have opted for custom policies. One of the reasons for this is that we want to allow different user groups to access different applications, in the following way:
superusers can access all Applications, including our CMS
product admins can access the customer facing CMS and the end product
product users can access the end product
For this, we have the policies:
B2C_1A_xxx_cms
B2C_1a_xxx_product
B2C_1A_xxx_customercms
In all policies, we do an API call to an internal authentication API, which validates the user's group memberships throught MS Graph API.
The problem is that these policies seem to be able to be used interchangibly:
https://{tenant}.b2clogin.com/{tenant}/b2c_1a_xxx_cms/oauth2/v2.0/authorize?response_type=id_token&scope={scope}%20openid%20profile&client_id={client_id}&redirect_uri={redirect_uri}&nonce={nonce}&client_info=1&x-client-SKU=MSAL.JS&x-client-Ver=1.4.4&client-request-id={client-request-id}&response_mode=fragment
In the above url, users can access the CMS by replacing b2c_1a_xxx_cms with b2c_1a_xxx_product, thus bypassing the group-based validation in place for the specific application.
The original implementation of our policies are based on this tutorial:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/custom-policy-get-started
How can we configure these policies in such a way that changing the URL and trying to log in is impossible?
Based on your requirement, I think you need a the application assignment to users feature.
But it is only available in Azure AD rather than Azure B2C.
So I suggest that you use custom attribute to control the access of the user for different applications.
“ we do an API call to an internal authentication API, which validates the user's group memberships throught MS Graph API. ”
When User A calls Policy B, this API should return back a claim into the journey that prevents it from issuing a JWT. That can be achieved by creating a “block page” using a self asserted technical profile. Call this from the orchestration step using this claim from the API to trigger it with a precondition.

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.

Add claims into token Azure B2C

What are ways to include custom claims (user subscriptions or roles list as example) in a token before issuing it in Azure AD B2C, provided that claims are stored somewhere on own server (not available in B2C)?
Goal to have claims in the token to avoid additional round trip to the storage on every request.
Investigation on the topic brought me to following ways:
Add custom attribute via Graph API, configure to include in JWT. Attribute values should be kept in sync with our datastorage.
Custom Sign-In Policy like in this article https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-rest-api-step-custom but if I got it right, additional Step 6 is a user journey to publicly available API in non restricted way (request not secured by secret, might be used to get user claims by presented UserId)?
IdentityServer4 Federation gateway http://docs.identityserver.io/en/release/topics/federation_gateway.html that will allow to add any claims before issuing.
The first two mechanisms you outlined are the most common and recommended ways to include custom claims in an Azure AD B2C issued token:
Add a custom attribute and include it in the JWT. You can enable the custom attribute via the B2C UI or via the Graph API. You'd need to build your own mechanism to keep the value of this attribute in B2C in sync with your external source via the Graph API.
You can use a custom policy to add a step in your authentication flow to call a Rest API to obtain the claim and include it in the token. This call to the Rest API will be performed by the Azure AD B2C service and NOT the user's browser, so it'll be a service-to-service call (versus a client-to-service call), keeping any secrets you use for authentication with your Rest API safe (such as a Azure function code).

Resources