How to add dedicated scope to Keycloak via kcadm - keycloak

I'd like to add dedicated scopes to a client so that it can access information from other clients.
Turning full access on works but grants too many permissions.
The scopes are already created with their respective clients. It is “only” a matter of assigning scope from client a to client b. I have a list of names and client ids available locally. How can I efficiently assign them via kcadm.sh?
I already tried with the network tab open but I couldn't wrap my head around what the logic behind assigning scopes is.
E.g., there is a
POST /admin/realms/master/clients/968c7b36-95dd-4121-b92b-37b324298890/scope-mappings/realm with an empty array as payload
POST /admin/realms/master/clients/968c7b36-95dd-4121-b92b-37b324298890/scope-mappings/clients/74cb7b05-34d5-4657-8fe6-bb19a7c8a07f from the APIDOC it just says client. But I don't know what that client should be.
How to reproduce on Keycloak (X) 20.0.3
Login to the Keycloak Admin Console
Click on the client tab
Click createClient
Create client id and click next.
Click save.
On the new client. Click on the upper tab 'Client scopes'.
Click on the first blue item.
Click on the upper tab 'scope' and turn off full scope allowed.
Click assign role and add one of the items.
This is what I want to achieve with the help of the kcadm.sh as clients are added dynamically. You can't even export the client from Actions->Export and Import it again from the UI. Every scope is lost when imported again.

To assign role from client A to client B at the bear minimal you need the following Rest Full API call:
POST /admin/realms/ <REALM NAME> /clients/< ID OF THE CLIENT >/scope-mappings/clients/< ID OF THE CLIENT where the role comes from>
so in your case /admin/realms/ <REALM NAME> /clients/< ID OF CLIENT B >/scope-mappings/clients/ < ID OF CLIENT A>
the payload should be [{"id":"<ID OF ROLE>","name":"<ROLE NAME>"}]
You will need the call to get the id of the client for that you can call:
GET /{realm}/clients
with clientId as query parameter.
And then you will need the call to get the ID of the role, for that you can use:
GET /{realm}/clients/{id}/roles/{role-name}
id is the id of the client.

Related

What is the workflow for a basic Auth OIDC with Keycloak

