Creating admin in imported realm - keycloak

I've launched keycloak locally from a docker container with
docker run -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin
Then I've imported a realm (let's call it test-realm) from a json file by POSTing to {keycloak_host}/admin/realms. This works, the realm is created.
It's created without any initial users though. I want to create the users via curl as I want to automatize the whole process (start keycloak server, import realm, create users from json) in the future.
I'm aware of {keycloak_host}/admin/realms/test-realm/users of course. The problem is that POSTing to that end point already requires credentials (e.g. a JWT) from an admin account on test-realm. Or am I mistaken in this assumption?
My question is, how do I create that first admin account on test-realm having access to an admin on master. Or do I even need it to create users on test-realm through curl?

Turned out you can include a users key in the json realm representation. The value is an array of user representations as of version 4.5 of keycloak. So problem solved.

Related

How to synchronize user's data with users stored by keycloak in a Jhipster-App?

I wanted to create an webapp using JHipster with Keycloak and ran into a problem:
There is no deal to create new users using Keycloak or connecting user specific data to these users.
But if I want to delete a user I have to do that via Keycloak too, so the entry in JHipsters JHI_USER, the role-assignments and all the data created by this user will not be affected from these deletion.
So what I can do to make it possible to delete these user's data as well?
If Keycloak supported SCIM, you could use Apache SCIMple to sync your users. Here's a demo script that shows how to do it with Okta:
https://github.com/mraible/okta-scim-spring-boot-example/blob/main/demo.adoc

Keycloak token exchange across realms

We use Keycloak 12.02 for this test.
The idea is that we have a lot of customers, that we all have in their own realms. We want to be able to impersonate a user in any non-master realm for an admin/support user in the master realm.
The flow would be to:
login using a super-user/password to login into the master realm
get a list of all available realms and their users
craft a request to exchange the current access token with a new access token for that specific user.
It is the last step I cannot get to work.
Example:
Login to master realm
token=$(curl -s -d 'client_id=security-admin-console'
-d 'username=my-super-user' -d 'password=my-super-pass' \
-d 'grant_type=password' \
'https://login.example.net/auth/realms/master/protocol/openid-connect/token' | jq -r .access_token)
(we now have an access token for the super-user in the master realm)
The Keycloak server has enabled token exchange (-Dkeycloak.profile.feature.token_exchange=enabled) as described here https://www.keycloak.org/docs/latest/securing_apps/#_token-exchange.
Attempt to impersonate a user in another realm (not master):
curl -s -X POST "https://login.example.net/auth/realms/some_realm/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d 'client_id=some_client' \
-d "requested_subject=some_user" \
-d "subject_token=$token"
However, this does not work. The result is: {"error":"invalid_token","error_description":"Invalid token"}
(Doing this inside a single realm work)
What am I doing wrong here? This seems like a very normal feature to utilize in a real-life deployment, so any help is much appreciated!
UPDATE:
First of all, I found the very same use-case here: https://lists.jboss.org/pipermail/keycloak-user/2019-March/017483.html
Further, I can get it to work by working through some major hoops. As described above, one can use the broker client in the master realm as an identity provider:
Login as super-user adminA -> TokenA
use TokenA to get a new external token, TokenExt from the master identity provider.
Use TokenExt to do a token exchange for the user you want to impersonate
The caveat with the above is that the user adminA is created in each of the realms you log into with this method, so still not ideal.
as far as I know what you are describing is not possible. I'm wondering where you are, more than a year afterwards... did you solve your issue?
Before going further, note that I have found Keycloak discourse a good forum for Keycloak questions: https://keycloak.discourse.group/
Second, this is what I understand: for Keycloak, 2 realms or 2 different Keycloaks is the same. There is nothing common, they are 2 completely different id providers. So any reasoning that supposes shared trust or shared users between realms will not work.
For logging in to the other realm, you need a token that is trusted. There is no reason for the other realm to trust the master realm. The way to set that trust is to set up the master realm client as an identity provider to the other realm (I understand that this is what you do not want to do), so that tokens signed by the master realm will be trusted by the other realm.
And once you have that set up, I have not seen any other way of exchanging than having the token exchange create a federated "admin" user in the other realm (I configure it to be created each time from scratch, to avoid any synch). Also, 2 mappings are going to come in to play, the ID provider mapping, and the client mapping, for creating the resulting JWT.
If this doesn't match with your findings, please correct me.
Ah yes: there is also the question of using token exchange as defined in OAuth, with the may_act claim, which would be perfect here. But it would come after the exchange between realms, in addition. See https://datatracker.ietf.org/doc/html/rfc8693#section-4.4
EDIT: to "create the user each time from scratch"
go to "identity providers" / / "settings"
select "sync mode" to "force"
This is the relevant extrant from the tooltip:
The sync mode determines when user data will be synced using the
mappers. Possible values are: 'legacy' to keep the behaviour before
this option was introduced, 'import' to only import the user once
during first login of the user with this identity provider, 'force' to
always update the user during every login with this identity
provider.
so when you choose "force", basically the user will be overwritten at each login.
Ok so it's not really a creation, but as close as you can get :-)
The idea here is to not care about it, which is fine for prototyping. But I guess that in production you may want to optimize this.

Why does keycloak hide the "Service-account-admin-cli" user under "Users" section?

