【问题标题】:How can I debug oauth2_proxy when connecting to Azure B2C?连接到 Azure B2C 时如何调试 oauth2_proxy?
【发布时间】:2020-04-10 20:51:12
【问题描述】:

我是 Kubernetes 新手,我一直在学习 Ingress。在入口点处理 TLS 证书和身份验证的想法给我留下了深刻的印象。我添加了一个简单的静态文件服务器,并添加了 cert-manager,所以我基本上有一个 HTTPS 静态网站。

我读到 NGINX 入口控制器可以与 oauth2 代理一起使用来处理入口处的身份验证。问题是我根本无法让它工作。我可以确认我的 oauth2-proxy 部署服务和部署存在且正确 - 在 Pod 的日志中,我可以看到来自 NGINX 的请求,但我看不到它在 Azure B2C 上实际调用的 uri。每当我尝试访问我的服务时,我都会收到 500 内部错误 - 如果我将我的 /oath2/auth 地址放在浏览器中,我会收到“不支持请求中指定的范围 'openid'。”。但是,如果我在 Azure 中测试运行用户流,测试 URL 还会指定“openid”并且它按预期运行。

我认为,如果我能找到如何监控来自 Azure 的 oauth2-proxy 请求(即通过观察它的 uri 来找出我的配置错误的地方),我可以解决这个问题 - 否则,也许有人已经这样做了告诉我配置哪里出错了。

我的配置如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: oauth2-proxy
  template:
    metadata:
      labels:
        k8s-app: oauth2-proxy
    spec:
      containers:
      - args:
        - -provider=oidc
        - -email-domain=*
        - -upstream=file:///dev/null
        - -http-address=0.0.0.0:4180
        - -redirect-url=https://jwt.ms/
        - -oidc-issuer-url=https://<tenant>.b2clogin.com/tfp/<app-guid>/b2c_1_manager_signup/
        - -cookie-secure=true
        - -scope="openid"

        # Register a new application
        # https://github.com/settings/applications/new
        env:
        - name: OAUTH2_PROXY_CLIENT_ID
          value: <app-guid>
        - name: OAUTH2_PROXY_CLIENT_SECRET
          value: <key-base64>
        - name: OAUTH2_PROXY_COOKIE_SECRET
          value: <random+base64>
        image: quay.io/pusher/oauth2_proxy:latest
        imagePullPolicy: Always
        name: oauth2-proxy
        ports:
        - containerPort: 4180
          protocol: TCP
---

apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: default
spec:
  ports:
  - name: http
    port: 4180
    protocol: TCP
    targetPort: 4180
  selector:
    k8s-app: oauth2-proxy
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: static1-oauth2-proxy
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
spec:
  rules:
  - host: cloud.<mydomain>
    http:
      paths:
      - backend:
          serviceName: oauth2-proxy
          servicePort: 4180
        path: /oauth2
  tls:
  - hosts:
    - cloud.<mydomain>
    secretName: cloud-demo-crt

在我的静态站点入口中,我将以下内容添加到 metadata.annotations:

    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$request_uri"

我不能 100% 确定这些注释是否应该始终这样设置,或者我是否应该为 B2C/OIDC 更改这些注释,但它们似乎转到了代理,这正是代理接下来要做的事情失败。

请注意,日志确实表明 oauth2-proxy 已连接到 B2C,实际上,如果颁发者 uri 发生更改,则会进入崩溃回退循环。

似乎有很多关于如何设置的文章,所以我确信这是可能的,但我有点迷失了。如果有人可以帮助调试设置或想法,那就太好了。

谢谢。


现在我能够可靠地获取 ?state= 和 code= 以显示在 /oauth2/callback 页面的浏览器窗口中,但该页面报告内部错误。 oauth2_proxy 正在记录它现在应该记录的时间,并且日志显示:

[2020/06/03 21:18:07] [oauthproxy.go:803] 在 OAuth2 回调期间兑换代码时出错:令牌交换:oauth2:服务器响应缺少 access_token

我的 Azure B2C 审核日志显示它正在发布 id_tokens。

