问题
I need to configure Keycloak running in Docker with a realm, a user with credentials, and a client and then get a JWT as in this blog post. If I use the UI as shown it works, but I need to automate all steps through the Keycloak REST API. When I do that all steps seem to work but getting a JWT fails.
I run Keycloak in Docker like this
docker network create keycloak-network
docker run --name mysql -d \
--net keycloak-network \
-e MYSQL_DATABASE=keycloak \
-e MYSQL_USER=keycloak \
-e MYSQL_PASSWORD=password \
-e MYSQL_ROOT_PASSWORD=root_password \
mysql:8.0.22
docker run -d -it \
-e DB_VENDOR=mysql \
-e KEYCLOAK_USER=admin \
-e KEYCLOAK_PASSWORD=admin \
--name keycloak \
--net keycloak-network \
-p 8080:8080 \
jboss/keycloak:11.0.3
I obtain an access token from the master realm
POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin" -d "password=admin" -d "grant_type=password" -d 'client_id=admin-cli' "http://localhost:8080/auth/realms/master/protocol/openid-connect/token"|jq -r '.access_token'
Then I create my realm (named testrealm)
POST -H "Authorization: Bearer ${ACCESS_TOKEN}" -H "Content-Type: application/json" -d @"${REALM_FILE}" "http://localhost:8080/auth/admin/realms"
Then I create a user with credentials:
POST "http://localhost:8080/auth/admin/realms/testrealm/users" --header 'Content-Type: application/json' -H "Authorization: Bearer ${ACCESS_TOKEN}" -d {"enabled":true,"username":"testuser","email":"test.user@gmail.com","firstName":"test","lastName":"user","credentials":[{"type":"password","value":"abc123","temporary":false}]}
I can see the new user in the UI and an entry in the new users credentials with Type password.
I create a client (named testclient)
POST -H "Authorization: Bearer ${ACCESS_TOKEN}" -H "Content-Type: application/json" -d @"${CLIENT_FILE}" "http://localhost:8080/auth/admin/realms/testrealm/clients"
I get the necessary ids to modify the new client with
GET -H "Accept: application/json" -H "Authorization: Bearer ${ACCESS_TOKEN}" "http://localhost:8080/auth/admin/realms/testrealm/authentication/flows"
extracting the BROWSER_ID from the Alias browser and the DIRECT_GRANT_ID from the Alias direct grant.
I update the client changing the Access Type to confidential and with Authentication Flow Overrides for Browser Flow and Direct Grant Flow
PUT -H "Authorization: Bearer ${ACCESS_TOKEN}" -H "Content-Type: application/json" --data @client.update.json "http://localhost:8080/auth/admin/realms/testrealm/clients/${clientId}"
where the data is
{
"publicClient": false,
"clientAuthenticatorType": "client-secret",
"authenticationFlowBindingOverrides": {
"direct_grant":"${DIRECT_GRANT_ID}",
"browser":"${BROWSER_ID}"
}
}
I get the client secret with
GET -H "Accept: application/json" -H "Authorization: Bearer ${ACCESS_TOKEN}" http://localhost:8080/auth/admin/realms/testrealm/clients/${CLIENT_ID}/client-secret
At this point if I go into the UI it shows the same client secret that I get back and that the client Access Type is confidential and the Authentication Flow Overrides were set to browser and direct grant. Everything looks correct. The Keycloak server should now be configured the same as when done through the UI as shown in the post.
When I use the curl command as shown in the post to get a JWT
curl -L -X POST http://localhost:8080/auth/realms/testrealm/protocol/openid-connect/token -H 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'client_id=testclient' --data-urlencode 'grant_type=password' --data-urlencode 'client_secret=544479de-72a4-44c7-9420-3a142cd699c6' --data-urlencode 'scope=openid' --data-urlencode 'username=testuser' --data-urlencode 'password=abc123'
gives an error saying that https is required.
{"error":"invalid_request","error_description":"HTTPS required"}
But https is not required when the configuration was done through the UI. In fact all requests have been sent through http, not https.
Then using https
curl -L -X POST https://localhost:8080/auth/realms/testrealm/protocol/openid-connect/token -H 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'client_id=testclient' --data-urlencode 'grant_type=password' --data-urlencode 'client_secret=544479de-72a4-44c7-9420-3a142cd699c6' --data-urlencode 'scope=openid' --data-urlencode 'username=testuser' --data-urlencode 'password=abc123'
I get this error
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
If I configure Keycloak through the UI the curl command works so I must have missed something when using the REST API. The Keycloak docs don't show this use case so they are no help here.
Does anyone know what I've missed when using the REST API?
回答1:
Publish port 8443 of the Keycloak container. There will be https with self signed cert (so disable tls verification in your requests):
docker run -d -it \
-e DB_VENDOR=mysql \
-e KEYCLOAK_USER=admin \
-e KEYCLOAK_PASSWORD=admin \
--name keycloak \
--net keycloak-network \
-p 8443:8443 \
jboss/keycloak:11.0.3
Keycloak will be available on https://localhost:8443. See Keycloak Docker HTTPS required
来源:https://stackoverflow.com/questions/65460489/how-do-i-configure-keycloak-and-get-a-jwt-with-all-steps-done-through-the-rest-a