oauth filter for client authorization via groups

161 views
Skip to first unread message

Pratik Lotia

unread,
Jun 28, 2023, 8:01:39 PM6/28/23
to envoy-users
Hi all,

I'm looking to understand how to configure the oauth filter to do authorization along with authentication.

I'm using envoy as a api gateway and my current config (below) defines the Oauth server which does authentication of my clients. I have multiple apps behind this envoy proxy and I want to limit which group of users can access which app. The IdToken returned by the Oauth provider provides all claims including an array of groups which the client is a part of. Example:
{ 'iss': 'https://oauth_server.com/', 'email':' joh...@example.com', 'groups': [ 'All_users', 'grp-app1', 'grp-app2'] }

 The JWT authn claim_to_header does not allow extracting array values from claims due to which I cannot directly forward the `groups` info to upstream apps.

Say I have 3 upstream apps: App1, App2, App3. I want to allow John Doe to access App1 & App2 but not App3 and I am setting this by the 'Groups' defined in the Oauth provider. How do I specific a per virtual_host rule which defines which groups can access the app?

$cat envoy.yaml

node:
  id: my_id
  cluster: my_cluster

static_resources:
  listeners:
  - name: my_listener
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 9999
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: AUTO
          stat_prefix: my_apps_stat
          route_config:
            name: local_route
            virtual_hosts:
            - name: upstream
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: upstream-service
          http_filters:
          - name: envoy.filters.http.oauth2
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.oauth2.v3.OAuth2
              config:
                token_endpoint:
                  cluster: oauth
                  uri: "https://example.oauth.com/v1/token"
                  timeout: 5s
                authorization_endpoint: "https://example.oauth.com/v1/authorize"
                redirect_uri: "%REQ(x-forwarded-proto)%://%REQ(:authority)%/callback"
                redirect_path_matcher:
                  path:
                    exact: /callback
                signout_path:
                  path:
                    exact: /signout
                forward_bearer_token: true
                credentials:
                  client_id: my_random_client_id_oeriubgfw
                  token_secret:
                    name: token
                    sds_config:
                      path: "/etc/envoy/token-secret.yaml"
                  hmac_secret:
                    name: hmac
                    sds_config:
                      path: "/etc/envoy/hmac-secret.yaml"
                auth_scopes:
                - openid
                - email
                - groups
          - name: envoy.filters.http.jwt_authn
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
              providers:
                provider1:
                  remote_jwks:
                    http_uri:
                      uri: "https://example.oauth.com/v1/keys"
                      cluster: oauth
                      timeout: 10s
                    cache_duration: 300s
              rules:
                 - match:
                     prefix: /
                   requires:
                     provider_name: provider1
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          common_tls_context:
            tls_certificates:
            - certificate_chain: {filename: "/etc/envoy/cert.pem"}
              private_key: {filename: "/etc/envoy/key.pem"}
  clusters:
  - name: upstream-service
    connect_timeout: 2s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: upstream-service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: App1.example.com
                port_value: 9000
  - name: oauth
    connect_timeout: 2s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: oauth
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: example.oauth.com
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: example.oauth.com




Note: in the above example, I have not defined multiple upstreams apps but you get my point.

I attempted using the rbac filter but my downstream clients are human users (no client cert) and have a null principal_name (SAN)

I appreciate any guidance on this. Thank you.

Reply all
Reply to author
Forward
0 new messages