我使用此命令在 docker 容器中运行 keycloak(我也尝试过版本 24)
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:23.0 start-dev
当我访问该网址时
http://localhost:8080/realms/my_app/protocol/openid-connect/auth?response_type=code&scope=openid&redirect_uri=https://www.google.com/&client_id=my_app
在我使用邮递员发出获取令牌的请求后立即获得授权码
curl -X POST \
http://localhost:8080/realms/my_app/protocol/openid-connect/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'client_id=my_app' \
-d 'redirect_uri=https://www.google.com/' \
-d 'code= {codeFromUrlEntered}'
但是我不断收到错误:
error="invalid_code", grant_type="authorization_code", code_id="594c3aa2-cec6-488d-8026-24b9fb6721e5", client_auth_method="client-secret"
我第一次使用授权码就可以确认。
看来配置中存在一些误解。
#1 领域和客户端 ID 之间似乎存在混淆。您已将 client_id 设置为 my_app,它实际上指的是 URL http://localhost:8080/realms/my_app 中的领域。 client_id 应对应于客户端标识符,而不是领域名称。
#2 redirect_uri 已设置为 https://www.google.com/。为了安全性和功能性,redirect_uri 应与本地服务器或生产环境的 URL 一致,而不是与 google.com 等不相关的网站一致。
#3 授权代码流程(grant_type=authorization_code)需要用户登录步骤;因此,直接使用 cURL 来完成此过程是不可行的。此流程需要提供本地服务器来通过重定向 URL 处理代码交换。
由
docker compose
在这里
领域:
my_app
客户:
my_client
凭证
username: user1
password: 1234
"authorization_endpoint": "http://localhost:8080/realms/my_app/protocol/openid-connect/auth",
"token_endpoint": "http://localhost:8080/realms/my_app/protocol/openid-connect/token",
另存为
server.js
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;
const KEYCLOAK_CLIENT_ID = "my_client";
const KEYCLOAK_CLIENT_SECRET = "oCDrud4nUSxp6ol56u9ZEJhdG3tsKji9"; // your client secret
const KEYCLOAK_REALM = "my_app";
const KEYCLOAK_SERVER_URL = "http://localhost:8080";
const REDIRECT_URI = "http://localhost:3000/callback"; // your client's redirect URI
app.get('/login', (req, res) => {
const authUrl = `${KEYCLOAK_SERVER_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/auth?client_id=${encodeURIComponent(KEYCLOAK_CLIENT_ID)}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&response_type=code&scope=openid`;
res.redirect(authUrl);
});
app.get('/callback', async (req, res) => {
const { code } = req.query;
try {
const response = await axios.post(`${KEYCLOAK_SERVER_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token`, new URLSearchParams({
client_id: KEYCLOAK_CLIENT_ID,
client_secret: KEYCLOAK_CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code',
code,
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const { access_token, refresh_token, id_token } = response.data;
// Here you can store/use the tokens as needed
res.json({ access_token, refresh_token, id_token });
} catch (error) {
res.status(500).json({ error: error.toString() });
}
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
npm install express axios
node server.js
打开浏览器并访问此 URL。
http://localhost:3000/login
凭证
username: user1
password: 1234
将在浏览器中显示令牌