You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过OAuth2与Keycloak实现Istio授权并解决登录重定向问题

Istio + OAuth2-Proxy + Keycloak 认证重定向异常问题

问题背景

基于《API Authentication: Configure Istio IngressGateway, OAuth2-Proxy and Keycloak》及Istio官方授权策略文档,尝试通过OAuth2与Keycloak实现Istio入口网关的外部认证。

预期效果

用户访问<ingress host>/app时,自动重定向至Keycloak登录页面,完成认证后可访问后端服务。

当前异常

访问<ingress host>/app时页面加载10秒后返回403;若在10秒内执行kubectl delete -f authorization-policy.yaml删除授权策略,可正常触发Keycloak登录重定向。


相关配置文件

oauth2.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: oauth-proxy
  name: oauth-proxy
spec:
  type: NodePort
  selector:
    app: oauth-proxy
  ports:
  - name: http-oauthproxy
    port: 4180
    nodePort: 31023
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: oauth-proxy
  name: oauth-proxy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "oauth-proxy"
  template:
    metadata:
      labels:
        app: oauth-proxy
    spec:
      containers:
      - name: oauth-proxy
        image: "quay.io/oauth2-proxy/oauth2-proxy:v7.2.0"
        ports:
        - containerPort: 4180
        args:
          - --http-address=0.0.0.0:4180
          - --upstream=http://test-web-app:3000
          - --set-xauthrequest=true
          - --pass-host-header=true
          - --pass-access-token=true
        env:
          # OIDC Config
          - name: "OAUTH2_PROXY_PROVIDER"
            value: "keycloak-oidc"
          - name: "OAUTH2_PROXY_OIDC_ISSUER_URL"
            value: "http://192.168.1.2:31020/realms/my_login_realm"
          - name: "OAUTH2_PROXY_CLIENT_ID"
            value: "my_nodejs_client"
          - name: "OAUTH2_PROXY_CLIENT_SECRET"
            value: "JGEQtkrdIc6kRSkrs89BydnfsEv3VoWO"
          # Cookie Config
          - name: "OAUTH2_PROXY_COOKIE_SECURE"
            value: "false"
          - name: "OAUTH2_PROXY_COOKIE_SECRET"
            value: "ZzBkN000Wm0pQkVkKUhzMk5YPntQRUw_ME1oMTZZTy0="
          - name: "OAUTH2_PROXY_COOKIE_DOMAINS"
            value: "*"
          # Proxy config
          - name: "OAUTH2_PROXY_EMAIL_DOMAINS"
            value: "*"
          - name: "OAUTH2_PROXY_WHITELIST_DOMAINS"
            value: "*"
          - name: "OAUTH2_PROXY_HTTP_ADDRESS"
            value: "0.0.0.0:4180"
          - name: "OAUTH2_PROXY_SET_XAUTHREQUEST"
            value: "true"
          - name: OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER
            value: "true"
          - name: OAUTH2_PROXY_SSL_UPSTREAM_INSECURE_SKIP_VERIFY
            value: "true"
          - name: OAUTH2_PROXY_SKIP_PROVIDER_BUTTON
            value: "true"
          - name: OAUTH2_PROXY_SET_AUTHORIZATION_HEADER
            value: "true"

keycloak.yaml

apiVersion: v1
kind: Service
metadata:
  name: keycloak
spec:
  type: NodePort
  selector:
    app: keycloak
  ports:
  - name: http-keycloak
    port: 8080
    nodePort: 31020
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keycloak
spec:
  selector:
    matchLabels:
      app: keycloak
  template:
    metadata:
      labels:
        app: keycloak
    spec:
      containers:
      - name: keycloak
        image: quay.io/keycloak/keycloak:17.0.0
        ports:
        - containerPort: 8080
        args: ["start-dev"]
        env:
        - name: KEYCLOAK_ADMIN
          value: "admin"
        - name: KEYCLOAK_ADMIN_PASSWORD
          value: "admin"

