Keycloak: updating master realm via Admin API - keycloak

I tried to edit the master realm of my keycloak standalone installation via the admin api interface. I already created a whole realm and everything works fine. If I now try to update the client roles inside the master realm the server responds with "No content" but the data is not changed. What do I wrong?
relative url:
/auth/admin/realms/master/groups/654dc766-d307-4e44-9b6c-d53f16a2eedf
body:
{
"id":"654dc766-d307-4e44-9b6c-d53f16a2eedf",
"name":"TECHNICAL",
"path":"/TECHNICAL",
"attributes":null,
"realmRoles":null,
"clientRoles":{
"test-client-realm":[
"manage-realm",
"manage-users",
"view-realm",
"view-users"
]
},
"subGroups":[]
}

updating client goes via PUT /admin/realms/{realm}/clients/{id} and not as stated in your question. In your example you would update a group.

Related

NextJS app builds fine locally but fails when deploying to Vercel (FetchError)

Fairly new to web dev and I'm trying to build fullstack for the first time.
I've built a simple blog using Next as frontend and Strapi as the backend. The app works fine locally but I'm stuck at deployment. I figure it's some sort of a connection issue with the backend (which is still running locally) or I'm totally missing something on the frontend. Is it that I need to make Strapi available online first and then use that domain in my fetch?
Vercel throws this error during build:
FetchError: request to http://localhost:1337/api/places?populate=%2A failed, reason: connect ECONNREFUSED 127.0.0.1:1337
at ClientRequest.
This is how I'm getting data from Strapi
export async function getStaticProps() {
// const postRes = await axios.get("http://localhost:1337/api/articles?populate=*");
const reviewsRes = await fetchAPI("/articles", { populate: ["image", "place"] });
return {
// props: { reviews: postRes.data.data },
props: { reviews: reviewsRes.data },
};
}
I'm also using this line to bring in images and data
backgroundImage: `url(${process.env.NEXT_PUBLIC_STRAPI_API_URL}${place.attributes.image.data.attributes.url})`,
I've also tried changing localhost to 127.0.0.1:1337 in my env/config
You've actually answered your question in this line:
Is it that I need to make Strapi available online first and then use that domain in my fetch?
Yes! You have to deploy your Strapi backend first, and use the domain/URL inside your deployed NextJS frontend.
Strapi Deployment Documentation: https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment.html
What you're doing with the backgroundImage url is what you need to do to your data-fetching url.
Use that NEXT_PUBLIC_STRAPI_API_URL env variable so you don't have to change the code before deploying.
Locally you can have .env file in you NextJS root folder something like this
NEXT_PUBLIC_STRAPI_API_URL=http://localhost:1337/api
Then, once you've deployed the NextJS app to Vercel, you have to set the NEXT_PUBLIC_STRAPI_API_URL variable to the project setting.
Set env variables in Vercel: https://vercel.com/docs/concepts/projects/environment-variables
Welcome to web dev world! Hope it helps!

Netlify deploy can't connect to Heroku backend

