I want to create a fairly simple role-based access control system using Keycloak's authorizaion system. The system Keycloak is replacing allows us to create a "user", who is a member of one or more "groups". In this legacy system, a user is given "permission" to access each of about 250 "capabilities" either through group membership (where groups are assigned permissions) or a direct grant of a permission to the user.
I would like to map the legacy system to keycloak authorizations.
It should be simple for me to map each "capability" in the existing system to a keycloak resource and a set of keycloak scopes. For example, a "viewAccount" capability would obviously map to an "account" resource and a "view" scope; and "viewTransaction" maps to a "transaction" resource... but is it best practice to create just one "view" scope, and use it across multiple resources (account, transaction, etc)? Or should I create a "viewAccount" scope, a "viewTransaction" scope, etc?
Similarly, I'm a little confused about permissions. For each practical combination of resource and scope, is it usual practice to create a permission? If there are multiple permissions matching a given resource/scope, what does Keycloak do? I'm guessing that the intention of Keycloak is to allow me to configure a matrix of permissions against resources and scopes, so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
I ask because the result of all this seems to be that my old "viewAccount" capability ends up creating an "Account" resource, with "View" scope, and a "viewAccount" permission, which seems to get me back where I was. Which is fine, if it's correct.
Finally, obviously I need a set of policies that determine if viewAccount should be applied. But am I right that this means I need a policy for each of the legacy groups that a user could belong to? For example, if I have a "helpdesk" role, then I need a "helpdesk membership" policy, which I could then add to the "viewAccount" permission. Is this correct?
Thanks,
Mark
Resource servers are managed using the Keycloak Administration Console. There you can enable any registered client application as a resource server and start managing the resources and scopes you want to protect. A resource can be a web page, a RESTFul resource, a file in your file system, an EJB, and so on.
Client scopes are entities in Keycloak, which are configured at the realm level and they can be linked to clients. The client scopes are referenced by their name when a request is sent to the Keycloak authorization endpoint with a corresponding value of the scope parameter.
Access Type. This defines the type of the OIDC client. confidential. Confidential access type is for server-side clients that need to perform a browser login and require a client secret when they turn an access code into an access token, (see Access Token Request in the OAuth 2.0 spec for more details).
I know I'm 2+ years late but I figure I'd share what I know and hopefully alleviate some pain for future readers. Full transparency- I am by no means a Keycloak/OAuth/OIDC expert and what I know is mostly from reading the docs, books, good ol' YouTube and playing around with the tool.
This post will be comprised of two parts:
Keycloak 8.0.0.Some terminology before we get started:
Resource-Based permissions, you apply it directly to your resource Scoped-Based permission, you apply it to your scope(s) or scope(s) and resource. is it best practice to create just one "view" scope, and use it across multiple resources (account, transaction, etc)? Or should I create a "viewAccount" scope, a "viewTransaction" scope, etc?
Scopes represent a set of rights at a protected resource. In your case, you have 2 resources: account and transaction, so I would lean towards the second approach.
In the long run, having a global view scope associated with all your resources (e.g. account, transaction, customer, settlement...) makes authorization difficult to both manage and adapt to security requirement changes.
Here are a few examples that you can check out to get a feel for design
Do note though - I am not claiming that you shouldn't share scopes across resources. Matter of fact, Keycloak allows this for resources with the same type. You could for instance need both viewAccount and viewTransaction scope to read a transaction under a given account (after all you might need access to the account to view transactions). Your requirements and standards will heavily influence your design.
For each practical combination of resource and scope, is it usual practice to create a permission?
Apologies, I don't fully understand the question so I'll be a bit broad. In order to grant/deny access to a resource, you need to:
scope or resource (or both)for policy enforcement to take effect. See Authorization Process.
How you go about setting all this up is entirely up to you. You could for instance:
Define individual policies, and tie each policy under the appropriate permission.
Better yet, define individual policies, then group all your related policies under an aggregated policy (a policy of policies) and then associate that aggregated policy with the scope-based permission. You could have that scoped-based permission apply to both the resource and all its associated scope.
Or, you could further break apart your permissions by leveraging the two separate types. You could create permissions solely for your resources via the resource-based permission type, and separately associate other permissions solely with a scope via the scope-based permission type.
You have options.
If there are multiple permissions matching a given resource/scope, what does Keycloak do?
This depends on
Decision Strategy
Decision Strategy
Logic value. The Logic value is similar with Java's ! operator. It can either be Positive or Negative. When the Logic is Positive, the policy's final evaluation remains unchanged. When its Negative, the final result is negated (e.g. if a policy evaluates to false and its Logic is Negative, then it will be true). To keep things simple, let's assume that the Logic is always set to Positive.
The Decision Strategy is what we really want to tackle. The Decision Strategy can either be Unanimous or Affirmative. From the docs,
Decision Strategy
This configurations changes how the policy evaluation engine decides whether or not a resource or scope should be granted based on the outcome from all evaluated permissions. Affirmative means that at least one permission must evaluate to a positive decision in order grant access to a resource and its scopes. Unanimous means that all permissions must evaluate to a positive decision in order for the final decision to be also positive. As an example, if two permissions for a same resource or scope are in conflict (one of them is granting access and the other is denying access), the permission to the resource or scope will be granted if the chosen strategy is Affirmative. Otherwise, a single deny from any permission will also deny access to the resource or scope.
Let's use an example to better understand the above. Suppose you have a resource with 2 permissions and someone is trying to access that resource (remember, the Logic is Positive for all policies). Now:
Permission One has a Decision Strategy set to Affirmative. It also has 3 policies where they each evaluate to:
true false false Since one of the policies is set to true, Permission One is set to true (Affirmative - only 1 needs to be true).
Permission Two has a Decision Strategy set to Unanimous with 2 policies:
true false In this case Permission Two is false since one policy is false (Unanimous - they all need to be true).
Decision Strategy is set to Affirmative, access to that resource would be granted because Permission One is true. If on the other hand, the resource server's Decision Strategy is set to Unanimous, access would be denied.See:
We'll keep revisiting this. I explain how to set the resource sever's Decision Strategy in Part II.
so for example I could have permission to access "accounts" and permission for "view" scope, so therefore I would have permission to view accounts?
The short answer is yes. Now, let's expand on this a bit :)
If you have the following scenario:
Decision Strategy set to Unanimous or Affirmative account/{id} resource is true view scope is true
You will be granted access to view the account.
true + true is equal to true under the Affirmative or Unanimous Decision Strategy. Now if you have this
Decision Strategy set to Affirmative account/{id} resource is true
view scope is false You will also be granted access to view the account.
true + false is true under the Affirmative strategy. The point here is that access to a given resource also depends on your setup so be careful as you may not want the second scenario.
But am I right that this means I need a policy for each of the legacy groups that a user could belong to?
I'm not sure how Keycloak behaved 2 years ago, but you can specify a Group-Based policy and simply add all your groups under that policy. You certainly do not need to create one policy per group.
For example, if I have a "helpdesk" role, then I need a "helpdesk membership" policy, which I could then add to the "viewAccount" permission. Is this correct?
Pretty much. There are many ways you can set this up. For instance, you can:
/account/{id}) and associate it with the account:view scope. helpdesk role under that policy Scope-Based permission called viewAccount and tie it with scope, resource and policy
We'll set up something similar in Part II.
Keycloak has a neat little tool which allows you test all your policies. Better yet, you actually do not need to spin up another application server and deploy a separate app for this to work.
Here's the scenario that we'll set up:
stackoverflow-demo
bank-api client under that realm /account/{id} for that client account/{id} will have the account:view scopebob under the new realm bank_teller, account_owner and user
bob with any roles. This is not needed right now. Role-Based policies:
bank_teller and account_owner have access to the /account/{id} resource account_owner has access to the account:view scope user does not have access to the resource or scopeEvaluate tool to see how access can be granted or
denied. Do forgive me, this example is unrealistic but I'm not familiar with the banking sector :)
cd tmp
wget https://downloads.jboss.org/keycloak/8.0.0/keycloak-8.0.0.zip
unzip keycloak-8.0.0.zip
cd keycloak-8.0.0/bin
./standalone.sh
http://localhost:8080/auth
Administration Console link Visit Getting Started for more information. For our purposes, the above is enough.
master realm and click on the Add Realm button.stackoverflow-demo as the name. Create. stackoverflow-demo instead of the master realm. See Creating a New Realm
Users link on the leftAdd User button username (e.g. bob) User Enabled is turned on Save See Creating a New User
Roles link Add Role bank_teller, account_owner and user
Again, do not associate your user with the roles. For our purposes, this is not needed.
See Roles
Clients link Create
bank-api for the Client ID Root URL enter http://127.0.0.1:8080/bank-api
Save Client Protocol is openid-connect Access Type to confidential Authorization Enabled to On
Save. A new Authorization tab should appear at the top. Authorization tab and then Settings Decision Strategy is set to Unanimous
Decision Strategy
See:
Authorization tab Authorization Scopes > Create to bring up Add Scope page account:view in the name and hit enter. Authorization link above Resources
Create View Account Resource for both the Name and Display name account/{id} for the URI account:view in the Scopes textboxSave
See Creating Resources
Authorization tab, click on Policies Role from the the Create Policy dropdown Name section, type Only Bank Teller and Account Owner Policy Realm Roles select both the bank_teller and account_owner roleLogic is set to Positive Save Policies link Role again from the Create Policy dropdown. Only Account Owner Policy for the Name Realm Roles select account_owner
Logic is set to Positive
Save Policies link at the top, you should now see your newly created policies. See Role-Based Policy
Do note that Keycloak has much more powerful policies. See Managing Policies
Authorization tab, click on Permissions
Resource-Based View Account Resource Permission for the Name Resources type View Account Resource Permission Apply Policy select Only Bank Teller and Account Owner Policy Decision Strategy is set to Unanimous
Save See Create Resource-Based Permissions
Phew...
Authorization tab, select Evaluate User enter bob Roles select user
Resources select View Account Resource and click Add View Account Resource with scopes [account:view] to see the results and you should see DENY. 
Only Bank Teller and Account Owner Policy. Let's test this to make sure this is true! Back link right above the evaluation result account_owner and click on Evaluate. You should now see the result as PERMIT. Same deal if you go back and change the role to bank_teller See Evaluating and Testing Policies
Permissions section Scope-Based this time under the Create Permission dropdown. Name, enter View Account Scope Permission Scopes, enter account:view Apply Policy, enter Only Account Owner Policy Decision Strategy is set to Unanimous
Save
See Creating Scope-Based Permissions
Second test run
Authorization section Evaluate
bob bank_teller View Account Resource and click Add Evaluate and we should get DENY.
bank_teller has access to the resource but not the scope. Here one permission evaluates to true, and the other to false. Given that the resource server's Decision Strategy is set to Unanimous, the final decision is DENY. Settings under the Authorization tab, and change the Decision Strategy to Affirmative and go back to steps 1-6 again. This time, the final result should be PERMIT (one permission is true, so final decision is true). Decision Strategy back to Unanimous. Again, go back to steps 1 through 6 but this time, set the role as account_owner. This time, the final result is again PERMIT which makes sense, given that the account_owner has access to both the resource and scope.Neat :) Hope this helps.
i know i am bit late to the party but let me try to explain as much as i can.
in keycloak we have terms like :
Resource : object which users will be accessing or performing the action on
Auth scopes : Actions that users can perform on the specific object
Policies : Policy
Permission : Mapping actually occur here
If you don't want to follow manual way you can export this JSON and all the users, resources, permissions will be auto-set bu keycloak
JSON configuration file
Now let's see a scenario where :

Now we have few resources like :
We want to implement the scenario where only specific user can performe specific actions.
Create a new realm



Check that the Decision Strategy is set to Unanimous. This is the resource server strategy

Go the Authorization tab Select Authorization Scopes > and click on Create Enter scopes:create & scopes:view in the text and save values.




You will see grant is permitted as Admin role has access to do operations create and view on resource account.

You will see grant is Deny as only Super_Admin role has access to do operations create on resource report.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With