首页 > 解决方案 > Flask_oidc 在 Docker 容器中运行时给出“Errno 99 无法分配请求的地址”

问题描述

目标:

在 Docker 容器中运行的 Flask 应用程序中使用 OIDC。

背景:

我正在使用 Flask 构建一个 Web 应用程序,并希望使用 Keycloak 来提供访问权限。为此,我使用 Python 库 flask_oidc。

所有服务都使用 docker-compose 文件在本地运行:

我遵循了https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a的示例,甚至将我的应用程序简化为这个。

问题:

  1. 启动所有服务
  2. 导航到需要登录的服务(/private在示例中)
  3. 用户被重新路由到提示登录的 Keycloud 服务器。
  4. 用户登录。
  5. Keycloak 将用户路由应用程序 ( /oidc_callback)
  6. !!!Flask 应用程序因OSError: [Errno 99] Cannot assign requested address错误而崩溃。

这是在尝试连接到 Keycloak 服务器时在flask_oidc> oauth2client>中引起的。httplib2

认为正在发生的是库尝试打开与 Keycloak 服务器的连接,但尝试将其绑定到localhost. 这可能会失败,因为在 Docker 容器内,应用程序绑定到0.0.0.0.

我尝试了什么:

[ WORKS ] 在容器外运行 Gunicorn/Flask 应用程序,并在容器内运行 Keylcoak。

这表明(对我而言)我的所有设置和代码都很好,但问题出在 Docker<-->flask_oidc+ 之间的交互中。

问题:谁能解释一下?我真的希望有人有一个工作设置(在 docker 中使用 flask_oidc 的 Flask),并且愿意分享这个。

更新 [2018 年 5 月 12 日] 我想我明白了。我使用 PyOIDC 手动完成所有步骤并能够进行调试。

在您自己的计算机 ( localhost) 上在 Docker 中运行这两个服务时,您会遇到冲突:

现在,如果您实际上有域名(例如 keycloak.awesome.app 和 app.awesome.app),我认为它会正常工作,因为它会使用外部 DNS 将其解析为 IP 地址,即正确的机器。

奖励: PyOIDC 可以从 Keycloak 中检索提供程序配置,因此无需为此手动输入。耶!

新设置 对于本地开发,我决定进行如下设置:

(1) 添加到/etc/hosts127.0.0.1 keycloak.dev.local 127.0.0.1 app.dev.local

(2) 添加到您的 Flask 服务中docker-compose.ymlextra_hosts: #host.docker.internal is not accepted. - "keycloak.dev.local:<YOUR IP ADRESS>" - "app.dev.local:<YOUR IP ADRESS>"

(=) 现在,您和 Flask 应用程序都可以访问keycloak.dev.local并且可以正确响应!

请注意,我仍然希望有一个更好的解决方案。一旦我的 IP 地址更改,此设置就会失败。

标签: pythondockerflaskopenid-connect

解决方案


flask-oidc 从客户端机密文件中获取令牌端点配置。

我设法通过进行以下更改使其工作:

  1. 为烧瓶应用keycloak容器创建了一个 docker 网络;
  2. 编辑了属性userinfo_uritoken_uritoken_introspection_uri,将主机名替换为 keycloak 容器主机名(我使用的是 docker-compose,在这种情况下,keycloak 容器主机名是服务名称)。

例子:

{
  "web": {
    "auth_uri": "http://localhost:8080/auth/realms/REMOVED/protocol/openid-connect/auth",
    "client_id": "flask-client",
    "client_secret": "REMOVED",
    "redirect_uris": ["http://localhost:5000/oidc_callback"],
    "userinfo_uri": "http://keycloak:8080/auth/realms/REMOVED/protocol/openid-connect/userinfo",
    "token_uri": "http://keycloak:8080/auth/realms/REMOVED/protocol/openid-connect/token",
    "token_introspection_uri": "http://keycloak:8080/auth/realms/REMOVED/protocol/openid-connect/token/introspect"
  }
}

现在它通过 docker 网络连接以交换令牌信息。


推荐阅读