In Keycloak, basing a permission on a custom user attribute - security

I am looking into using Keycloak to give some users special permissions.
The permissions will need to have a limited validity.
My current idea is to set special user attributes, for example ALLOW_PERIOD_1='2022-01-01:2022-02-01' and ALLOW_PERIOD_2='2023-01-01:2023-02-01'
We will add a mapper to add claims based on the user attributes.
In the application the claims in the token will be checked and allowing this user only access in January 2022 or 2023.
I have 2 questions about this:
Is this the right way to manage temporary access per user?
Perhaps there is a simpler way to achieve the same.
Is this secure?
Can a user set its own custom attributes via the Keycloak pages?
For example, we have added the custom attribute middleName to our registration page by simply adding a form-variable "user.attributes.middleName" to the registration form.
Can any user add "user.attributes.ALLOW_PERIOD_1=2022-01-01:2030-01-01" to a POST to one of the keycloak pages and give himeself access?
Thanks for any advice,
Rob

Related

How to set information to Azure AD B2C users after registration?

In my application I have the following scenario:
Users first register in the application Using SignUp-SignIn user flow, so at that point the user is created in Azure AD B2C. Then when the users starts to use the application I want to add some information to the user and retrieve it in the token during the next authorizations.
The information I want to add to the user is the following:
1- Identifier I use in my database to store data related to that created user
2- Some application role (e.g. customer, shop owner...) - here, it would be great if I can prevent users to make requests based on that role, but not a big deal to check it in the code after the request is executed
The idea I have is to use Graph API and assign this data in a custom attribute to the users, so this data is always managed by the API and user can't change it himself.
Then I am thinking if mixing that approach with groups could be also and option so some requests will be only available for users that belong to some group.
What is the best approach to achieve my requirements?
Out-of-the-box AAD B2C SignUp-SignIn user flow does not expose any functionality related to Security Groups.
If you want to use group claims in B2C, choose to add some custom code through custom (IEF) policies. See this answer and this post.
In order to achieve your requirements, you could use custom attribute which you have mentioned.
Please note that if you don't want the user to set the custom attribute by themselves, you don't need to do this 3rd step under "Use a custom attribute in your user flow":
Select User attributes and then select the custom attribute (for example, "ShoeSize"). Click Save.
After you create the custom attribute, you can Get the application properties and Using custom attribute with MS Graph API.
Update the custom attribute for a user with Microsoft Graph:
PATCH https://graph.microsoft.com/v1.0/users/userID
{"extension_831374b3bd5041bfaa54263ec9e050fc_ShoeSize": "123"}
Then you can get the custom attribute claim in token like this: "extension_ShoeSize": "123".

AAD B2C - Is a user authorized to change their own custom attributes?

I want to use custom attributes in AAD B2C as a shortcut for authorization. I would love to set values on users that I can use in my apis to know what they have access to do.
I see that I can create a User flow for a user to edit their own attributes, but that is the opposite of what I want.
If I don't create a user flow to edit the attribute, can I be confident that the user can't edit it on their own through Microsoft Graph or something like that? I tried doing it through graph but I can't tell if I did something wrong or if the user is not allowed to change it.
It is better not to depend on User attributes for authorization. As user profile information (user attributes)can be managed by the user self or organization level.
I don't think users can adjust their own attributes if they don't have the graph permissions in Azure. When signing in your users within your application you can allow them to access certain scopes. As long as they cant access these scopes they cannot perform any actions on the graph API. Updating user details would in this case require 'User.ReadWrite' scope assigned.

Azure AD B2C Custom Edit profile page

