Keycloak - How to aggregate the policy user and group attribute - keycloak

In a Keycloak realm client, I want to aggregate the "policy" attribute defined on the users and their groups.
To test this, I have a user "joe" with the attribute "policy" set to "alpha". He is member of the group "project" that have an attribute "policy" set to "beta".
I have created a client mapper like this:
policy mapper.
But when I log into a client webapp with "joe", I've checked the JWT token sent by Keycloak and the "policy" field is set to "alpha".
I've noticed that if I change the "Token Claim Name" to "policies" (policies mapper) or "fake" for example, the JWT "policies" field is set to
"policies": [
"alpha",
"beta"
]
I don't understand why I get this behaviour and how to fix it.

Related

Use ldap attribute for role-ldap-mapper role name

I'm trying to sync my roles from my LDAP to keycloak. As i have objects in my Domain that share the name of my needed roles i can't use the cn as "Role Name LDAP Attribute". Instead i want to create groups with a prefix like keycloak-mygroup and omit said prefix in the keycloak roles.
If that isn't possible, i'd like to create these groups with a prefix and use another attribute of the group as a role name. The roles i want to sync, already exist in my keycloak instance.
If i try to use an attribute like description i get an error ("Violation of UNIQUE KEY constraint "UK_J3RWUVD56ONTGSUHOGM184WW2-2". A duplicate key cannot be inserted into the dbo.KEYCLOAK_ROLE object. The duplicate key value is (, default).") and if i use an attribute like distinguishedName (those roles don't exist) everything is created.
How can i use a different attribute than cn for my role names and have it sync?
I was able to solve this problem. The error happens if a group is missing the attribute used for the group name. Every group has to have the used attribute, otherwise the sync will fail for all groups.

Keycloak client mapper to show the relam name as individual attibute in JWT token

By default keycloak (here version 11) provides information about the realm, a token was fetched for, only parsing the iss attribute of the token payload. e.g.
{
"exp": ...,
"iat": ...,
"jti": "...",
"iss": "http://localhost:8088/idp-provider-context/auth/realms/realmname",
"aud": [...
Is there a build in way, like a client mapper, to add the information about the realm name directly as a dedicated attribute to the JWT-token?
One workaround would be to add an attribute "realmname" to each user and setting the realmname as the value. But on the one hand this seems to be a bit messy, as it is redundant information. On the other hand this could speed up the application a bit, as tokens/users without this attribute or the wrong value in it could be already count as invalid without requesting the backend. This would identify users not created in the desired process, defined for the application.
Instead of a user attribute, use a Client Mapper Instead. For that go to:
Select your realm
Go to clients
Select the appropriate client for your use-case
(For the OLD Keycloak UI)
Go to Mappers
Click Create
In Mapper type select Hardcoded claim
Fill up the field Token Claim Name as realm name
Fill up the field Claim value as the name of the realm
Fill up the renaming fields, accordingly.
Click on Save
(For the NEW Keycloak UI)
Go to the tab Client Scopes
Click on the scope -dedicated (e.g., test-dedicated in my example)
Click on Configure a new mapper (or Add Mapper > By configuration if you have already created mappers before for this client)
Select Hardcoded claim
Fill up the field Token Claim Name as realm name
Fill up the field Claim value as the name of the realm
Fill up the renaming fields, accordingly.
Click on Save
The client will be the client that you are using to authenticate against.

Keycloak - Manage realm with user from different realm

Is possible to have user in one realm to manage another realm in keycloak?
My goal is to have 2 realms - adminRealm & userRalm. In adminRealm should be users, which will be able to log in to our admin app and there they could create via Keycloak rest api "ordinary user" which will be placed into userRealm.
Currently my solution working over one realm, where I have admin user which is able to log into my admin app and there he can create users in the same realm. But if I want create users to another realm, I get 403 error. So is there any way how to allow admin user to manage another realm (eg create users etc.)?
You should use master realm for storing admin accounts. Non master realms are isolated from each other. If you look to the clients list in master realm you should see that every realm represented by client with OIDC id like "foo-realm". This clients represents administration REST API for corresponding realms, and users with granted roles from this clients could perform admin requests to corresponding apis.
For example you have foo realm which will contain ordinary application users. To achieve your goal to introduce admin accounts that will be able to manage users from foo you have to create foo-admin user in master realm and grant him foo-realm.realm-admin role. Now this user has total control over foo realm and no control over master realm. You also can map foo-realm.realm-admin role to some group in master realm and add users to it (so if any changes appears in future you will have to change only group role settings)
In case you use terraform your solution would look like this:
data "keycloak_realm" "master" {
realm = "master"
}
data "keycloak_openid_client" "realm_management" {
realm_id = data.keycloak_realm.master.id
client_id = "foo-realm"
}
data "keycloak_role" "query_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "query-users"
}
data "keycloak_role" "manage_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "manage-users"
}
resource "keycloak_user_roles" "user_admin_roles" {
realm_id = data.keycloak_realm.master.id
user_id = keycloak_user.users_admin.id
role_ids = [
data.keycloak_role.query_users.id,
data.keycloak_role.manage_users.id,
]
}

Loopback Update User Field

I am trying to update a field in a model that extends the user model. In the API explorer, I set the where field to {"id": 59}, and have the access token one that corresponds with id 59. In the data field I have {"age": 55} where I am just trying to update the age to 55.
The request URL ends up being: http://IP:3000/api/MODEL/update?where=%7B%22id%22%3A%2059%7D&access_token=LONG ACCESS TOKEN VALUE
Which gives an error:
{
"error": {
"statusCode": 401,
"name": "Error",
"message": "Authorization Required",
"code": "AUTHORIZATION_REQUIRED",
}
}
I don't understand why authorization is required when I have a correct access token and the email has been verified. What am I doing wrong?
Loopback by default provides ACL to user model. So by default the update operation can only be changed by the $OWNER, ie. the person himself.
So first login with the username and password, you get the accesstoken. Copy and set the accesstoken in Api Explorer.
Now use the PUT method, which will say Users/{$id}
Open it and you will see 2 fields, data and id. Provide your model's id and provide the data object (the data that needs to be changed)
Hope this helps.

GCS delete bucket ACL always returns 404

I can't seem to delete a GCS bucket ACL that I inserted.
I did a POST to insert an ACL for my service account:
https://www.googleapis.com/storage/v1/b/arqclient-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s/acl
with this request JSON:
{
"entity" : "user-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s#developer.gserviceaccount.com",
"role" : "WRITER"
}
When I list the ACLs, the ACL I inserted looks like this:
{
bucket = "arqclient-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s";
entity = "user-00b4903a970addfce72044c71917166bd27bc8b9ab94a391dc841b526cd9466f";
entityId = 00b4903a970addfce72044c71917166bd27bc8b9ab94a391dc841b526cd9466f;
etag = "CA0=";
id = "arqclient-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s/user-00b4903a970addfce72044c71917166bd27bc8b9ab94a391dc841b526cd9466f";
kind = "storage#bucketAccessControl";
role = WRITER;
selfLink = "https://www.googleapis.com/storage/v1/b/arqclient-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s/acl/user-00b4903a970addfce72044c71917166bd27bc8b9ab94a391dc841b526cd9466f";
}
So apparently my "user-<emailaddress>" gets converted some other kind of ID.
When I try to delete the ACL:
DELETE https://www.googleapis.com/storage/v1/b/arqclient-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0sfkjhfkjhf/acl/user-1026650596885-sfd2omc18k3qs6lgphlch37jb5fucg0s%40developer.gserviceaccount.com
I always get a 404 error.
What's wrong with my DELETE command? The doc says I can use user-emailAddress, but that doesn't work.
If I use the entity ID from the listing, "user-00b4903a970addfce72044c71917166bd27bc8b9ab94a391dc841b526cd9466f", that works through the Google APIs Explorer.
If I'm supposed to use the entity ID, how do I get the entity ID given a service-account email address?
The access control page of the Google API docs says "You can find a user's Google Storage ID by retrieving the ACL of an object that the user uploaded." https://cloud.google.com/storage/docs/access-control?hl=en#google-storage-ids
So I guess the best answer is to create an object with my service account, retrieve its ACL, and find the entity ID in the ACL.