当我查看 oauth2_proxy 的源代码时,似乎问题发生在 oauth2.config.Exchange() 期间 - 它位于 goloang 库中 - 我不知道那是什么,但我不知道认为它适用于 Azure B2c。有人知道我如何从这里取得进步吗?

谢谢。

标记

【问题讨论】:

  • golang/x/exchange::config.Exchange 的代码显示它没有将 Client_Id 应用于 oidc 发现中的 TokenUrl。 Azure B2C 没有 client_id 作为 Url 的一部分,因此我可能会在今天稍后再查看。

标签: azure nginx oauth-2.0 proxy oauth2-proxy


【解决方案1】:

我求助于在 VSCode 中编译和调试代理应用程序。我运行了一个简单的 NGINX 代理来为代理提供 TLS 终止,以允许 Azure B2C 端运行。事实证明,我做错了很多事情。以下是我解决的问题列表,希望其他人可以使用它来通过 Azure B2C 运行他们自己的 oauth_proxy。

当附加到调试器时,很明显 oauth2_proxy 会读取令牌并期望 fin,依次是 access_token,然后是 id_token,然后它需要(默认情况下)“电子邮件”声明。

要让“access_token”返回,您必须请求访问某些资源。最初我没有这个。在我的 yaml 文件中,我有:

    - --scope=openid

注意:不要在 YAML 中的范围值周围加上引号,因为它们被视为请求范围值的一部分!

我必须通过“应用注册”和“公开 API”在 Azure B2C 中设置“读取”范围。我最终的工作范围是:

    - --scope=https://<myspacename>.onmicrosoft.com/<myapiname>/read openid

您必须确保两个范围(读取和 openid)一起通过,否则您不会获得 id_token。如果您收到错误提示您在服务器响应中没有 id_token,请确保在一次使用 --scope 标志时这两个值都通过。

一旦您拥有 access_token 和 id_token,oauth2_proxy 就会失败,因为没有“电子邮件”声明。 Azure B2C 有“电子邮件”声明,但我认为不能使用。为了解决这个问题,我使用了对象 id,我设置了:

    - --user-id-claim=oid

我遇到的最后一个问题是浏览器中没有设置 cookie。我确实在 oauth2-proxy 输出中看到了一个错误,即 cookie 值本身太长,并且我删除了“offline_access”范围并且该消息消失了。然而,浏览器中仍然没有 cookie。

但是,我的 NGinX 入口日志确实有一条消息,表明标头超过 8K,因此 NGinX 报告了 503 错误。

在 oauth2-proxy 文档中,有一个说明,即如果您的 cookie 很长,则应使用 Redis 存储 - 它专门将 Azure AD cookie 标识为足够长以保证使用 Redis 解决方案。

我安装了一个单节点 Redis 以使用来自此答案 https://stackoverflow.com/a/53052122/2048821 的 YAML 配置进行测试(未硬化) - 必须使用 --session-store-type=redis 和 --redis-connection-url 选项。

我的 oauth2_proxy 的最终服务/部署如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: oauth2-proxy
  template:
    metadata:
      labels:
        k8s-app: oauth2-proxy
    spec:
      containers:
      - args:
        - --provider=oidc
        - --email-domain=*
        - --upstream=file:///dev/null
        - --http-address=0.0.0.0:4180
        - --redirect-url=https://<myhost>/oauth2/callback
        - --oidc-issuer-url=https://<mynamespane>.b2clogin.com/tfp/<my-tenant>/b2c_1_signin/v2.0/
        - --cookie-secure=true
        - --cookie-domain=<myhost>
        - --cookie-secret=<mycookiesecret>
        - --user-id-claim=oid
        - --scope=https://<mynamespace>.onmicrosoft.com/<myappname>/read openid
        - --reverse-proxy=true
        - --skip-provider-button=true
        - --client-id=<myappid>
        - --client-secret=<myclientsecret>
        - --session-store-type=redis
        - --redis-connection-url=redis://redis:6379

        # Register a new application
        image: quay.io/pusher/oauth2_proxy:latest
        imagePullPolicy: Always
        name: oauth2-proxy
        ports:
        - containerPort: 4180
          protocol: TCP

---

apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: oauth2-proxy
  name: oauth2-proxy
  namespace: default
