title: Istio OAuth2 with Keycloak
body: <p>I am using Istio as API Gateway and Service Mesh. The plan is to have the authentication and authorization flow (oauth2) being managed by the Ingress Envoy Gateway in Istio. However, the usage of Envoy filters are not redirecting the URL request to the login page as expected (the example followed can be found in <a href="https://medium.com/@suman_ganta/openid-authentication-with-istio-a32838adb492" rel="nofollow noreferrer">here</a> and the login is not happening.
  If I try to connect by curl (authenticate, use the token received to get the authorization), it works fine. But when involve the Oauth 2 flow, it gets stuck.
  This authorizations are being done using <strong>Keycloak</strong>.</p>
  
  <p>This is the Lua Filter being used:</p>
  
  <pre><code>apiVersion: networking.istio.io/v1alpha3
  kind: EnvoyFilter
  metadata:
    name: authn-filter
    namespace: istio-test
  spec:
    filters:
    - filterConfig:
        inlineCode: |
          function login (request_handle)
            request_handle:logInfo("logging in")
            local request_url = "http://"..request_handle:headers():get(":authority")..request_handle:headers():get(":path")
            request_handle:logInfo(request_url)
            headers, body = request_handle:httpCall(
              "outbound|3000||service-gatekeeper.istio-test.svc.cluster.local",
              {
                [":method"] = "POST",
                [":path"] = "/oauth/authorize",
                [":authority"] = request_handle:headers():get(":authority"),
                ["X-Auth-Request-Redirect"] = request_url
              },
              nil,
              5000)
            return headers, body
          end
          function envoy_on_request(request_handle)
            local path = request_handle:headers():get(":path")
            -- ignore metrics, liveness probe requests
            request_handle:logInfo("Envoy on Request")
            if path == "/" then
              return
            end
            token = request_handle:headers():get("Authorization")
            cookie = request_handle:headers():get("Cookie")
            if token == nil and cookie == nil then
               request_handle:logInfo("about to login")
               headers, body = login(request_handle)
               request_handle:respond(headers,body)
            end
            request_handle:logInfo("validating token against Certs")
            local headers, body = request_handle:httpCall(
              "outbound|8080||eseabyr-oauth2-proxy-innulic-test.svc.cluster.local",
              {
                [":method"] = "GET",
                [":path"] = "/oauth/authorize",
                [":authority"] = request_handle:headers():get(":authority"),
                ["Authorization"] = token,
                ["Cookie"] = cookie
              },
              nil,
              5000)
            local status
            for header, value in pairs(headers) do
              if header == ":status" then
                 status = value
              end
            end
  
            request_handle:logInfo("token validation status:"..status)
            if status == "401" then
              headers, body = login(request_handle)
              request_handle:respond(headers,body)
            end
          end
          -- Called on the response path.
          function envoy_on_response(response_handle)
              local headers = response_handle:headers()
              headers:add("X-Envoy-Ingress", os.getenv("HOSTNAME"))
          end
      filterName: envoy.lua
      filterType: HTTP
      listenerMatch:
        listenerType: GATEWAY
  </code></pre>
  
  <p>Thank you.</p>