[keycloak-user] filter group claim in token per client

Ronald Demneri ronald.demneri at amdtia.com
Tue Nov 6 10:08:01 EST 2018


Hello again,

Upon testing login and experimenting where the claim should be inserted, I found out that the duplicate print() is a result of including the claim in both ID access tokens. The error comes as a result of including the claim in the userinfo token, and probably that is why the userinfo endpoint does not contain the claim when the client application requests it.

Any idea how to solve it?


Thanks in advance,
Ronald

-----Original Message-----
From: Ronald Demneri 
Sent: 06.Nov.2018 12:01 PM
To: Ronald Demneri <ronald.demneri at amdtia.com>; Dmitry Telegin <dt at acutus.pro>; keycloak-user at lists.jboss.org
Subject: RE: [keycloak-user] filter group claim in token per client

So, I am looking at the logs and receive the following when going to App1 > Client Scopes > Evaluate:

2018-11-06 10:51:42,407 INFO  [stdout] (default task-1892) ############################################ APP1
2018-11-06 10:51:42,407 INFO  [stdout] (default task-1892) ############################################
2018-11-06 10:51:42,407 INFO  [stdout] (default task-1892)  We are here!!!
2018-11-06 10:51:42,408 INFO  [stdout] (default task-1892) ############################################

But when trying to actually log in to the client, I receive the following:

2018-11-06 10:52:20,465 INFO  [stdout] (default task-1891) ############################################ APP1
2018-11-06 10:52:20,465 INFO  [stdout] (default task-1891) ############################################
2018-11-06 10:52:20,465 INFO  [stdout] (default task-1891)  We are here!!!
2018-11-06 10:52:20,466 INFO  [stdout] (default task-1891) ############################################
2018-11-06 10:52:20,474 INFO  [stdout] (default task-1891) ############################################ APP1
2018-11-06 10:52:20,474 INFO  [stdout] (default task-1891) ############################################
2018-11-06 10:52:20,474 INFO  [stdout] (default task-1891)  We are here!!!
2018-11-06 10:52:20,475 INFO  [stdout] (default task-1891) ############################################
2018-11-06 10:52:20,691 ERROR [org.keycloak.protocol.oidc.mappers.ScriptBasedOIDCProtocolMapper] (default task-1891) Error during execution of ProtocolMapper script: org.keycloak.scripting.ScriptExecutionException: Could not execute script 'token-mapper-script_filteredGroupsMapper' problem was: TypeError: null has no such function "toUpperCase" in <eval> at line number 31

Line 31 is as follows:

31:    var client = token.getIssuedFor().toUpperCase();
32:    print("############################################ " + client);

So why does it display an error, when in fact it also displays the correct form of the clientId in upper case? And why is the log entry duplicated? ATM, I removed the client scope mapper and have recreated the script mapper only for this client.


Regards,
Ronald


-----Original Message-----
From: Ronald Demneri 
Sent: 06.Nov.2018 11:05 AM
To: 'Ronald Demneri' <ronald.demneri at amdtia.com>; 'Dmitry Telegin' <dt at acutus.pro>; 'keycloak-user at lists.jboss.org' <keycloak-user at lists.jboss.org>
Subject: RE: [keycloak-user] filter group claim in token per client

Hello Dmitry,

A colleague of mine helped solving the issue with the array, and I can see the filtered groups in the Access token. I also used token.getIssuedFor() to get the client name and make the evaluation of the filtered groups dynamic. The problem now is that this new claim is not present in the userinfo. This is the script that we came up with (configured both as client scopes (possibly define as a default client scope) as well as script mapper specific to this client for test purposes - claim names are different of course):