I've built a wee program that works fine when I run it locally. I've deployed the backend to Heroku, and I can access that either by going straight to the URL (http://gymbud-tracker.herokuapp.com/users) or when running the frontend locally. So far so good.
However, when I run npm run-script build and deploy it to Netlify, something goes wrong, and any attempt to access the server gives me the following error in the console:
auth.js:37 Error: Network Error
at e.exports (createError.js:16)
at XMLHttpRequest.p.onerror (xhr.js:99)
The action that is pushing that error is the following, if it is relevant:
export const signin = (formData, history) => async (dispatch) => {
try {
const { data } = await api.signIn(formData);
dispatch({ type: AUTH, data });
history.push("../signedin");
} catch (error) {
console.log(error);
}
};
I've been tearing my hair out trying to work out what is changing when I build and deploy, but cannot work it out.
As I say, if I run the front end locally then it access the Heroku backend no problem - no errors, and working exactly as I'd expect. The API call is correct, I believe: const API = axios.create({baseURL: 'http://gymbud-tracker.herokuapp.com/' });
I wondered if it was an issue with network access to the MongoDB database that Heroku is linked to, but it's open to "0.0.0.0/0" (I've not taken any security precautions yet, don't kill me!). The MDB database is actually in the same collection as other projects I've used, that haven't had this problem at all.
Any ideas what I need to do?
The front end is live here: https://gym-bud.netlify.app/
And the whole thing is deployed to GitHub here: https://github.com/gordonmaloney/gymbud
Your issue is CORS (Cross-Origin Resource Sharing). When I visit your site and inspect the page, I see the following error in the JavaScript console which is how I know this:
This error essentially means that your public-facing application (running live on Netlify) is trying to make an HTTP request from your JavaScript front-end to your Heroku backend deployed on a different domain.
CORS dictates which requests from a frontend application are ALLOWED to make a request to your backend API.
What you need to do to fix this is to modify your Heroku application and have it return the appropriate Access-Control-Allow-Origin header. This article on MDN explains the header and how you can use it.
Here's a simple example of the header you could set on your Heroku backend to allow this to work:
Access-Control-Allow-Origin: *
Please be sure to read the MDN documentation, however, as this example will allow any front-end application to make requests to your Heroku backend when in reality, you'll likely want to restrict it to just the front-end domains you build.
God I feel so daft, but at least I've worked it out.
I looked at the console on a different browser (Edge), and it said it was blocking it because it was mixed origin, and I realised I had just missed out the s in the https on my API call, so it wasn't actually a cors issue (I don't think?), but just a typo on my part!
So I changed:
const API = axios.create({baseURL: 'http://gymbud-tracker.herokuapp.com' });
To this:
const API = axios.create({baseURL: 'https://gymbud-tracker.herokuapp.com' });
And now it is working perfectly ☺️
Thanks for your help! Even if it wasn't the issue here, I've definitely learned a lot more about cors on the way, so that's good

Is there an elegant way to clone a Keycloak realm with all its configurations (clients and roles) for a multitenant application?

I'm building a multitenant application and I'm using Keycloak for authentication and authorization.
Foreach each tenant, the idea is to have a dedicated Keycloak realm. Each tenant will have exactly the same roles and clients.
I have tried to export one existing realm, use it as template and import it for new tenant. Problem: I'm facing database constraint violation due to internal id.
Question: Is there an elegant way to achieve this, having a template to create a new realm ?
Be sure that the feature for uploading script is enabled. For a deployment with a docker-compose just add this:
command: -Dkeycloak.profile.feature.upload_scripts=enabled
Export your realm (the one to be used as model)
Remove all line containing "id:" and "_id:"
Search and replace template realm name by the new realm name
In Keycloak UI admin console, Add new realm, provide the file and that is all.
You can use the cleaned exported file as template.
Can't comment due to rep,
but I'd like to add to #Youssouf Maiga's answer,
that you should also modify any fields that contain values under "authenticationFlowBindingOverrides":
Replace any entries that have values assigned under "direct_grant" or "browser"
i.e
"authenticationFlowBindingOverrides": {
"direct_grant": "f5d1wb45e-27eb-4466-937439-9cc8a615ad65e",
"browser": "5b23141a1c-7af8d-410e-a9b451f-0eec12039c72e9"
},
replaced with
"authenticationFlowBindingOverrides": {},
I tried cloning my realm based on this and got an error saying:
"Unable to resolve auth flow binding override for: direct_grant" when importing the modified realm export.
Keycloak version 16.1.1
What you could do is configure everything using the Keycloak Terraform provider. That way you only have to define the configuration once, in code, and then apply it using Terraform. See for the documentation: https://registry.terraform.io/providers/mrparkers/keycloak/latest/docs
An advantage of this is that you can put your code in an SCM tool (e.g. git), so you can track your changes, and go back to a previous version if necessary.

Keycloak Admin CLI - Updating a realm with JSON file