I have keycloak on docker (v20.0.2) and as you know some versions change some or good part of the UI, so is hard to follow tutorials around the web...
I am trying to follow this particular tuto
https://developers.redhat.com/blog/2020/11/24/authentication-and-authorization-using-the-keycloak-rest-api#keycloak_sso_demo
that seems the more updated. My keycloak is actually behind traeffic and thomseddon/traeffic-fordward-auth with a docker-compose file (but the connection through traeffic is good and I have acces to admin UI)
So on step 10 of the tutorial things change for me, I have to look for that particular view inside:
Click on lateral menu Client Scope
Click on button Create client scope
Give a name to the scope, and click on Tab Mapper
All mappers are predefined... so there is no "New mapper" don't understand this bit
then just follow the tuto
With that series of steps I get an error when retriving the token...
https://keycloak:8443/realms/education/protocol/openid-connect/token
enter image description here
(this are fake local data from the realm I created for testing)
that responds with a or something similar I have also tried to change the grant_type to password, and the same happens can not query the token....
{
"error": "invalid_client",
"error_description": "Invalid client or Invalid client credentials"
}
But if I do not link a user with an scope/role as in the tuto suggest then I get the token, but of course I want to use the role or scope to limit who can see which endpoint and who can not
Any step that I'm missing from this update, do you have the same error?
Thank you in advance
I have tried to run it with different combinations of options to see if there is a toggle that actually allows me to fetch the token
Also with different types of grant_type
I will build an API in Python (I don't know Java and prefer Json instead of XML) that connect to this keycloak to allow users or not based on their scope/role/permission or something
I need to be able to block user so if user Student try to access an url from another Student he get blocked that url. So is based on the role or scope or I don't know which is prefered or easer to accomplish, the mission is to block users or not based on a factor that could be used for this in keycloak.

Creating public action does not add to sequence

I am a new user following this tutorial provided by IBM.
I am up to this step:
For Cloudant Instance, select Input your own credentials and fill in the following fields with the credentials information captured for your cloudant service: Username, Password, Host and Database = guestbook and click Add and then Save.
After following the instruction to 'Add', I am returned to the sequence view (with the list of actions representing the sequence I'm working on).
Expected: The newly created public action w/ binding should appear in the list.
Instead: The newly created public action is not in the list. There is no evidence of it having been created at all. There is no option to 'save'.
Am I doing something wrong? This seems like an enormous bug.
Attempted solutions (unsuccessful):
Log out and back in.
Create new Cloudant service credentials.
Enter service credentials manually vs via dropdown.
Create action in a named package rather than default package.
Create new Cloudant service credentials, selecting a specific service ID.
PS
Attempted to create support ticket but needed to upgrade account by adding credit card. Filled in card information. Card rejected: "Error: Could not place order. Unable to verify the credit card. Declined due to Risk management". I use this card successfully all the time.
In actions UI, selected a sequence, added an action to the sequence, 'reset' sequence to discard changes, began to add yet another action, cancelled that new action, returned to sequence view and the previously created action that I had discarded was there. Ie seems like some backend / database propagation issues on IBM's end?
The steps have been updated in https://cloud.ibm.com/docs/tutorials?topic=solution-tutorials-serverless-api-webapp#sequence-of-actions-to-save-the-guestbook-entry.
To create the new Cloudant binding:
Set Name to binding-for-guestbook.
Set Instance to Input your own credentials.
Set Username, Password, Host and IAM API Key from the values found in the Cloudant credentials for-guestbook created earlier.
Set Database to guestbook.
Set whiskoverwriteLabel to true.
Save

Access Keycloak group attributes from Nodejs

I've got Keycloak setup and running with NodeJS.
I see you can create groups and assign attributes to those groups. Is it possible to access these attributes from the NodeJS application?
I can't even find the groups let alone their attributes.
Yes you can. But there is almost no official documentation on how to achieve this. You can return most keycloak attributes, groups and roles through the client mappers. By default none are configured.
To configure extra mappers: In the administration console, select the client and then the Mappers tab. That should bring you to a list of mappers.
You can add mappers here of different types. Once you add a mapper you can decide which calls to Keycloak from the client return the attribute(s), and what the name of the returned attribute is. The following screenshot includes a mapper that returns a dictionary of groups, with subgroups, separated by forward slashes. Your Node code will need to parse the returned JSON object.
All the information is returned in the keycloak token, which is a Javascript Web Token. In Node you can examine it by printing the token to the log. The keycloak-connect middleware stores tokens etc in an object on the request called kauth. The path to retrieve a list of groups specified by the configuration in the above screenshot is shown below. If you change the token claim name in the configuration, you will need to change the path in your NodeJS code accordingly. You will need to logout from your application and login again for changes to the mapper to work.
router.get('/', async function(req, res){
console.log(req.kauth.grant.access_token.content.groups) ..
}

Postman requests keep creating new conversations

I've deployed the "pizza" dialog to my Bluemix account. I'm using Postman to verify the REST interactions prior to my coding implementation. I'm able to retrieve the dialog id using the dialog REST GET. Taking the returned dialog id I establish a new conversation (leave client_id and conversation_id) empty:
https://gateway.watsonplatform.net/dialog/api/v1/dialogs/ee93cf6e-8718-4524-b10c-4f20fee90883/conversation
I use the returned conversation id to send another conversation request but I first set in the header the conversation_id, and the input value to "A large Pizza"
https://gateway.watsonplatform.net/dialog/api/v1/dialogs/ee93cf6e-8718-4524-b10c-4f20fee90883/conversation
Rather than getting the next turn in the dialog asking for toppings I get a new conversation id and new client id, and input asking me again for what size pizza I'd like to order.
Should I be able to test the dialog interaction using Postman, and why are my subsequent dialog requests all being treated as new conversation requests?
Appreciate any advice.
You said you are setting the conversation ID in the header so I am going to assume you may be passing that ID parameter incorrectly. According to the Watson Dialog API Explorer it states that if you do not pass in a conversation_id it will start a new conversation. Since you pass the converation_id incorrectly it thinks you did not provide one and will start a new conversation with you.
Since you are using Postman, try setting the conversation_id in the Body of the POST and not in the header.

Breeze EFContextProvider per request and based on parameter?

I have a multi-tenant app in which user can select "current company" after they log in.
There is a DB per company but the model is the same, the workflow is the same, and the controller actions are same....The user can switch companies while being logged in and all actions need to be 'directed' to proper DB.
I know it is possible to customize context creation in EFContextProvider<T> by overriding CreateContext() but how do I pass the extra info (parameter, e.g. CompanyId) that would allow me to create context with correct connection string?
Is this possible?
I find the easiest way is to include the tenant id in a custom HTTP header.
Because the tenant id changes during the session, you probably want to create a custom Breeze ajax adapter (wrap the one you're using now) that sets this header dynamically during its implementation of the ajax method.
On the server you fish the header out of the request.
MAKE SURE YOU ARE VALIDATING USER AND HEADER ON THE SERVER