I'm working with Azure B2C from a MVC (4.6) WebApp. I've followed this guide to make it work and it's all good:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-web-dotnet
However, regarding the Edit Profile Policy, I need custom values coming from another system for a specific User profile property (i.e: Favorite Categories, coming from a custom Categories table). I don't want to add all the possible categories to the User profile property settings in the Azure portal, cos values can change frequently. So, couple of questions:
1- Is there a way to tell Azure AD B2C Edit profile policy, what are the values to use for a specific user profile property? (I don't think so)
2- Can I call the Edit Profile policy Endpoint to update the user profile? that way, I'd have a custom page with the user profile properties, and I will update the user from code. I've "fiddled" the MS page, and it's doing a post to a specific endpoint, but I'm not able to make it work from code. I've also tried a bunch of different things.
The only approach that seems will work is to call the Graph API from code, following this article (but it requires to register another App from PowerShell, and also, execute the action with an App Token, instead of the current logged user):
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet
Any help would be very appreciate it.
Thanks a lot.
1- Is there a way to tell Azure AD B2C Edit profile policy, what are the values to use for a specific user profile property? (I don't think so)
No. All the users use the policy you config on the portal. We can create multiple profile edit policy and choose the right policy based on you business with custom code.
2- Can I call the Edit Profile policy Endpoint to update the user profile? that way, I'd have a custom page with the user profile properties, and I will update the user from code. I've "fiddled" the MS page, and it's doing a post to a specific endpoint, but I'm not able to make it work from code. I've also tried a bunch of different things.
No. It is impossible. As you mentioned, if you want to update the users profile programatically, the Azure AD Graph is recommend.
you not able use JS, but you able customize with css;
(enable cors to ms login domain on your web app etc)
see msdm docs all are desribed;
you able add custom properties in AD B2C to user sign up; so to edit profile should be possible too;
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-reference-ui-customization

What's a good way to have ordinary-user segregation but admin-user access to the same pages?

I'm using ASP.NET MVC 5 and ASP.NET Identity. I have a site with multiple users, who should only see their own data. The ordinary users access the site via URLs such as "/orders", "/orders/edit/1" etc.
I also have some "admin" users, who should be able to access all the same stuff that ordinary users see, except that they can view the data for all users. What I want to do is allow them to "impersonate" a user, and see what that user sees. So, they might access the site via URLs such as "/user-foo/orders", "/user-foo/orders/edit/1", etc.
Currently, my controllers have two variants of each action: one with a user id parameter (for admin users) and one without (for ordinary users). In the latter case, the id of the logged-in user is used. Both of these then call some shared code to render the view.
However, when rendering the view, I need to ensure that any embedded links (e.g. to an order detail page) use the correct routing form (with/without user id). That means I need to constantly check whether the user is an admin, etc. Is there a better way to do this?
I would use the claims that are available in ASP.NET Identity. Just add a claim for the impersonated user ID that will only be used if the user is an administrator. The roles are probably already in the claims. You do not need the action that passes the ID, instead add some logic that looks at the claims to see if the person is an administrator. If they are an administrator and there is a claim containing the impersonated ID then use it instead of the logged in users ID.
Here is an article that shows how to use claims with ASP.NET Identity. This shows how to set the claims during the log-in process. If you need to add a claim after the log-in process just use the SignIn method again, like this.
var AuthenticationManager = System.Web.HttpContext.Current.GetOwinContext().Authentication;
var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
prinicipal.AddClaim(new Claim(MyClaimTypes.ImpersonatedUserId, impersonatedUserId));
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = persistCookie }, principal);
I normally provide the same structure for both, but with an Authorize attribute with a role specified if i am blocking access by a certain role type. Alternatively you can check the controllers User property to find out the logged on user and perform your own logic to determine what data that user has access to view.

Place to store user settings in Sharepoint besides profiles

Is user profiles an appropriate place to store things like number of items per page in a custom grid user selected? (I you can store it in the view, but it won't be per user this way).
My first though was to store these settings in user profiles, but there are problems with access permissions for programmatically creating user profile properties boiling down to you either have to give every user 'Manager User Profiles' permission in SSP or you have to run the application pool under a domain user, not NETWORK SERVICE. Both scenarios are unrealistic for me, so I'm now looking for another way to store such 'per user' settings.
Thanks!
Edit: I'm now considering ASP.NET profile mechanism with an additional DB to store user properties.
Given that the information is not sensitive a simple database with values stored against AD login should suffice.
And as you have the ASP.Net user database already, storing the information there would be the best option.
Maybe a Global List, that is only accessible for the SHAREPOINT\SYSTEM User and that you can then Query in a SPSecurity.RunWithElevatedPrivileges Function.
Disadvantage: You require Custom code to read/write to that list.
Cookie?
Sure they have limitations, but it is fairly easy to create the control to run javascript to add/edit the value

Resources