Objective:
Our objective is to update the entire realm provided a json file.
Problem:
The issue at hand is we cannot seem to update the realm entirely to include the client changes as well.
Actions taken:
Option 1:
Based on the Keycloak Admin CLI documentation, a Keycloak realm can be updated from a JSON file using the following command:
kcadm.sh update realms/demorealm -f demorealm.json
However, when making an update to a property within the clients section of the JSON file (i.e. a client's description), the change is not reflected within the Keycloak realm.
We also tried to take a look at the kcadm.sh help update . We tried to utilize the merge flag (Merge new values with existing configuration on the server. Merge is automatically enabled unless --file is specified) . We do have a file specified and therefore tried to enable it using the flag - but to no success. The clients did not change as expected.
Option 2:
We have tried the partial import command found in Keycloak documentation
$ kcadm.sh create partialImport -r demorealm -s ifResourceExists=OVERWRITE-o -f demorealm.json
With the ifResourceExists set to OVERWRITE, it accurately changes clients. However, it alters other Realm configurations such as assigned users roles. Ex: After manually creating a new user via the Keycloak UI and setting roles for the user, the roles are lost after running the command with the OVERWRITE flag set. Setting the ifResourceExists to SKIP does not properly update values for a client as it is skipped altogether.
Question:
Is it possible, either with a different command or different flags, to update a Keycloak realm in its entirety with a single Keycloak admin command? Neither Option 1 or Option 2 listed above worked for us. We want to avoid making individual update client calls when updating the Realm.
Notes:
We have properly authenticated and confirmed that changes made at the realm level are reflected in Keycloak.
After further research, the approach we decided to go with is to update realm level settings with:
kcadm.sh update realms/demorealm -f demorealm.json
We then iterate over the clients and add/update them with:
kcadm.sh update clients/{clients-uuid} -f clientfile.json
Since the previous command does not update client roles, we must then use the following command to add the roles:
kcadm.sh update clients/{clients-uuid}/roles/{role-name} -f rolefile.json
Finally, to add in composite roles, we use this command:
kcadm.sh add-roles --cclientid {clientID} --rid {id of client role} --rolename {name of role to add}

How to make Amplify CloudFormation aware of changes made outside of it

I ended up on a point that Amplify fails to push any change I made, with a non existent UserPool clientId exception.
Something like
Resource Name: XXXXXXXXXXX (AWS::Cognito::UserPoolClient) Event Type:
update Reason: User pool client does not exist. (Service:
AWSCognitoIdentityProviderService; Status Code: 400; Error Code:
ResourceNotFoundException; Request ID: YYYYYYYYYYYYYYYYYY URL:
https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/xxxxxxxxxxx
I have explained my whole journey on a Github issue for Amplify Cli that you can see here, unfortunately, I'm not getting much support from Amplify team, as you can see there.
I also have created a StackOverflow question with the initial problem I was facing, that you can check here
After digging more into this issue for 3-4 long days, as this issue is blocking my deployment, I came to a guess to what happened:
I have added auth to my amplify project months ago
Eventually, I noticed one of the created clients were not being used, so I have deleted it, using the Cognito console.
I had not updated the auth during months
Now that I have introduced the social authentication Amplify tried to update it and because of the client Id not existing anymore, it can't and raises the mentioned error.
Now, anything I try to update it fails, and I guess the reason is this out of sync between what Amplify expects and what actually is the infra.
Every time I pull --restore my environment, I get my amplify-meta.json updated with this invalid client Id (and yes, I have tried changing it on the local amplify-meta.json and pushing it), something like:
"auth": {
"myproject": {
"service": "Cognito",
"providerPlugin": "awscloudformation",
"output": {
"GoogleWebClient": "111111111.apps.googleusercontent.com",
"AppClientSecret": "aaaaaaaaaaa",
"UserPoolId": "region-pooId",
"AppClientIDWeb": "VALID ID",
"AppClientID": "INVALID ID",
"FacebookWebClient": "2222222222",
"IdentityPoolId": "region:Id",
"IdentityPoolName": "myproject__env",
"UserPoolName": "mypoolname"
},
"lastPushTimeStamp": "2020-05-13T20:48:29.797Z",
"providerMetadata": {
"s3TemplateURL": "https://s3.amazonaws.com/myproject-deployment/amplify-cfn-templates/auth/lexis-cloudformation-template.yml",
"logicalId": "authmyproject"
},
"lastPushDirHash": "XXXXXXXXXXXXXX="
}
},
I have a different valid ClientId on my Cognito, so on my last resort, what I have tried is going direct to the S3TemplateURL pointed on this code and updating it there to the valid one, my guess was that this file was the single point of truth for Amplify.
But no success, still getting the same wrong Id after pull restore.
Any idea how can I make Amplify in sync again? Making it aware that this ClientId doesn't exist anymore and just getting rid of it on the CloudFormation/Templates?
Amplify Cli is not supporting this feature.
I had the same problem.
I updated Appsync and Cognitor in the cloud and I cannot pull the changes to my project.
When I run amplify status, it said no changes.
So I contacted AWS support and they said this is coming feature.
The solution is to change everything in amplify cli and manage amplify in the console. Don't change anything in the cloud.