问题
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