[kcadmin at keycloak bin]$ ./kcadm.sh get client-scopes [ {
  "id" : "4ea94866-044e-4590-a2da-f25c980f08b4",
  "name" : "Filtered_Groups",
  "protocol" : "openid-connect",
  "attributes" : {
    "display.on.consent.screen" : "true"
  },
  "protocolMappers" : [ {
    "id" : "7d3c521a-b291-4f43-ad87-6891ed9584d3",
    "name" : "Filtered Groups",
    "protocol" : "openid-connect",
    "protocolMapper" : "oidc-script-based-protocol-mapper",
    "consentRequired" : false,
    "config" : {
      "multivalued" : "true",
      "userinfo.token.claim" : "true",
      "id.token.claim" : "true",
      "access.token.claim" : "true",
      "claim.name" : "fGroup",
      "jsonType.label" : "String",
      "script" : "/**
	* Available variables:
	* user - the current user
	* realm - the current realm
	* token - the current token
	* userSession - the current userSession
	* keycloakSession - the current userSession
	*/
	
	//insert your code here...

	//So, first we need to know, how many names should be added to the new claim,
	var username = user ? user.username : \"anonymous\";
	var groups = user.getGroups();
	var group_array = groups.toArray();
	//print(\"########################################## \" + username);

	var client = token.getIssuedFor();
	//print(\"############################################ \" + client);

	var clUp = client.toUpperCase();
	//print(clUp);

	var group_APP = \"APP-\" + clUp + \"-USERS\";
	var group_ROL = \"ROL_SSO-\" + clUp + \"-ADMIN\";

	var group_filtered = [];

	for (var i in group_array) {
		var gn = group_array[i].getName();
		var gnUp = gn.toUpperCase();
		if (gnUp === group_APP || gnUp === group_ROL) {
			group_filtered.push(\"/\" + gn);
			}
		}
	//Then we declare the new array.
	var l = group_filtered.length;
	var group_token = java.lang.reflect.Array.newInstance(java.lang.String.class, l);

	for (var f in group_filtered) {
		group_token[f] = group_filtered[f];
		//print(group_token[f]);
	}

	//And submit the array as token
	token.setOtherClaims(\"fGroup\", group_token);"
    }
  } ]
}

This is the userinfo data for my account:

{
  "sub": "bad7ff26-2a70-446f-a635-06fdbe1bec55",
  "Group": [
    "/APP-App1-Users/TGR-Team-ABC",
    "/APP-App1-Users/TGR-Team-DEF",
    "/APP-App1-Users",
    "/APP-MySmallApp-Users"
  ],
  "email_verified": false,
  "name": "Ronald Demneri",
  "preferred_username": "u151302",
  "given_name": "Ronald",
  "family_name": "Demneri"


The group claim is inserted by the group mapper created for this client, and the idea is to remove it once the script mapper works as expected.
What do you think is going on? Is this behavior normal?

Thanks in advance,
Ronald

-----Original Message-----
From: Ronald Demneri
Sent: 05.Nov.2018 12:12 PM
To: 'Ronald Demneri' <ronald.demneri at amdtia.com>; Dmitry Telegin <dt at acutus.pro>; keycloak-user at lists.jboss.org
Subject: RE: [keycloak-user] filter group claim in token per client

Hello,

In the script authenticator there was authenticationSession which I used to get the clientId. There is no such variable in the script mapper, and If I define such mapper in the client template, I suppose I'd need some mechanism to get the client name and then make the filtering of the groups that need to be inserted in the token. How do I do that? Is there any documentation available for this online?


Thanks again for your support!
Ronald


-----Original Message-----
From: keycloak-user-bounces at lists.jboss.org <keycloak-user-bounces at lists.jboss.org> On Behalf Of Ronald Demneri
Sent: 05.Nov.2018 11:00 AM
To: Dmitry Telegin <dt at acutus.pro>; keycloak-user at lists.jboss.org
Subject: Re: [keycloak-user] filter group claim in token per client

Hello Dmitry,

Thanks for the response. In fact I tried that before posting here, created a custom script mapper for the client that I have configured. The problem is that the script will return a list of objects, not an array of strings, which is what I am expecting.

What do I need to pay extra attention in order to solve this?


Thanks in advance and Regards,
Ronald

-----Original Message-----
From: Dmitry Telegin <dt at acutus.pro>
Sent: 05.Nov.2018 6:54 AM
To: Ronald Demneri <ronald.demneri at amdtia.com>; keycloak-user at lists.jboss.org
Subject: Re: [keycloak-user] filter group claim in token per client

Hello Ronald,

As in the case with authentication, JavaScript is to the rescue again :) You can create a script mapper for groups that will do additional group filtering based on the client, and use it instead of the built-in one.

To avoid explicitly configuring it for each and every client, you can create a Client Scope (can be called "Client Template" depending on the KC version), define the mapper in the scope, and add it do default scopes.

Cheers,
Dmitry Telegin
CTO, Acutus s.r.o.
Keycloak Consulting and Training

Pod lipami street 339/52, 130 00 Prague 3, Czech Republic
+42 (022) 888-30-71
E-mail: info at acutus.pro 

On Fri, 2018-11-02 at 10:30 +0000, Ronald Demneri wrote:
> Hello everyone,
> 
> Is there a way to filter the groups a user is a member of per client, based on clientId (which is part of the group name(s) in AD). Let's say that user Ronald is member of  group_client1, group_client2 and group_client3, so using a group mapper, the token will contain a claim like group:["group_client1", "group_client2", "group_client3"]. Upon logging in to client1 app, I want to customize the group claim so that it contains only the respective group_client1 value.
> 
> Thanks in advance,
> 
> Ronald
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user

_______________________________________________
keycloak-user mailing list
keycloak-user at lists.jboss.org
https://lists.jboss.org/mailman/listinfo/keycloak-user



More information about the keycloak-user mailing list