├── README.md ├── docker-compose.yaml ├── envoy ├── Dockerfile ├── envoy.yaml ├── hmac-secret.yaml └── token-secret.yaml └── keycloak ├── Dockerfile └── realm.json /README.md: -------------------------------------------------------------------------------- 1 | # envoy-keycloak-oauth2 2 | 3 | An example of using Keycloak with Envoy proxy for user auth utilizing Envoy's [oauth2 filter](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/oauth2_filter) 4 | 5 | Keycloak image has pre-configured realm "demorealm" with client_id/secret and a test user. Same client_id/secret are specified in Envoy configuration of the oauth2 filter. 6 | 7 | ### how to run 8 | 9 | 1. Start containers via `docker-compose up` 10 | 1. Go to http://localhost:10000 where Envoy listens. You should see immediate redirect to keycloak for user auth at http://localhost:8080 11 | 1. Log in as user "aa" password "aa". You should see redirect to upstream (Nginx with default web page) 12 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | keycloak: 5 | build: 6 | context: ./keycloak 7 | ports: 8 | - 8080:8080 9 | networks: 10 | - demonet 11 | 12 | envoy: 13 | build: 14 | context: ./envoy 15 | ports: 16 | - 10000:10000 17 | networks: 18 | - demonet 19 | 20 | upstream: 21 | image: nginx 22 | networks: 23 | - demonet 24 | 25 | networks: 26 | demonet: {} 27 | -------------------------------------------------------------------------------- /envoy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM envoyproxy/envoy-dev 2 | 3 | RUN mkdir -p /etc/envoy 4 | COPY ./envoy.yaml /etc/envoy/envoy.yaml 5 | COPY ./token-secret.yaml /etc/envoy/token-secret.yaml 6 | COPY ./hmac-secret.yaml /etc/envoy/hmac-secret.yaml 7 | 8 | CMD ["/usr/local/bin/envoy","-c","/etc/envoy/envoy.yaml","--service-cluster","envoy","--service-node","envoy","--log-level","debug"] 9 | -------------------------------------------------------------------------------- /envoy/envoy.yaml: -------------------------------------------------------------------------------- 1 | static_resources: 2 | listeners: 3 | - name: listener_proxy 4 | 5 | address: 6 | socket_address: 7 | address: 0.0.0.0 8 | port_value: 10000 9 | 10 | filter_chains: 11 | - filters: 12 | 13 | - name: envoy.filters.network.http_connection_manager 14 | typed_config: 15 | "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager 16 | stat_prefix: ingress_http 17 | route_config: 18 | name: default 19 | virtual_hosts: 20 | - name: default 21 | domains: ["*"] 22 | routes: 23 | - match: 24 | prefix: "/" 25 | route: 26 | cluster: upstream 27 | 28 | http_filters: 29 | - name: envoy.filters.http.oauth2 30 | typed_config: 31 | "@type": type.googleapis.com/envoy.extensions.filters.http.oauth2.v3alpha.OAuth2 32 | config: 33 | token_endpoint: 34 | cluster: keycloak 35 | uri: http://keycloak:8080/auth/realms/demorealm/protocol/openid-connect/token 36 | timeout: 5s 37 | authorization_endpoint: http://localhost:8080/auth/realms/demorealm/protocol/openid-connect/auth 38 | redirect_uri: "http://%REQ(:authority)%/oauth2/callback" 39 | redirect_path_matcher: 40 | path: 41 | exact: /oauth2/callback 42 | signout_path: 43 | path: 44 | exact: /oauth2/signout 45 | credentials: 46 | client_id: "democlient" 47 | token_secret: 48 | name: token 49 | sds_config: 50 | path: "/etc/envoy/token-secret.yaml" 51 | hmac_secret: 52 | name: hmac 53 | sds_config: 54 | path: "/etc/envoy/hmac-secret.yaml" 55 | forward_bearer_token: true 56 | auth_scopes: 57 | - openid 58 | 59 | - name: envoy.filters.http.router 60 | 61 | clusters: 62 | - name: keycloak 63 | connect_timeout: 1s 64 | type: STRICT_DNS 65 | lb_policy: ROUND_ROBIN 66 | load_assignment: 67 | cluster_name: keycloak 68 | endpoints: 69 | - lb_endpoints: 70 | - endpoint: 71 | address: 72 | socket_address: 73 | address: keycloak 74 | port_value: 8080 75 | 76 | - name: upstream 77 | connect_timeout: 1s 78 | type: STRICT_DNS 79 | lb_policy: ROUND_ROBIN 80 | load_assignment: 81 | cluster_name: upstream 82 | endpoints: 83 | - lb_endpoints: 84 | - endpoint: 85 | address: 86 | socket_address: 87 | address: upstream 88 | port_value: 80 89 | -------------------------------------------------------------------------------- /envoy/hmac-secret.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" 3 | name: hmac 4 | generic_secret: 5 | secret: 6 | inline_bytes: "zSsSrgTlxnST4t/8gHvZsARClqigpN3hyejev51mPVY=" 7 | -------------------------------------------------------------------------------- /envoy/token-secret.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret" 3 | name: token 4 | generic_secret: 5 | secret: 6 | # client secret from keycloak 7 | inline_string: "69b26b08-12fe-48a2-85f0-6ab223f45777" 8 | -------------------------------------------------------------------------------- /keycloak/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jboss/keycloak 2 | 3 | COPY ./realm.json /realm.json 4 | 5 | ENV KEYCLOAK_USER admin 6 | ENV KEYCLOAK_PASSWORD admin 7 | ENV KEYCLOAK_IMPORT /realm.json 8 | -------------------------------------------------------------------------------- /keycloak/realm.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "demorealm", 3 | "enabled": "true", 4 | "sslRequired": "none", 5 | "clients": [ 6 | { 7 | "clientId": "democlient", 8 | "clientAuthenticatorType": "client-secret", 9 | "secret": "69b26b08-12fe-48a2-85f0-6ab223f45777", 10 | "redirectUris": [ 11 | "http://*" 12 | ], 13 | "protocol": "openid-connect" 14 | } 15 | ], 16 | "users": [ 17 | { 18 | "username": "aa", 19 | "enabled": "true", 20 | "credentials": [ 21 | { 22 | "type": "password", 23 | "secretData": "{\"value\":\"kNGQec20vpNf9eqvzky+X2X82etF4+S7lXIH/CAhZrULdTP8/et8vHPJ6JPrewZ5h1wNs3ya2jaN34x1LXclyQ==\",\"salt\":\"jHw554VBg7N56gDAxWatzA==\"}", 24 | "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" 25 | } 26 | ] 27 | } 28 | ] 29 | } --------------------------------------------------------------------------------