Unable to create a new user using keycloak: 403 unknown_error - keycloak

This question has been asked before but none of the solutions has worked for me.
I've created a bash script to register a new user on my key cloak server. The bashscript is shown below:
#!/bin/sh
RESULT=$(curl -s --location --request POST 'http://localhost:8180/auth/realms/master/protocol/openid-connect/token' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=client_credentials' --data-urlencode 'client_id=admin-cli' --data-urlencode 'client_secret=12345678-12a3-1234-bc12-d12345678910');
TOKEN=$(echo $(echo "$RESULT" | jq .access_token))
TOKEN=$(echo "${TOKEN//\"}")
echo "$TOKEN\n\n"
USER=$(curl --location -v --request POST 'http://localhost:8180/auth/admin/realms/MyMarketplace/users' --header 'Content-Type: application/json' --header "Authorization: Bearer $TOKEN" --data-raw '{"enabled":"true", "username":"app-user"}');
echo $USER;
When I run this script, I keep getting the following output:
HTTP/1.1 403 Forbidden
< Connection: keep-alive
< X-XSS-Protection: 1; mode=block
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Content-Type: application/json
< Content-Length: 25
< Date: Fri, 17 Jul 2020 20:11:40 GMT
<
{ [25 bytes data]
100 66 100 25 100 41 974 1597 --:--:-- --:--:-- --:--:-- 1640
* Connection #0 to host localhost left intact
{"error":"unknown_error"}
I'm not sure why. Here's what I've tried:
I've made sure that the URL that I'm sending the request to is correct.
I've made sure that the username is unique and that I've provided all mandatory fields.
In the MyMarketplace realm, I added a realm role 'admin' with a client role 'manage-users' from client 'realm-management' and I assigned this realm role to my client's scope (as per the steps given in this answer)
In the Master realm, I assigned the manage-users role to the client admin-cli's scope.
None of these has yielded any results so I've run out of options.
I would greatly appreciate it if someone could help me understand what I'm missing.

use http://localhost:8180/auth/realms/MyMarketplace/protocol/openid-connect/token to obtain access_token and give admin-cli client manage-users role from realm-management client in Service Account Roles and then call http://localhost:8180/auth/admin/realms/MyMarketplace/users with access token in header and "enabled": true, "username": "user" body.
make sure your enabled boolean look like this one and dont use "" I think keycloak reads your request as String.
I think it will fix your problem.

Use and configure admin-cli client as you did, but in MyMarketplace realm. Don't use the master realm.

Related

cURL - Setting Content-Type Header is not working?

I'm trying to set the content-type header of my cURL request to application/json.
This is the request I'm using in cmd (I left out the Json-Body):
curl -v -X POST http://localhost:40071/api/Sale --header 'Content-Type: application/json' -d '{[Json Body]}'
When running this command, cURL is logging the following:
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:40071...
* Connected to localhost (127.0.0.1) port 40071 (#0)
> POST /api/Sale HTTP/1.1
> Host: localhost:40071
> User-Agent: curl/7.79.1
> Accept: */*
> Content-Length: 332
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Date: Tue, 09 Nov 2021 11:18:33 GMT
< Content-length: 0
<
My REST server is running into an exception because of HTTP 415 Unsupported Media Type.
It seems as if cURL did not make use of my "--header" parameter?
Because the log is showing that Content-Type: application/x-www-form-urlencoded was chosen.
I also tried it with the abbreviated parameter "-h".
Seems duplicate question, for more examples, refer here.
How to send a header using a HTTP request through a cURL call?
curl -X POST mockbin.org/request -H "Accept: application/json"

Keycloak API to create users returns a 403 Forbidden

Experimenting with Keycloak as an Identity Provider. I'm running it by using the ./standalone.sh script.
So, I obtain the access_token like this:
curl --request POST \
--url http://localhost:8080/auth/realms/master/protocol/openid-connect/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=admin-cli \
--data client_secret=<the-client-secret-under-master-realm-for-admin-cli-client>
Response:
{
"access_token": "the-access-token",
"expires_in": 60,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0,
"scope": "profile email"
}
And then quickly, under my test-realm I try to create a user as follows:
curl --request POST \
--url http://localhost:8080/auth/admin/realms/test-realm/users \
--header 'Authorization: Bearer the-access-token' \
--header 'Content-Type: application/json' \
--data '{
"firstName": "Sergey",
"lastName": "Kargopolov",
"email": "test#test.com",
"enabled": "true",
"username": "app-user"
}'
And I get hit with a 403:
< HTTP/1.1 403 Forbidden
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Referrer-Policy: no-referrer
< Date: Thu, 28 Jan 2021 23:43:57 GMT
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Content-Type-Options: nosniff
< Content-Type: application/json
< Content-Length: 25
Is there something I'm missing? I'm following this tutorial and I'm doing everything exactly as described!
Edit: I tried the Password Grant way to obtain the Bearer Token and that worked, but NOT the client secret way. I obviously prefer the client secret way (which is where I'm stuck currently). What could be the issue here?
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.
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.
If you click on the admin user > roles, you would see the following:
The admin user, has already the admin role.
Edit: I tried the Password Grant way to obtain the Bearer Token and
that worked, but NOT the client secret way. I obviously prefer the
client secret way (which is where I'm stuck currently). What could be
the issue here?
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.
Now the problem is that Service-account-admin-cli user is hidden in the User section. Nonetheless, you can do the following:
Request again the admin token with your setup;
Go to Master Realm > Clients > admin-cli > Session > Click on [Show Session]:
click on the user service-account-admin-cli;
Go to Role Mappings;
Assign the admin role;
Since the service-account-admin-cli user has now the admin role, a token request on that user's behalf will contain the necessary privileges to create the users.
If the aforementioned does not work, then do the following go to:
Realm Master;
Clients > admin-cli;
Go to Mappers;
Click on [Create];
As Mapper Type select "Hardcoded Role";
Click on Select Role and selection "admin";
Click [Save].

Creating a Milestone for a Github Project via REST

I would like to use the REST API of Github to manage the milestones and labels of some of my repositories, but I constantly fail to create new milestones or labels via REST. What do I miss?
I enable 2FA for my account and also create a personal access token, as it is described in Other Authentication Methods
For example I try to create a new milestone with this cURL command:
curl -X POST -v \
-H "Authorization: token MyPersonalAccessToken" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.github.v3+json" \
-d '{"title": "1", "state": "open", "description": "Milestone", "due_on": "2025-10-09T23:39:01Z"}' \
https://api.github.com/repos/obfischer/boxsack/milestones
I tried various other variants but all seems to be wrong. At least I always get only a 404 Not Found. According to the Github documentation this could also mean that my authentication failed, as Github returns a 404 Not Found response code to protect user data instead of returning a 401 Unauthorized.
But I am pretty sure that the authentication via the Person Access Token is working as I can see a user specific rate-limit headers in the response:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
Does someone have a clue why I can't create a milestone via REST?
Maybe your personal access token doesn't have the repo scope. I've just tested to send the request with a token without that scope & it also returns 404 :
< HTTP/1.1 404 Not Found
< Date: Sat, 26 Oct 2019 11:07:31 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 125
< Server: GitHub.com
< Status: 404 Not Found
< X-RateLimit-Limit: 5000
< X-RateLimit-Remaining: 4989
< X-RateLimit-Reset: 1572091544
< X-OAuth-Scopes: [Here there should be repo] <================
< X-Accepted-OAuth-Scopes:
< X-GitHub-Media-Type: github.v3; format=json
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type
< Access-Control-Allow-Origin: *
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< X-Frame-Options: deny
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Content-Security-Policy: default-src 'none'
< X-GitHub-Request-Id: 87B2:23EED:36F2B7F:42647AE:5DB428F3
<
{
"message": "Not Found",
"documentation_url": "https://developer.github.com/v3/issues/milestones/#create-a-milestone"
}

POST request with CSRF works in Postman but fails in cURL

I make a POST request to REST API to upload a file. In Postman everything works fine. I add Basic authorization and custom CSRF (XSRF) token which I get from the server.
I want to make the same using cURL. I copied the code from Postman, and it does not seem to work.
I believe that the error is related to CSRF because if I turn off CSRF on server and make the same cURL call without CSRF token, everything works fine.
Now some more details:
That's what the command for cURL which Postman gives:
curl -X POST -H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" -H "Authorization: Basic bbhjbjb=" -H "Cache-Control: no-cache" -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "package=#C:\Downloads\hello-world.zip" "http://host:port/api/import"
And that's the reply I get with --verbose
timeout on name lookup is not supported
Trying ::1...
Connected to localhost (::1) port 7777 (#0)
POST /api/import HTTP/1.1
Host: localhost:7777
User-Agent: curl/7.47.1
Accept: /
XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42
Authorization: Basic bbhjbjb=
Cache-Control: no-cache
Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47
Content-Length: 31281
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW;
boundary=------------------------742d3475ac5f6aba
< HTTP/1.1 302 Found
< Set-Cookie: JSESSIONID=1qfjmbntrthxll;Path=/api < Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Set-Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o;Path=/;Expires=Thu, 15-Dec-2016 10:28:46 GMT
< XSRF: b29bd143-cc80-49ad-b495-711125678o < Location:
http://localhost:7777/api/login/error.jsp?errorMessage=Access Denied
< Content-Length: 0
< Server: Jetty(9.2.17.v20160517)
HTTP error before end of send, stop sending
Closing connection 0
I am probably missing something very obvious here, but don't know what yet.
Looks like I am redirected to login page, not being authenticated correctly, but do not know why (I do send XSRF in cURL). I tried also adding sessionid in cURL - also didn't work.
Any ideas and directions about where to search would be very appreciated!!!
As mentioned in this post, add following option
--cookie "csrftoken=XXXXXX;sessionid=YYYYYYY"
along with
-H "X-CSRFToken: XXXXX"
It is unclear how your server side code is implemented. One visible difference can be seen here is the UserAgent string in request header User-Agent: curl/7.47.1. You may try with adding -A "Mozilla/5.0" with your curl request.
About the comment above regarding XSRF 1-time token; Your server is returning Set-Cookie header in response. It can happen that the postman is using that as cookie for second time request, and that's why it works for it over and over. You can try adding -H "Cookie: XSRF=b29bd143-cc80-49ad-b495-711125678o" at the end of your curl and see if that makes any difference.
Those are all wild guess. Better you add some code at your server side that can print the request-headers. Then make two requests, one from curl and other one from postman. After that check the difference between the request headers. That will give you some clue.
In the end it turned out that the session id was required (adding JSESSIONID in cURL solved the problem).
Without more info on the server side code, I'm not sure either. If you're making your call from cURL, and not Postman, do you really need the Postman-Token header? Maybe it will work if you remove -H "Postman-Token: 76a7a43b-f407-15a2-aaff-5242b44d0f47" from the code.
curl -X POST \
-H "XSRF: 79f51981-8e85-4e26-be1b-bf63aed92a42" \
-H "Authorization: Basic bbhjbjb=" \
-H "Cache-Control: no-cache" \
-H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" \
-F "package=#C:\Downloads\hello-world.zip" \
"http://host:port/api/import"

Crowd Rest API usage

I am trying to add 100 of users to a group in crowd and I want to automate it using curl and crowd's rest api. At first I am just trying to add a singleuser to a group and then auotmate it using shell script. Following this document, I pass the command as
curl -X POST{"name":"groupname"} -ik -u application:password-H 'Content-Type: application/json' -H 'Accept: application/json' https://localhost/crowd/rest/usermanagement/1/user/group/direct?username=username.
I am getting the following error.
HTTP/1.1 405 Method Not Allowed
Server: Apache-Coyote/1.1
X-Embedded-Crowd-Version: Crowd/2.8.3
X-Crowd-User-Management-Version: 1.4
Set-Cookie: JSESSIONID=17490A660F9A2267B378CD767CEADDF8; Path=/crowd/; Secure; HttpOnly
Allow: HEAD,DELETE,POST,GET,OPTIONS
X-Content-Type-Options: nosniff
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1013
Date: Mon, 29 Jun 2015 02:56:15 GMT
FYI: I am using a application to authenticate against crowd via rest. Please suggest on what I need to do and how should I do.
P.S. I also need to figure out on adding hudreds of groups to crowd too.
You are missing a space between POST and your data.
To post data use:
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server,
in the same way that a browser does when a user has filled in an HTML
form and presses the submit button. This will cause curl to pass the
data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
So the command should be:
curl -X POST -d {"name":"groupname"} -ik -u application:password -H 'Content-Type: application/json' -H 'Accept: application/json' https://localhost/crowd/rest/usermanagement/1/user/group/direct?username=username
From Crowds Docs,
Authentication Access to all resources (using any method) requires the
client to be authenticated via basic authentication. See RFC 2617.
Your environment must retain cookies set by the Crowd server and
retransmit them on subsequent calls, otherwise Crowd will have to
re-authenticate the application on every REST call.
So first authenticate your self and store the cookies, (make note of --cookie-jar parameter)
curl -i -u application_name:application_password --data '{"value": "my_password"}' http://localhost:8095/crowd/rest/usermanagement/1/authentication?username=my_username --header 'Content-Type: application/json' --header 'Accept: application/json' --cookie-jar cookies.txt
So as per docs on subsequent calls use the cookies (using --cookie parameter)
curl -X POST -d {"name":"groupname"} -ik -u application:password -H 'Content-Type: application/json' -H 'Accept: application/json' https://localhost/crowd/rest/usermanagement/1/user/group/direct?username=username --cookie cookies.txt