我有一个项目,有一个Python/Django后端。它位于密钥斗篷之后,用于身份验证。一切正常,用户可以使用Keyloak登录。
我们有一个客户端需要从后端访问一些端点的用例。我们希望为客户端提供某种类型的API密钥,这样他们就可以使用Keyloak进行身份验证,并以编程方式到达后端端点。在进行了一些研究之后,我们想到了使用离线令牌。我们能够获得令牌,并正在尝试将访问令牌添加为承载令牌。问题是我们无法通过登录屏幕。
我们使用的是Keyloak 17.0.0。
以下是在Python中的工作流程:
# Get the token
data = {
"client_id": <id>,
"client_secret": <secret>,
"username": "admin",
"password": "foo",
"grant_type": "password",
"scope": "openid offline_access"
}
response = requests.post('http://keycloak:8080/realms/<realm>/protocol/openid-connect/token', headers={'Content-Type': 'application/x-www-form-urlencoded'}, data=data)
# What is returned in the response
{
"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkWVQ3eWJOdWM3ODN5OU53d3VabmdTaHNSMV83T0xtQ2E5NW5HZHh5bXZvIn0.eyJleHAiOjE2NjI3NDU5NjgsImlhdCI6MTY2Mjc0NTY2OCwianRpIjoiZjcyZDBhYWUtOGFlMy00NjA1LTgzMWYtYzdiN2YzN2E2MzY1IiwiaXNzIjoiaHR0cDovL2tleWNsb2FrOjgwODAvcmVhbG1zL2FyY2FuZS1maXJlIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjJmNzM5ZGQ1LTQxZmUtNDVmNy1hYzBjLTM2NTU4N2MyNTE3MyIsInR5cCI6IkJlYXJlciIsImF6cCI6Im5naW54Iiwic2Vzc2lvbl9zdGF0ZSI6IjVjMGIzNGM2LTc2YWItNDJlNy04ZjBjLTljODEzNzA4ZjcwZCIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1hcmNhbmUtZmlyZSIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIG9mZmxpbmVfYWNjZXNzIGVtYWlsIiwic2lkIjoiNWMwYjM0YzYtNzZhYi00MmU3LThmMGMtOWM4MTM3MDhmNzBkIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiQ2hyaXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJDaHJpcyJ9.J3oPEDWw_c-L6jMySSBF1uNV9mjl7d8AFwky8kN71qhTEJLDJFWKznIQ0sAMK8pGenbYOQFGDnAiL5E5BGh5g97jkv-PK1xSsvjKjIEAJuH15FGIeHB8RSth7ZYPcca-2kzRsqfs9ueeKbe1IAMlMcFdKgX3qJa3MPsLLYWVBI5QbxTf068sWxAoWNWCQzYfyTnsZKnnbGEHzMyHyTjKaFfCHj8Y2lTw1RXeEVdts2ck8OVg5B66NHxu4KHQqnS2t3EhhX-vsovctrZ-yyX_KXkv9uaZ8OUjbsPcAFr0Ta8vcK5ay-FyXfmcApwp6JptNBcL4M54OHcYAV3wmJS5Tg",
"expires_in":300,
"refresh_expires_in":0,
"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJlMWI1ZjRmNC0xY2RiLTQwZmUtYWI0OS0yODFmNWExNzE1Y2YifQ.eyJpYXQiOjE2NjI3NDU2NjgsImp0aSI6IjRkMDUwMWQyLTEwYzktNDcwYS1iNmExLWNmZTE3MGUwMzc5YyIsImlzcyI6Imh0dHA6Ly9rZXljbG9hazo4MDgwL3JlYWxtcy9hcmNhbmUtZmlyZSIsImF1ZCI6Imh0dHA6Ly9rZXljbG9hazo4MDgwL3JlYWxtcy9hcmNhbmUtZmlyZSIsInN1YiI6IjJmNzM5ZGQ1LTQxZmUtNDVmNy1hYzBjLTM2NTU4N2MyNTE3MyIsInR5cCI6Ik9mZmxpbmUiLCJhenAiOiJuZ2lueCIsInNlc3Npb25fc3RhdGUiOiI1YzBiMzRjNi03NmFiLTQyZTctOGYwYy05YzgxMzcwOGY3MGQiLCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIG9mZmxpbmVfYWNjZXNzIGVtYWlsIiwic2lkIjoiNWMwYjM0YzYtNzZhYi00MmU3LThmMGMtOWM4MTM3MDhmNzBkIn0.DOu_zKq5WFI4PcTn5Qpe-VFwOj-aLtvc3q9SACs51Ew",
"token_type":"Bearer",
"id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkWVQ3eWJOdWM3ODN5OU53d3VabmdTaHNSMV83T0xtQ2E5NW5HZHh5bXZvIn0.eyJleHAiOjE2NjI3NDU5NjgsImlhdCI6MTY2Mjc0NTY2OCwiYXV0aF90aW1lIjowLCJqdGkiOiI0MDI5ZmI1ZC05ZDQwLTQ5NTQtYmNiMC02MmYzOTU2YjdmOTIiLCJpc3MiOiJodHRwOi8va2V5Y2xvYWs6ODA4MC9yZWFsbXMvYXJjYW5lLWZpcmUiLCJhdWQiOiJuZ2lueCIsInN1YiI6IjJmNzM5ZGQ1LTQxZmUtNDVmNy1hYzBjLTM2NTU4N2MyNTE3MyIsInR5cCI6IklEIiwiYXpwIjoibmdpbngiLCJzZXNzaW9uX3N0YXRlIjoiNWMwYjM0YzYtNzZhYi00MmU3LThmMGMtOWM4MTM3MDhmNzBkIiwiYXRfaGFzaCI6InNuVW11a3I1VUZWbTRyYVlxM1FxVlEiLCJhY3IiOiIxIiwic2lkIjoiNWMwYjM0YzYtNzZhYi00MmU3LThmMGMtOWM4MTM3MDhmNzBkIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiQ2hyaXMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJDaHJpcyJ9.AUGLQUiA8gyz_yEz5mShGdgVS9vQx_LbmJ6Xh9sEqTtIo9rDgflhKBlGK_b8V8KHir1NExtcuLAlSdMAwJWZ02IzMPNazkYEqxM_PMJh3nLXV6Q7Ph9a4BoPsN2xs6c9BxhlrXKgN1NChm38cKZHnBzw0ZlXcGTJfJdQvGjO8GGiXlZuzo9JioCByn-ZQvWtfepEHKZREx6rVcahSBM5PNG1i8GATRbAIxWpl88CRwv6r9OHXcvdjEEZo8Jl4yePumchyEo9NGMnf2Vk0Alp-cZv90AIO91uUAwo6a3P-iT-rJvk-tfJVed7XzxDqOaUA4ZMD9kCmZCyERolglV2QQ",
"not-before-policy":0,
"session_state":"5c0b34c6-76ab-42e7-8f0c-9c813708f70d",
"scope":"openid profile offline_access email"
}
# Make request to the backend endpoint
response = requests.get('http://localhost/api/foo', headers={'Authorization': 'Bearer ' + response.json().get('access_token')})
在响应中返回的只是Keyloak登录页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="login-pf">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow">
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Sign in to***</title>
...
我不知道为什么我们无法通过登录页面。我想,如果我们在标题中提供访问令牌,我们就可以通过登录页面访问后端端点。
以下是我们的一些相关文件:
Dev.confNginx配置
server {
listen 80;
server_name localhost;
charset utf-8;
client_max_body_size 10000m;
resolver 127.0.0.11 valid=30s ipv6=off;
resolver_timeout 10s;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# login with keycloak
access_by_lua_file /etc/nginx/lua/auth.lua;
...
Nginx配置中使用的auth.lualua文件
local opts = {
redirect_uri_path = "/redirect_uri",
accept_none_alg = true,
discovery = "http://keycloak:8080/realms/<realm>/.well-known/openid-configuration",
client_id = <id>,
client_secret = <secret>,
redirect_uri_scheme = "http",
logout_path = "/logout",
redirect_after_logout_uri = "http://keycloak:8080/realms/<realm>/protocol/openid-connect/logout",
post_logout_redirect_uri = "http://localhost",
redirect_after_logout_with_id_token_hint = false,
revoke_tokens_on_logout = true,
session_contents = {id_token=true,access_token=true,user=true}
}
-- call introspect for OAuth 2.0 Bearer Access Token validation
local res, err = require("resty.openidc").authenticate(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- decode and send the user roles for this session
local jwt = require "resty.jwt"
local jwt_obj = jwt:load_jwt(res.access_token)
local cjson = require "cjson"
ngx.log(ngx.DEBUG, "res.access_token.sub=", cjson.encode(jwt_obj))
ngx.req.set_header("ACCESS-TOKEN", cjson.encode(jwt_obj))
我们无法通过登录屏幕访问我们的后端终端。我们的环境里有什么东西吗?我想知道这是不是我们Lua档案里的逻辑。此外,有没有更好的方法让客户端访问我们的终端?
任何帮助都将不胜感激。
1条答案
按热度按时间dxxyhpgq1#
我能够解决这个问题。我不得不更改Lua文件中的代码。
以下是我将其更改为:
我使用
bearer_jwt_verify
检查承载令牌。如果没有设置,则恢复到以前使用authenticate
进行身份验证。