Add permissions base on roles of group in keycloak - mapping

I first set my application base on Auth0, with roles and permissions setup. Result user are linked with x roles, and Auth0 inject to the token claim an array of linked permissions. Now my app need to become also compatible to use KeyCloak.
How to inject into the token the permissions array, like with Auth0?

To match same beaver of Auth0, on keycloak all the auth0-roles are set as group. And all auth0-permission as roles.
Now to allow to inject into the token the related roles of groups linked with a user, I created a Script Mapper in the client like this:
var ArrayList = Java.type("java.util.ArrayList");
var permissions = new ArrayList();
user.getGroups().forEach(function(groupModel) {
groupModel.getRoleMappings().forEach(function(roleModel) {
var roleName = roleModel.getName();
if(!permissions.contains(roleName)) {
permissions.add(roleName);
}
});
});
token.setOtherClaims("permissions", permissions);
Take me time to find the best way to make it working. But if you know a better solution. Thank you for sharing ;-)

Related

Setting up new default Roles in jhipster

How can I set up default roles in jhipster ? (using angularjs and spring).
I explain myself
in the registration page I want to specify the role for the registred user. let's say by a checkbox or a list. (for exemple human and animal )
How can I do that in the angular controller and in spring ?
What I can do now ?
I added the roles I need in the database and in angular and I can specify the roles for the new registred users , only through the Admin's users management page.
There is some work to do, to achieve that, so I will paste just the right parts with some small samples..
In general you must extend the API to become aware of a role selection, so this information can be provided explicitly. Then you change your angularJS frontend as you need.
for the backend
a registration happens by POSTing a ManagedUserVM to /api/account/register, so the first thing is to tell AccountResource.registerAccount(...) to pass a set of of strings (your roles) as additional parameter to userService.createUser
#Timed
public ResponseEntity registerAccount(#Valid #RequestBody ManagedUserVM managedUserVM) {
HttpHeaders textPlainHeaders = new HttpHeaders();
///...
User user = userService
.createUser(managedUserVM.getLogin(),
managedUserVM.getPassword(),
managedUserVM.getFirstName(),
managedUserVM.getLastName(),
managedUserVM.getEmail().toLowerCase(),
managedUserVM.getImageUrl(),
managedUserVM.getLangKey(),
//add authorities here
managedUserVM.getAuthorities()
);
mailService.sendActivationEmail(user);
//...
}
Then in UserService.createUser, you apply the set and add them to the user before saving it, by adding the Set<String> authorities to its parameters and
if (authorities != null) {
Set<Authority> authorities = new HashSet<>();
authorities.forEach(
authority -> authorities.add(authorityRepository.findOne(authority))
);
user.setAuthorities(authorities);
}
and this should be sufficient to pass authorities to /api/register/ and save them. You should be aware of users forbid to register themselves with ADMIN roles, but the security consideration is up to you and not part my answer.
apply to frontend
Knowing your API now can process also authorities, you could just pass them.
You just add some checkbox or selectbox with ng-model="vm.registerAccount.authorities" to src/main/webapp/app/account/register/register.html (if angularJS1) or
[(ngModel)]="registerAccount.authorities" tosrc/main/webapp/app/account/register/register.component.html` (if angular2).
AFAIK this should lead automatically to the angular services passing these authorities/roles to the API.
I hope my brief answer helps you to find the proper places! Feel free to ask in comments if you stuck

Different between api scope and user claim in identityserver4

i am reading the identityserver4 guildence, here is the example code
UserClaims =
{
new UserClaim(JwtClaimTypes.Name),
new UserClaim(JwtClaimTypes.Email)
},
// this API defines two scopes
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2",
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
my questions is
seems the scope is used to control which client can access the api resources, and user claims controler the user permission on apis. let's take a look at "api2.read_only", does this mean client with this scope can only have the read access to the apis? but what if the user has for example: write access for a speicific api? i get confuse about the these two.
thanks in advance for your help.
Scopes defines whether you have access to the API or not. Where as Claims are more granular. Within the API, what resource you can access? for example, you can access identity resource like name.
Scopes are special claims which define what resources a client can have access to.
User claims are just assertions about a user. You would normally give a user a "role" or "permission" claim (or something like that). By using the user claims you can do some claims authorization if doing authorization based on scopes does not satisfy your requirements.

Best Practices for Roles vs. Claims in ASP.NET Identity

I am completely new to the use of claims in ASP.NETIdentity and want to get an idea of best practices in the use of Roles and/or Claims.
After all this reading, I still have questions like...
Q: Do we no longer use Roles?
Q: If so, why are Roles still offered?
Q: Should we only use Claims?
Q: Should we use Roles & Claims together?
My initial thought is that we "should" use them together. I see Claims as sub-categories to the Roles they support.
FOR EXAMPLE:
Role: Accounting
Claims: CanUpdateLedger, CanOnlyReadLedger, CanDeleteFromLedger
Q: Are they intended to be mutually exclusive?
Q: Or is it better to go Claims ONLY and "fully-qualify" you claims?
Q: So what are the best practices here?
EXAMPLE: Using Roles & Claims Together
Of course, you would have to write your own Attribute logic for this...
[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
EXAMPLE: Fully-Qualifying Your Claims
[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here
return View();
}
A role is a symbolic category that collects together users who share the same levels of security privileges. Role-based authorization requires first identifying the user, then ascertaining the roles to which the user is assigned, and finally comparing those roles to the roles that are authorized to access a resource.
In contrast, a claim is not group based, rather it is identity based.
from Microsoft documentation:
When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is a name value pair that represents what the subject is, not what the subject can do.
A security check can later determine the right to access a resource based on the value of one or more claims.
You can use both in concert, or use one type in some situations and the other in other situations. It mostly depends on the inter-operation with other systems and your management strategy. For example, it might be easier for a manager to manage a list of users assigned to a role than it is to manage who has a specific Claim assigned. Claims can be very useful in a RESTful scenario where you can assign a claim to a client, and the client can then present the claim for authorization rather than passing the Username and Password for every request.
As #Claies perfectly explained, claims could be a more descriptive and is a deep kind of role. I think about them as your role's ids. I have a gym Id, so I belong to the members role. I am also in the kickboxing lessons, so I have a kickboxing Id claim for them. My application would need the declaration of a new role to fit my membership rights. Instead, I have ids for each group class that I belong to, instead of lots of new membership types. That is why claims fit better for me.
There is a a great explanation video of Barry Dorrans, talking about the advantage of using claims over roles. He also states that roles, are still in .NET for backward compatibility. The video is very informative about the way claims, roles, policies, authorization and authentication works.
Or check a related session shared by Lafi
Having used various authentication and authorisation techniques over decades, my current MVC application uses the following methodology.
Claims are used for all authorisation. Users are assigned one role (multiple roles are possible but I do not need this) - more below.
As is common practice, A ClaimsAuthorize attribute class is used. Since most controller actions are CRUD, I have a routine in the code-first database generation that iterates all controller actions and creates claim types for each controller action attribute of Read/Edit/Create/Delete. E.g. from,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
For use at in an MVC View, a base controller class presents view bag items
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
For website menus and other non-controller actions, I have other claims. E.g. whether a user can view a particular monetary field.
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
So where do Roles fit in?
I have a table that links a Role to a (default) set of claims. When setting user authorisation, the default is to give the user the claims of their role. Each user can have more or less claims than the default. To make editing simple, the claims list is show by controller and actions (in a row), with other claims then listed. Buttons are used with a bit of Javascript to select a set of actions to minimise the "clicking" required to select claims. On Save, the users claims are deleted and all of the selected claims are added. The web application loads claims only once, so any changes must prompt a reload within this static data.
Managers can therefore select which claims are in each role and which claims a user has after setting them to a role and those default claims. The system has only a small number of users so managing this data is straightforward
To understand the difference between Roles and Claims you must face the limitation of roles and feel how claims come over these issues, so let me give you 2 scenarios to recognize the power of claims where role can't resolve these issues :
1- Your site has two modules (pages, service ..etc) the first module for children (under 18 years old) the other for adults (over 18 years old)
your user identity has a birthday claim
You need to create a policy on this claim so the authorization for each module will be given on this value and if the age of the user is over 18 years then he can go to the adult module and not before this age.
Role is Boolean data type you can have or not have the role, it doesn't have multi values.
2- Your site has role user and you want to prevent access of users to make some maintenance without changing the code.
In claims, you can create an UnderConstrain policy that if true the user can't view the page give property authorize for role user.
At the time of writing this answer we were at '.NET 5.0' with '.NET 6.0' just around the corner. And this is my understanding of what I've seen:
Q: Do we no longer use Roles?
Yep, you're not supposed to use Roles any longer (at least not the way you did it in the previous frameworks.
Q: If so, why are Roles still offered?
To make upgrading projects easier/faster?
Q: Should we only use Claims?
yes. But be sure to check out the video posted here in the answer by #Jonathan Ramos.
Q: Should we use Roles & Claims together?
No, but you can put a role into a claim ofcourse, but be sure to upgrade your project to use Claims only.
And you should not have to write you're own attributes, you should use policy for that, as it's the way of the newer framework. If you need you're own attributes you're "doing it wrong", just create your own Requirement(handler) that's what the whole 'new' policy is all about.
In the current framework the attribute ClaimAuthorize is not even available anymore.

ASP.NET Identity and Claims

I am trying to move away from WebForms and learn MVC, specifically using the new ASP.NET Identity model. However, I cant seem to find any formal documentation from Microsoft, that demonstrates how to create a claims object, and store it in a database for a authenticated user.
My site, needs to do the following:
Authentication a user - TICK
Create a Claim, and store user information in it, so that I can use it throughout the session - NO TICK
Pull back the users roles from the new ASP.NET Roles table - NOT TICK
Can anyone shed any light on how this can be achieve?
Honestly, I'm still learning the ropes with Identity, myself. Admittedly, the Microsoft provided documentation could be better, but I've never found any of their documentation all that helpful. The best stuff always comes from the community, and unfortunately, Identity is still so new that the community has had time to really flesh it out yet.
That said, here's what I know, with the understanding that there may be better ways that I'm simply not aware of, yet.
Claims
Your UserManager has three methods of significance: GetClaimsAsync, AddClaimAsync and RemoveClaimAsync.
To get all claims for a user:
var claims = await UserManager.GetClaimsAsync(userId);
You can get the current user's id with:
var userId = User.Identity.GetUserId();
Once you have the claims, to pull out a specific one:
var someClaim = claims.FirstOrDefault(c => c.Type == "SomeClaimType");
Where "SomeClaimType" is the name of the claim as it was added. In some scenarios this might be a fully qualified URN, or it may just be a simple string. If it's not something you personally added, the best thing to do is just inspect the claims variable during a debug session to see what you actually have there.
Also, since the list of claims is a queryable, you can pretty much do whatever LINQ query you want on it, Where, Count, etc.
To add a new claim:
await UserManager.AddClaimAsync(userId, new Claim("SomeClaimType", claimValue));
And to remove a claim:
await UserManager.RemoveClaimAsync(userId, someClaim);
Roles
Roles work in a similar way. To get all roles for a user:
var roles = await UserManager.GetRolesAsync(userId);
To see if a user is in a particular role:
var hasRole = await UserManager.IsInRoleAsync(userId, "SomeRole");
To add a user to a particular role:
await UserManager.AddToRoleAsync(userId, "SomeRole");
And to remove:
await UserManager.RemoveFromRoleAsync(userId, "SomeRole");
Adding the roles in the first place is a bit different; you have to create an instance of RoleStore.
var roleStore = new RoleStore<IdentityRole>(context);
Then, you can use that to manage all roles. For example, to create a new role:
await roleStore.CreateAsync(new IdentityRole("RoleName"));
To remove:
var identityRole = await roleStore.FindByNameAsync("RoleName");
await roleStore.DeleteAsync(identityRole);
Getting all roles, is not possible with the Identity-specific API at this time, but you can always fall back to querying with Entity Framework directly:
var allRoles = context.Roles.OrderBy(o => o.Name);
Regarding Asp.Net Identity, I would strongly recommend Brock Allen's implementation, called 'Identity Reboot'. Identity Reboot basically is a set of extensions to the ASP.NET Identity. It was inspired due to frustrations with the ASP.NET Identity implementation.
You can read an introductory article here. You can download source code and samples from github here.
You can install it using nuget:
www.nuget.org/packages/BrockAllen.IdentityReboot/
www.nuget.org/packages/BrockAllen.IdentityReboot.Ef/ (for entity framework)

Spring Security User Roles Per Organization

In my application I have a top level entity called Organization. The relationship between User and Organization is many-to-many.
Because of this I could have the following scenario:
UserA has role ROLE_ADMIN for OrganizationA
UserA has role ROLE_USER for OrganizationB
I need to ensure that when UserA accesses resources for OrganizationB he is not doing it as an ADMIN. So I need an additional check that the user has the correct roles at the organization level. Is there anything built into Spring Security that allows for this? If not, does anyone know what the best way would be to about solving this?
UPDATE: A bit more information...
A User logs in and chooses which org they want to work with. That is stored in the session. Beyond that, URLs are locked down with the Secured annotation. What that means is that if UserA were to log in and select OrgA, they should be able to access /admin/user/create however, if they log in and choose OrgB they should not have access to that URL.
The long way is to add additional checks in every method where this matters. So call some service method that says "ok, you're an admin for OrgA but not for OrgB and you're logged in using OrgB, so deny this request".
I'm hoping for a more grails / spring-security way of handling this.
You can probably do this by using a custom AccessDecisionVoter. The vote method will supply you with the "configuration attributes" for the resource (method or URL), which will typically be the required roles, and you can obtain the current user's roles/authorities either directly from the Authentication object, or by reading the current org and selecting the appropriate roles for the user.
I'm assuming that you have some way of differentiating the user's roles, based on the org they've selected.
Essentially, you'd be writing an extended version of the standard RoleVoter, which takes the organization into account.
I think I'm little late here but this is what worked for me:
When an organization is selected, you can set a new Authentication object with new roles in your session(The previous Authentication object gets invalidated). Something like this:
#RequestMapping(value = "/org-a")
String orgA(HttpServletRequest request) {
request.getSession().setAttribute("org", "org-a")
Organization org = new Organization("org-a")
reloadRolesForAuthenticatedUser(org)
....
}
private void reloadRolesForAuthenticatedUser(Organization org) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication()
List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), org)
List<GrantedAuthority> authorities = getAuthorities(newRoles)
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
SecurityContextHolder.getContext().setAuthentication(newAuth)
}
private List<GrantedAuthority> getAuthorities(List<String> roles) {
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
if (!roles.isEmpty()) {
for (String r : roles) {
auths.add(new SimpleGrantedAuthority(r))
}
}
return auths
}

Resources