目标:
在运行于Docker容器中的Flask应用程序中使用OIDC。
背景:
我正在使用Flask构建Web应用程序,希望使用Keycloak提供访问权限。为此,我使用Python库flask_oidc。
所有服务都在本地运行的docker-compose文件中运行:
- Gunicorn运行Flask应用程序(端口5000)
- Keycloak(端口8080)
我按照https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a的示例进行操作,并将我的应用程序简化为这个样子。
问题:
- 启动所有服务
- 导航到需要登录的服务(示例中的
/private
) - 用户被重定向到Keycloud服务器并提示登录。
- 用户登录。
- Keycloak将用户路由回应用程序(
/oidc_callback
) - !!! Flask应用程序崩溃,并显示
OSError:[Errno 99] Cannot assign requested address
错误。
当尝试连接到Keycloak服务器时,这是由flask_oidc
> oauth2client
> httplib2
引起的。
我认为发生的事情是库尝试打开与Keycloak服务器的连接,但尝试将其绑定到localhost
。这可能会失败,因为在Docker容器内部应用程序绑定到0.0.0.0
。
我尝试过的:
[正常工作]在容器外运行Gunicorn / Flask应用程序,并在容器内运行Keylcoak。
对我来说,这表明我的所有设置和代码都很好,但问题出现在Docker< - > flask_oidc +之间的交互中。
问题: 有人能解释一下吗? 我真的希望有人有一个工作设置(在Docker中使用flask_oidc的Flask),并且愿意分享此信息。
更新[5-12-2018] 我想我想到了。 我使用PyOIDC手动执行所有步骤并能够进行调试。
当在计算机上同时运行Docker中的两个服务(localhost
)时,会出现冲突:
- 用户通过访问
localhost:8080
来找到Keycloak,通过访问localhost:5000
来找到应用程序。 - Flask应用程序在容器中运行,
localhost
不会被解析为主机,而是在容器内部被解析为自己。 - 您可以让Flask使用容器中的网络连接到
http://keycloak/
,但是它返回的是这个域名下的所有配置。这是不好的,因为对外界来说应该是localhost:8080
。
现在,如果您实际上有域名(例如keycloak.awesome.app和app.awesome.app),我认为它会正常工作,因为它将使用外部DNS将其解析为IP地址,这是正确的机器。
奖励: PyOIDC可以从Keycloak检索提供程序配置,因此不再需要手动输入。耶!
新设置 对于本地开发,我决定进行如下设置:
(1) 添加到/etc/hosts
:
127.0.0.1 keycloak.dev.local
127.0.0.1 app.dev.local
(2) 在docker-compose.yml
中添加到您的Flask服务:
extra_hosts: #host.docker.internal is not accepted.
- "keycloak.dev.local:<YOUR IP ADRESS>"
- "app.dev.local:<YOUR IP ADRESS>"
(=) 现在,您和Flask应用程序都可以访问keycloak.dev.local
并获得正确的响应!
请注意,我仍然更喜欢一个更好的解决方案。一旦我的IP地址发生变化,此设置就会失败。
flask-oidc
引起的。 - Filnor