Skip to content

Commit 9179889

Browse files
committed
Initial commit
0 parents  commit 9179889

File tree

10 files changed

+3911
-0
lines changed

10 files changed

+3911
-0
lines changed

README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# NGINX with OAuth2 Proxy and Keycloak demo
2+
3+
NGINX -> OAuth2 Proxy -> NodeJS
4+
5+
## Quick Start
6+
7+
```sh
8+
# Start (Keycloak will bootstrap with `dev` realm and users)
9+
# NGINX and OAuth2 Proxy will exit as dependent containers are not ready (https://docs.docker.com/compose/startup-order/)
10+
docker-compose up -d
11+
# Wait until Keycloak completes initialization, and start the stopped containers
12+
docker-compose up -d
13+
14+
# Cleanup
15+
docker-compose rm
16+
docker volume prune
17+
```
18+
19+
Initiate browser login at http://nginx.127.0.0.1.nip.io:9000/ with user=`user`, password=`password`.
20+
21+
Authenticated requests will be proxied to NodeJS server with HTTP headers echoed to the browser:
22+
23+
```sh
24+
'x-user': '4a76657b-35f0-43d0-9653-9b0f60ebd4b9'
25+
'x-email': '[email protected]'
26+
```
27+
28+
Sign-out URL: [http://nginx.127.0.0.1.nip.io:4180/oauth2/sign_out](http://proxy.127.0.0.1.nip.io:4180/oauth2/sign_out)
29+
30+
Access Keycloak at [http://keycloak.127.0.0.1.nip.io:8080](http://keycloak.127.0.0.1.nip.io:8080) with user=`admin`, password=`password` to check out the settings
31+
32+
## Refreshing Cookie
33+
34+
By setting a value for `refresh-cookie`, the proxy will refresh the Access Token after the specified duration. By setting a short duration (e.g. 5m, which is the default expiry for Access Token issued by Keycloak), this will allow sessions to be revoked quickly.
35+
36+
> For OAuth2 Proxy configuration, `refresh-cookie` does not work for `keycloak` provider but works for `oidc` provider.
37+
38+
## Hostname / Domain
39+
40+
The issuer of access token is the hostname / domain during browser login. Subsequent `POST` to token validation endpoint ( OAuth2 Proxy `validate_url` value if configured) by OAuth2 Proxy will fail with `{"error":"invalid_token","error_description":"Token verification failed"}` if the hostname is different.
41+
42+
For OAuth2 Proxy container to reach Keycloak using the same hostname / FQDN, an alias to Keycloak container is configured in `docker-compose.yml`.
43+
44+
```yml
45+
aliases:
46+
- keycloak.127.0.0.1.nip.io
47+
```
48+
49+
## Keycloak Export
50+
51+
```sh
52+
docker run --rm\
53+
--name keycloak_exporter\
54+
--network local\
55+
-v /tmp:/tmp/realm-config:Z\
56+
-e KEYCLOAK_USER=admin\
57+
-e KEYCLOAK_PASSWORD=password\
58+
-e DB_ADDR=mariadb\
59+
-e DB_USER=keycloak\
60+
-e DB_PASSWORD=password\
61+
-e DB_VENDOR=mariadb\
62+
jboss/keycloak:11.0.1\
63+
-Dkeycloak.migration.action=export\
64+
-Dkeycloak.migration.provider=dir\
65+
-Dkeycloak.migration.dir=/tmp/realm-config\
66+
-Dkeycloak.migration.usersExportStrategy=SAME_FILE
67+
```

config/oauth2-proxy.cfg

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
## OAuth2 Proxy Config File
2+
## https://github.com/oauth2-proxy/oauth2-proxy
3+
4+
## <addr>:<port> to listen on for HTTP/HTTPS clients
5+
# http_address = "127.0.0.1:4180"
6+
http_address="0.0.0.0:4180"
7+
# https_address = ":443"
8+
9+
## Are we running behind a reverse proxy? Will not accept headers like X-Real-Ip unless this is set.
10+
# reverse_proxy = true
11+
12+
## TLS Settings
13+
# tls_cert_file = ""
14+
# tls_key_file = ""
15+
16+
## the OAuth Redirect URL.
17+
# defaults to the "https://" + requested host header + "/oauth2/callback"
18+
redirect_url="http://nginx.127.0.0.1.nip.io:9000/oauth2/callback"
19+
20+
## the http url(s) of the upstream endpoint. If multiple, routing is based on path
21+
upstreams = [
22+
# static://200
23+
"http://server:8000/"
24+
]
25+
## Logging configuration
26+
#logging_filename = ""
27+
#logging_max_size = 100
28+
#logging_max_age = 7
29+
#logging_local_time = true
30+
#logging_compress = false
31+
#standard_logging = true
32+
#standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
33+
#request_logging = true
34+
#request_logging_format = "{{.Client}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"
35+
#auth_logging = true
36+
#auth_logging_format = "{{.Client}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}"
37+
38+
## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
39+
# pass_basic_auth = true
40+
# pass_user_headers = true
41+
## pass the request Host Header to upstream
42+
## when disabled the upstream Host is used as the Host Header
43+
# pass_host_header = true
44+
45+
## Email Domains to allow authentication for (this authorizes any email on this domain)
46+
## for more granular authorization use `authenticated_emails_file`
47+
## To authorize any email addresses use "*"
48+
# email_domains = [
49+
# "yourcompany.com"
50+
# ]
51+
email_domains = "*"
52+
53+
## The OAuth Client ID, Secret
54+
client_id = "server"
55+
client_secret = "d1680bbb-24f3-4835-a0d9-2a7492a4cc99"
56+
57+
## Pass OAuth Access token to upstream via "X-Forwarded-Access-Token"
58+
# pass_access_token = true
59+
60+
## Authenticated Email Addresses File (one email per line)
61+
# authenticated_emails_file = ""
62+
63+
## Htpasswd File (optional)
64+
## Additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -s" for SHA encryption
65+
## enabling exposes a username/login signin form
66+
# htpasswd_file = ""
67+
68+
## Templates
69+
## optional directory with custom sign_in.html and error.html
70+
# custom_templates_dir = ""
71+
72+
## skip SSL checking for HTTPS requests
73+
# ssl_insecure_skip_verify = false
74+
75+
76+
## Cookie Settings
77+
## Name - the cookie name
78+
## Secret - the seed string for secure cookies; should be 16, 24, or 32 bytes
79+
## for use with an AES cipher when cookie_refresh or pass_access_token
80+
## is set
81+
## Domain - (optional) cookie domain to force cookies to (ie: .yourcompany.com)
82+
## Expire - (duration) expire timeframe for cookie
83+
## Refresh - (duration) refresh the cookie when duration has elapsed after cookie was initially set.
84+
## Should be less than cookie_expire; set to 0 to disable.
85+
## On refresh, OAuth token is re-validated.
86+
## (ie: 1h means tokens are refreshed on request 1hr+ after it was set)
87+
## Secure - secure cookies are only sent by the browser of a HTTPS connection (recommended)
88+
## HttpOnly - httponly cookies are not readable by javascript (recommended)
89+
# cookie_name = "_oauth2_proxy"
90+
cookie_secret = "MTExMTExMTExMTExMTExMQ=="
91+
# cookie_domains = ""
92+
# cookie_expire = "168h"
93+
cookie_refresh = "5m"
94+
cookie_secure = false
95+
# cookie_httponly = true
96+
97+
oidc_issuer_url = "http://keycloak.127.0.0.1.nip.io:8080/auth/realms/dev"
98+
provider = "oidc"
99+
provider_display_name = "Keycloak"
100+
101+
request_logging = false
102+
# Optional: Set additional headers at http://nginx.127.0.0.1.nip.io:9000/oauth2/auth
103+
set_authorization_header = true
104+
set_xauthrequest = true

docker-compose.yaml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
version: '3.5'
2+
3+
services:
4+
5+
proxy:
6+
image: quay.io/oauth2-proxy/oauth2-proxy:v6.1.1
7+
container_name: oauth2-proxy
8+
command: --config /oauth2-proxy.cfg
9+
ports:
10+
- 4180:4180
11+
- 443:443
12+
networks:
13+
- proxy-network
14+
volumes:
15+
- ./config/oauth2-proxy.cfg:/oauth2-proxy.cfg
16+
depends_on:
17+
- keycloak
18+
19+
keycloak:
20+
image: jboss/keycloak:11.0.1
21+
environment:
22+
- DB_ADDR=mariadb
23+
- DB_USER=keycloak
24+
- DB_PASSWORD=password
25+
container_name: kc
26+
volumes:
27+
- ./keycloak:/tmp/realm-config
28+
command:
29+
[
30+
'-Dkeycloak.migration.action=import',
31+
'-Dkeycloak.migration.provider=dir',
32+
'-Dkeycloak.migration.dir=/tmp/realm-config',
33+
'-Dkeycloak.migration.strategy=IGNORE_EXISTING',
34+
]
35+
networks:
36+
proxy-network:
37+
aliases:
38+
- keycloak.127.0.0.1.nip.io
39+
ports:
40+
- 8080:8080
41+
depends_on:
42+
- mariadb
43+
44+
mariadb:
45+
image: mariadb:10.5.5
46+
environment:
47+
- MYSQL_DATABASE=keycloak
48+
- MYSQL_ROOT_PASSWORD=password
49+
- MYSQL_USER=keycloak
50+
- MYSQL_PASSWORD=password
51+
container_name: keycloak-db
52+
networks:
53+
- proxy-network
54+
volumes:
55+
- vol-mariadb:/var/lib/mysql
56+
57+
server:
58+
build: ./server
59+
image: server
60+
user: node
61+
working_dir: /usr/src/app
62+
environment:
63+
- NODE_ENV=production
64+
ports:
65+
- 8000:8000
66+
command: node .
67+
container_name: server
68+
networks:
69+
- proxy-network
70+
71+
nginx:
72+
image: nginx:alpine
73+
ports:
74+
- 9000:80
75+
container_name: nginx
76+
volumes:
77+
- ./nginx:/etc/nginx/conf.d
78+
networks:
79+
- proxy-network
80+
depends_on:
81+
- server
82+
- proxy
83+
84+
networks:
85+
proxy-network:
86+
name: local
87+
88+
volumes:
89+
vol-mariadb:

0 commit comments

Comments
 (0)