如何配置 Keycloak 并通过 REST API 完成所有步骤并获得 JWT?
Posted
技术标签:
【中文标题】如何配置 Keycloak 并通过 REST API 完成所有步骤并获得 JWT?【英文标题】:How do I configure Keycloak and get a JWT with all steps done through the REST API? 【发布时间】:2021-04-04 05:08:22 【问题描述】:我需要为在 Docker 中运行的 Keycloak 配置一个领域、一个具有凭据的用户和一个客户端,然后像 blog post 一样获取 JWT。如果我使用如图所示的 UI,它可以工作,但我需要通过 Keycloak REST API 自动执行所有步骤。当我这样做时,所有步骤似乎都有效,但获取 JWT 失败。
我像这样在 Docker 中运行 Keycloak
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
我从主域获取访问令牌
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'
然后我创建我的领域(命名为testrealm
)
POST -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d @"$REALM_FILE" "http://localhost:8080/auth/admin/realms"
然后我创建一个具有凭据的用户:
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]
我可以在 UI 中看到新用户,并在新用户凭据中看到一个输入密码的条目。
我创建了一个客户端(名为testclient
)
POST -H "Authorization: Bearer $ACCESS_TOKEN" -H "Content-Type: application/json" -d @"$CLIENT_FILE" "http://localhost:8080/auth/admin/realms/testrealm/clients"
我获得了修改新客户端所需的 ID
GET -H "Accept: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" "http://localhost:8080/auth/admin/realms/testrealm/authentication/flows"
从别名 browser
中提取 BROWSER_ID,从别名 direct grant
中提取 DIRECT_GRANT_ID。
我更新客户端,将Access Type
更改为confidential
,并使用Authentication Flow Overrides
更改Browser Flow
和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"
数据在哪里
"publicClient": false,
"clientAuthenticatorType": "client-secret",
"authenticationFlowBindingOverrides":
"direct_grant":"$DIRECT_GRANT_ID",
"browser":"$BROWSER_ID"
我通过
获取客户端密码GET -H "Accept: application/json" -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:8080/auth/admin/realms/testrealm/clients/$CLIENT_ID/client-secret
此时,如果我进入 UI,它会显示我返回的相同客户端密码,并且客户端 Access Type
是 confidential
,而 Authentication Flow Overrides
设置为 browser
和 direct grant
。一切看起来都是正确的。现在,Keycloak 服务器的配置应该与通过 UI 完成时的配置相同,如博文所示。
当我使用帖子中显示的 curl 命令获取 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'
给出一个错误,说 https 是必需的。
"error":"invalid_request","error_description":"HTTPS required"
但通过 UI 完成配置时不需要 https。事实上所有的请求都是通过 http 发送的,而不是 https。
然后使用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'
我收到此错误
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
如果我通过 UI 配置 Keycloak,curl 命令可以工作,所以我在使用REST API
时一定错过了一些东西。 Keycloak 文档没有显示这个用例,所以它们在这里没有帮助。
有人知道我在使用REST API
时错过了什么吗?
【问题讨论】:
从 http 更改为 https 时,我应该将端口更改为 8443。该端口必须从 docker 共享,如下面的答案所示。 【参考方案1】:发布 Keycloak 容器的 8443 端口。将有带有自签名证书的 https(因此在您的请求中禁用 tls 验证):
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 将在https://localhost:8443
上提供。见Keycloak Docker HTTPS required
【讨论】:
好收获。这仍然留下了一个谜,为什么当我通过 UI 配置时我可以使用端口 8080,但当我使用 REST API 配置时我必须使用端口 8443。以上是关于如何配置 Keycloak 并通过 REST API 完成所有步骤并获得 JWT?的主要内容,如果未能解决你的问题,请参考以下文章
通过 REST 与 Keycloak 保护的后端进行后端到后端通信
如何在没有管理员帐户的情况下通过 REST 获取 Keycloak 用户
如何通过 REST API 将 Keycloak 领域角色添加到组
如何通过执行操作电子邮件通过 keycloak admin rest api 更新密码
使用 JAVA 通过 REST API 集成 Keycloak 时在 toRepresentation() 处获取 404