spec:
  ports:
  - name: http
    port: 4180
    protocol: TCP
    targetPort: 4180
  selector:
    k8s-app: oauth2-proxy

希望这可以节省很多人的时间。

标记

【讨论】:

  • 在 --oidc-issuer-url 目录(租户) ID guid,可在 Identity Experience Framework 中找到 |打开个人应用程序时的应用程序注册?
  • oidc-issuer-url 中的 /tfp/ 是什么?我注意到它在许多(旧的?)帖子中被引用,但当前的 MS document 不包括它,例如https://.b2clogin.com/.onmicrosoft.com//oauth2/v2.0/token
【解决方案2】:

我尝试关注Mark Rabjohn’s answer,但遇到了类似的错误

oidc:发行者与提供商返回的发行者不匹配,应为 “https://your-tenant-name.b2clogin.com/tfp/c5b28ff6-f360-405b-85d0-8a87b5783d3b/B2C_1A_signin/v2.0/” 拿到 “https://your-tenant-name.b2clogin.com/c5b28ff6-f360-405b-85d0-8a87b5783d3b/v2.0/” (网址中没有策略名称)

这是一个已知问题 (https://security.stackexchange.com/questions/212724/oidc-should-the-provider-have-the-same-address-as-the-issuer)

我知道微软等一些主流提供商 没有严格遵循这种模式,但你必须接受它 使用它们,或考虑 OIDC 库提供的解决方法。

幸运的是oauth2-proxy supports --skip-oidc-discovery 参数: 绕过 OIDC 端点发现。在这种情况下必须配置--login-url、--redeem-url 和--oidc-jwks-url。

参数示例如下:

- --skip-oidc-discovery=true
- --login-url=https://<mynamespace>.b2clogin.com/<mynamespace>.onmicrosoft.com/
      b2c_1a_signin/oauth2/v2.0/authorize
- --redeem-url=https://<mynamespace>.b2clogin.com/<mynamespace>.onmicrosoft.com/
      b2c_1a_signin/oauth2/v2.0/token
- --oidc-jwks-url=https://<mynamespace>.b2clogin.com/<mynamespace>.onmicrosoft.com/
      b2c_1a_signin/discovery/v2.0/keys

要创建 范围,我必须通过“应用注册”和“公开 API”在 Azure B2C 中设置应用程序 ID URI。 (例如见https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-web-api-dotnet?tabs=app-reg-ga#configure-scopes)。
我还必须按照https://docs.microsoft.com/en-us/azure/active-directory-b2c/add-web-api-application?tabs=app-reg-ga#grant-permissions 中的说明授予管理员权限(另请参阅Application does not have sufficient permissions against this web resource to perform the operation in Azure AD B2C

- —scope=https://<mynamespace>.onmicrosoft.com/<myappname>/<scopeName> openid

您还应该指定

- —oidc_issuer_url=https://<mynamespace>.b2clogin.com/<TenantID>/v2.0/

在 oidc_issuer_url 中使用 Directory/tenantId 满足回调/赎回阶段的验证,您无需设置 useinsecure_oidc_skip_issuer_verification=true。

另请注意,redirect-url=https:///oauth2/callback 应在 AAD B2C 中注册为应用程序重定向 URI(在应用程序概述窗格中导航到重定向 URI 链接)

【讨论】:

  • 嗨迈克尔,我没有注意到你以前的 cmets,但我确实喜欢这个允许精确设置的解决方案。仅供参考,如果你想查看包含 /tfp/ 的 URL 样式,它可以是在 Azure 门户的“属性”页面的“颁发者 (iss) 声明”下拉列表中找到每个用户流。可以选择 /tfp/ 版本。
  • 我还有一个 oauth2-proxy 分支(我认为来自 V5),它允许包含基于回调错误的自动重定向。这允许 oauth2-proxy 自动将 B2C 工作流链接在一起(例如从登录到恢复密码)。 github.com/IntegratedArts/oauth2-proxy/tree/… - 我希望在未来几周内将其更新到最新版本,并希望它能够被主项目接受。
【解决方案3】:

我不清楚调试,但根据您的问题,它看起来您没有传递标头参数。

在静态网站入口请也添加这个并尝试

nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-Access-Token, Authorization

或者这个

nginx.ingress.kubernetes.io/auth-response-headers: Authorization

【讨论】:

  • 我还没有得到这个工作,所以今天晚些时候我会试试你的建议。我读过一些关于隐式流程的文章。您是否还知道是否应该为 oath2_proxy 启用或禁用“隐式流”?
  • 嗨,当然,如果它不起作用,请告诉我。关于隐式流,不推荐,请禁用。在隐式流中,它将在 HTTP 请求上共享令牌(无需握手)。所以最好不要启用。
  • 花了一些时间才找到这个,但我仍然没有让它发挥作用。我的 oauth_proxy 容器现在正在记录,这帮助我修复了一些设置,但现在每次尝试都会导致在回调页面上显示 ?state=....&code=... 看起来不错。在日志中虽然我得到:[2020/06/03 21:18:07] [oauthproxy.go:803] 在 OAuth2 回调期间兑换代码时出错:令牌交换:oauth2:服务器响应缺少 access_token - 我的 Azure B2C 审核日志说我每次都发出 ID 并且状态和代码发生变化 - 有什么想法吗?
  • 我已经在本地机器上设置了 NGINX 和 OAuth2-Proxy。看来我的主要问题是我只请求了“openid offline_access”的范围 - 您还需要在需要令牌之前请求对特定资源的权限。我现在已经能够让 oauth2_proxy 说“经过身份验证”,但我不得不更改很多设置,但仍然没有得到 cookie。
【解决方案4】:

根据Mark RabjohnMichael Freidgeim 提供的信息,我还(经过数小时的尝试)获得了与 Azure AD B2C 的有效集成。这是一个重现工作设置的配置,使用 docker-compose 在本地进行测试:

本地设置

version: "3.7"
services:
  oauth2proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:latest
    command: >
      --provider=oidc
      --email-domain=*
      --upstream=http://web
      --http-address=0.0.0.0:9000
      --redirect-url=http://localhost:9000
      --reverse-proxy=true
      --skip-provider-button=true
      --session-store-type=redis
      --redis-connection-url=redis://redis:6379
      --oidc-email-claim=oid
      --scope="https://<mynamepsace>.onmicrosoft.com/<app registration uuid>/read openid"
      --insecure-oidc-skip-issuer-verification=true
      --oidc-issuer-url=https://<mynamespace>.b2clogin.com/<mynamepsace>.onmicrosoft.com/<policy>/v2.0/
    environment:
      OAUTH2_PROXY_CLIENT_ID: "<app registration client id>"
      OAUTH2_PROXY_CLIENT_SECRET: "<app registration client secret>"
      OAUTH2_PROXY_COOKIE_SECRET: "<secret follow oauth2-proxy docs to create one>"
    ports:
      - "9000:9000"
    links:
      - web
  web:
    image: kennethreitz/httpbin
    ports:
      - "8000:80"
  redis:
    image: redis:latest

这里的重要部分是这些选项:

--oidc-email-claim=oid
--scope="https://<mynamepsace>.onmicrosoft.com/<app registration uuid>/read openid"
--insecure-oidc-skip-issuer-verification=true
--oidc-issuer-url=https://<mynamespace>.b2clogin.com/<mynamepsace>.onmicrosoft.com/<policy>/v2.0/

使用--insecure-oidc-skip-issuer-verification=true 允许您跳过使用--login-url --redeem-url --oidc-jwks-url 明确提及端点。

--oidc-email-claim=oid 替换了 Mark Rabjohn 提到的已弃用选项 --user-id-claim=oid

正如马克解释的那样,范围也是需要的。

Azure AD B2C 设置

这些是在 Azure AD B2C 门户中执行所需的汇总步骤:

  1. 在用户流程中,转到“应用程序声明”并启用“用户的对象 ID”。这是使--oidc-email-claim=oid 设置工作所必需的
  2. 在应用注册中,在“API 权限”中,创建一个名为read 的新权限。该权限的url就是--scope="..."需要填写的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    • 2021-02-20
    • 2019-10-12
    • 2019-06-29
    • 1970-01-01
    • 2018-01-24
    • 2018-08-15
    相关资源
    最近更新 更多