istio-operator.yaml

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  meshConfig:
    accessLogFile: /dev/stdout
    extensionProviders:
    - name: "oauth2-proxy"
      envoyExtAuthzHttp:
        service: "oauth-proxy.default.svc.cluster.local"
        port: "4180" # The default port used by oauth2-proxy.
        includeHeadersInCheck: ["authorization", "cookie","x-forwarded-access-token","x-forwarded-user","x-forwarded-email","x-forwarded-proto","proxy-authorization","user-agent","x-forwarded-host","from","x-forwarded-for","accept","x-auth-request-redirect"] # headers sent to the oauth2-proxy in the check request.
        headersToUpstreamOnAllow: ["authorization", "path", "x-auth-request-user", "x-auth-request-email", "x-auth-request-access-token","x-forwarded-access-token"] # headers sent to backend application when request is allowed.
        headersToDownstreamOnDeny: ["content-type", "set-cookie"] # headers sent back to the client when request is denied.
        

gateway.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: test-gateway
  namespace : istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - '*'

virtual-service.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: gateway-vs
spec:
  hosts:
    - '*'
  gateways: 
    - istio-system/test-gateway
  http:
    - match:
      - uri:
          prefix: /oauth2
      route:
      - destination:
          host: oauth-proxy.default.svc.cluster.local
          port:
            number: 4180
    - match:
      - uri:
          prefix: /app
      route:
      - destination:
          host: test-web-app.default.svc.cluster.local
          port:
            number: 3000

authorization-policy.yaml

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: example-auth-policy
spec:
  action: CUSTOM
  provider:
    name: "oauth2-proxy"
  rules:
  - to:
    - operation:
        paths: ["/app"]
        notPaths: ["/oauth2/*"]

问题分析与修复方案

核心原因

  1. ExtAuthz模式适配错误:Istio的CUSTOM授权策略会向oauth2-proxy发送同步Check请求,但当前oauth2-proxy启用--set-xauthrequest=true时,期望处理反向代理流量而非标准ExtAuthz接口,导致请求超时后返回403。
  2. 重定向头未传递:Istio的ExtensionProvider配置中未包含location头,oauth2-proxy返回的302重定向响应无法正确转发给客户端。
  3. 授权策略规则范围错误:paths: ["/app"]仅匹配根路径,未覆盖子路径;notPaths规则逻辑无效,因为/oauth2流量由VirtualService直接路由,不会经过该授权策略。

修复步骤

1. 调整OAuth2-Proxy配置,支持ExtAuthz重定向

修改oauth2-proxy的Deployment参数,添加--auth-request-redirect=true以适配Istio的ExtAuthz模式:

args:
  - --http-address=0.0.0.0:4180
  - --upstream=http://test-web-app:3000
  - --set-xauthrequest=true
  - --auth-request-redirect=true  # 启用重定向响应支持
  - --pass-host-header=true
  - --pass-access-token=true

2. 更新Istio ExtensionProvider配置

在istio-operator.yaml的headersToDownstreamOnDeny中添加location头,确保重定向地址能传递给客户端:

headersToDownstreamOnDeny: ["content-type", "set-cookie", "location"]

3. 修正授权策略规则

调整路径匹配范围,确保覆盖/app下所有子路径:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: example-auth-policy
spec:
  action: CUSTOM
  provider:
    name: "oauth2-proxy"
  rules:
  - to:
    - operation:
        paths: ["/app/*"]  # 匹配/app下所有子路径

4. 应用配置并验证

  • 重新应用所有修改后的配置:
    kubectl apply -f oauth2.yaml
    kubectl apply -f istio-operator.yaml
    kubectl apply -f authorization-policy.yaml
    
  • 重启oauth2-proxy pod使配置生效:
    kubectl rollout restart deployment oauth-proxy
    

修复后流程说明

用户访问/app时,Istio触发ExtAuthz请求到oauth2-proxy;oauth2-proxy检测到未认证,返回带Location头的302响应,Istio将该响应转发给客户端,引导用户跳转到Keycloak登录页。登录完成后,Keycloak回调到/oauth2/callback,oauth2-proxy验证凭证并设置会话Cookie,再重定向回/app;此时Istio再次触发ExtAuthz请求,oauth2-proxy验证Cookie有效后返回允许访问的响应,Istio将请求转发到后端服务。

内容的提问来源于stack exchange,提问作者Krishnan KK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 02:45:35