I was trying to call keycloak's REST api to create new users under a realm and I was following this tutorial:
https://www.appsdeveloperblog.com/keycloak-rest-api-create-a-new-user/
I was able to configure the Admin-cli client as below:
and I was able to get the access token by using the client id and secret:
However, when I make a POST request to /auth/admin/realms/myapp/users with the bearer token, it fails to create a user and I got an "unknow_error"
I searched through the internet and community and documentation but there was no clue. Eventually after hours and hours of trying, I found a solution:
You need to first go to clients --> admin_cli --> Sessions:
Then click on the user "Service-account-admin-cli" and configure such that it has admin role
Then, the previous POST request will successfully create a new user.
I cannot understand why this user "Service-account-admin-cli" is hidden under the users section:
Why would it be hidden??? How are people supposed to find this user (Service-account-admin-cli) and configure it? Does keycloak expect people to find it by clicking clients --> admin_cli --> Sessions and then see the user from there??
IMO if one is starting to learn Keycloak one should avoid using the master Realm or change the admin_cli configuration like that without a very good reason.
From the Keycloak documentation one can read:
When you boot Keycloak for the first time Keycloak creates a
pre-defined realm for you. This initial realm is the master realm. It
is the highest level in the hierarchy of realms. Admin accounts in
this realm have permissions to view and manage any other realm created
on the server instance. When you define your initial admin account,
you create an account in the master realm. Your initial login to the
admin console will also be via the master realm.
We recommend that you do not use the master realm to manage the users
and applications in your organization. Reserve use of the master realm
for super admins to create and manage the realms in your system.
Following this security model helps prevent accidental changes and
follows the tradition of permitting user accounts access to only those
privileges and powers necessary for the successful completion of their
current task.
So typically you would create a different Realm, and create the users there. Unless, you really want to create a user on the master realm, typically admin-alike users.
That being said to create the user using the Keycloak Rest API, one just need to request from the admin-cli client a token on behalf of the admin user by providing its name and password, for instance as follows:
TOKEN=$(curl -k -sS -d "client_id=admin-cli" \
-d "username=$ADMIN_NAME" \
-d "password=$ADMIN_PASSWORD" \
-d "grant_type=password" \
http://$KEYCLOAK_IP/auth/realms/master/protocol/openid-connect/token)
from the $TOKEN object extract the access token (let us named $ACCESS_TOKEN).
And then create the user as follows:
curl -k -sS -X POST https://$KEYCLOAK_IP/auth/admin/realms/$REALM_NAME/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "$USER_JSON_DATA"
$USER_JSON_DATA will be the json data representation of the user to be created. There is no need to add the role admin to the master admin deployed with Keycloak by default.
Does keycloak expect people to find it by clicking clients -->
admin_cli --> Sessions
If setup normally, you would just need to know (as I already described) the admin's name and password, which is configured in the initial setup anyway.
Following this setup then you:
You need to first go to clients --> admin_cli --> Sessions:
you would see the following:
The difference now is that if you click on the admin user > roles, you would see the following:
The admin user, has already the admin role. No need for:
configure such that it has admin role
Now if you change the admin_cli configuration exactly as you did then you need to add to the Service-account-admin-cli user the role admin.
I cannot understand why this user "Service-account-admin-cli" is
hidden under the users section:
It is an implementation detail, unfortunately, I could not find online a an explanation for that either. But I do agree that without further context it does not look very user-friendly. Now that begs the question of why the tutorial did not warn their readers about it.
Now, if one speculate a bit, the reason to hide that user from the list of users could be because:
it is not a real user in the conventional sense; not meant to be used to login into Keycloak. If you try to set the password of that user you get always an error.
the list of users is for the users explicitly created for that realm that one can actually explicitly authenticate. In other words, "Service-account-admin-cli" is used so that it represents the "one" performing the call to the admin-cli, since when one changes the grand type from password to client-credentials there is no explicit user authentication anymore (i.e., admin username and password). So "Service-account-admin-cli" is used as a place holder.
Naturally, one could argue why not just make "Service-account-admin-cli" have the admin role by default?!, but again it is implementation details, that only the developers behind can justify.
Another good reason to not blindly change the original setup of the admin-cli.
Just did the same tutorial and had the same problem. Thank you for your post! It helped me to figure out the solution. I don't know if that is due to a newer Keycloak-version but I don't even see the session of the service-account.
Instead of going through the session-menu you could instead go to:
clients -> admin-cli -> service account roles
And then add "manage-users" from:
client roles -> realm-management
I think that's how it's supposed to work.

Edit/create user with read/write access MongoDB

After deploying my Flask app, I get the following error when trying to access the MongoDB service:
OperationFailure: not authorized on [db_name] to execute command ...
I understand this is because the db user does not have read/write access to the database. But I'm not able to create a new user or change permissions. db.grantRolesToUser() returns "not a function" and addUser() gives me no permission... What can I do?
You need to do two things:
Bind the app to the service using cf bind-service (or the web portal)
In the app, parse the VCAP_SERVICES environment variable to get the credentials
This will ensure you app gets readWrite permissions on your database.
Here's a few helpful links in this regard:
https://docs.developer.swisscom.com/devguide/services/application-binding.html
https://docs.developer.swisscom.com/devguide/deploy-apps/environment-variable.html#VCAP-SERVICES
https://docs.developer.swisscom.com/service-offerings/mongodb.html

how to login mongo as a specific user

I add a user in mongo, using the
use production
db.addUser({user:"user",pwd:"pwd",roles:["read"]})
and also authenticate it, using the
db.auth("user","pwd")
My question is how to login the production database with the user I just created info.