2016-11-29 15:30:53 +00:00
[[_policy_js]]
2022-04-18 14:10:57 +00:00
= JavaScript-based policy
2016-06-05 22:17:31 +00:00
2021-01-18 12:18:04 +00:00
WARNING: If your policy implementation is using Attribute based access control (ABAC) as in the examples below, then please make sure that
2023-11-13 08:17:34 +00:00
users are not able to edit the protected attributes and the corresponding attributes are read-only. See the details in the link:{adminguide_link}#mitigating_security_threats[Threat model mitigation] chapter.
2021-01-18 12:18:04 +00:00
2016-11-15 21:34:20 +00:00
You can use this type of policy to define conditions for your permissions using JavaScript. It is one of the rule-based policy types
2017-08-28 12:50:14 +00:00
supported by {project_name}, and provides flexibility to write any policy based on the <<_policy_evaluation_api, Evaluation API>>.
2016-06-05 22:17:31 +00:00
2022-04-18 14:10:57 +00:00
To create a new JavaScript-based policy, select *JavaScript* in the item list in the upper right corner of the policy listing.
2016-06-14 23:50:50 +00:00
2019-11-01 12:09:56 +00:00
NOTE: By default, JavaScript Policies can not be uploaded to the server. You should prefer deploying your JS Policies directly to
2022-04-20 12:25:22 +00:00
the server as described in link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}].
2022-04-18 14:10:57 +00:00
== Creating a JS policy from a deployed JAR file
2019-11-01 12:09:56 +00:00
{project_name} allows you to deploy a JAR file in order to deploy scripts to the server. Please, take a look at link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}]
for more details.
Once you have your scripts deployed, you should be able to select the scripts you deployed from the list of available policy providers.
2017-10-09 06:38:46 +00:00
== Examples
2016-06-05 22:17:31 +00:00
2018-06-12 02:16:55 +00:00
=== Checking for attributes from the evaluation context
2016-11-15 21:34:20 +00:00
Here is a simple example of a JavaScript-based policy that uses attribute-based access control (ABAC) to define a condition based on an attribute
2016-06-05 22:17:31 +00:00
obtained from the execution context:
```javascript
2022-03-13 11:41:25 +00:00
const context = $evaluation.getContext();
const contextAttributes = context.getAttributes();
2016-06-05 22:17:31 +00:00
2016-06-29 22:51:16 +00:00
if (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) {
2016-06-05 22:17:31 +00:00
$evaluation.grant();
}
```
2018-06-12 02:16:55 +00:00
=== Checking for attributes from the current identity
Here is a simple example of a JavaScript-based policy that uses attribute-based access control (ABAC) to define a condition based on an attribute
obtained associated with the current identity:
```javascript
2022-03-13 11:41:25 +00:00
const context = $evaluation.getContext();
const identity = context.getIdentity();
const attributes = identity.getAttributes();
const email = attributes.getValue('email').asString(0);
2018-06-12 02:16:55 +00:00
if (email.endsWith('@keycloak.org')) {
$evaluation.grant();
}
```
Where these attributes are mapped from whatever claim is defined in the token that was used in the authorization request.
=== Checking for roles granted to the current identity
2018-02-28 07:53:43 +00:00
You can also use Role-Based Access Control (RBAC) in your policies. In the example below, we check if a user is granted with a `keycloak_user` *realm* role:
2016-06-05 22:17:31 +00:00
```javascript
2022-03-13 11:41:25 +00:00
const context = $evaluation.getContext();
const identity = context.getIdentity();
2016-06-05 22:17:31 +00:00
2017-12-04 12:59:48 +00:00
if (identity.hasRealmRole('keycloak_user')) {
2016-06-05 22:17:31 +00:00
$evaluation.grant();
}
```
2018-02-28 07:53:43 +00:00
Or you can check if a user is granted with a `my-client-role` *client* role, where `my-client` is the client id of the client application:
2017-12-04 12:59:48 +00:00
```javascript
2022-03-13 11:41:25 +00:00
const context = $evaluation.getContext();
const identity = context.getIdentity();
2017-12-04 12:59:48 +00:00
if (identity.hasClientRole('my-client', 'my-client-role')) {
$evaluation.grant();
}
```
2022-10-19 06:33:25 +00:00
=== Checking for roles granted to a user
To check for realm roles granted to a user:
2018-06-12 02:16:55 +00:00
```javascript
2022-03-13 11:41:25 +00:00
const realm = $evaluation.getRealm();
2018-06-12 02:16:55 +00:00
if (realm.isUserInRealmRole('marta', 'role-a')) {
$evaluation.grant();
}
```
2022-10-19 06:33:25 +00:00
Or for client roles granted to a user:
2018-06-12 02:16:55 +00:00
```javascript
2022-03-13 11:41:25 +00:00
const realm = $evaluation.getRealm();
2018-06-12 02:16:55 +00:00
if (realm.isUserInClientRole('marta', 'my-client', 'some-client-role')) {
$evaluation.grant();
}
```
=== Checking for roles granted to a group
To check for realm roles granted to a group:
```javascript
2022-03-13 11:41:25 +00:00
const realm = $evaluation.getRealm();
2018-06-12 02:16:55 +00:00
if (realm.isGroupInRole('/Group A/Group D', 'role-a')) {
$evaluation.grant();
}
```
=== Pushing arbitrary claims to the resource server
To push arbitrary claims to the resource server in order to provide additional information on how permissions should be
enforced:
```javascript
2022-03-23 18:25:54 +00:00
const permission = $evaluation.getPermission();
2018-06-12 02:16:55 +00:00
// decide if permission should be granted
if (granted) {
permission.addClaim('claim-a', 'claim-a');
permission.addClaim('claim-a', 'claim-a1');
permission.addClaim('claim-b', 'claim-b');
}
```
=== Checking for group membership
```javascript
2022-03-13 11:41:25 +00:00
const realm = $evaluation.getRealm();
2018-06-12 02:16:55 +00:00
if (realm.isUserInGroup('marta', '/Group A/Group B')) {
$evaluation.grant();
}
```
=== Mixing different access control mechanisms
2017-12-04 12:59:48 +00:00
You can also use a combination of several access control mechanisms. The example below shows how roles(RBAC) and
2017-12-07 11:15:02 +00:00
claims/attributes(ABAC) checks can be used within the same policy. In this case we check if user is granted with `admin` role
or has an e-mail from `keycloak.org` domain:
2016-06-14 23:50:50 +00:00
```javascript
2022-03-13 11:41:25 +00:00
const context = $evaluation.getContext();
const identity = context.getIdentity();
const attributes = identity.getAttributes();
const email = attributes.getValue('email').asString(0);
2016-06-14 23:50:50 +00:00
2017-12-04 12:59:48 +00:00
if (identity.hasRealmRole('admin') || email.endsWith('@keycloak.org')) {
2016-06-14 23:50:50 +00:00
$evaluation.grant();
}
```
2018-06-12 02:16:55 +00:00
2022-04-18 14:10:57 +00:00
NOTE: When writing your own rules, keep in mind that the *$evaluation* object is an object implementing *org.keycloak.authorization.policy.evaluation.Evaluation*. For more information about what you can access from this interface, see the <<_policy_evaluation_api, Evaluation API>>.