├── proxy.png ├── proxy-basic-auth ├── .htpasswd ├── img │ ├── basic-auth.png │ └── proxy-basic.png ├── README.md ├── default.conf.template └── docker-compose.yml ├── proxy-header-auth ├── .htpasswd ├── img │ ├── proxy-header-auth.png │ ├── firefly-header-auth.png │ └── tandoor-header-auth.png ├── docker-compose.yml ├── README.md └── default.conf.template ├── app-no-auth ├── img │ └── no-auth.png ├── README.md ├── default.conf.template └── docker-compose.yml ├── app-oauth-auth ├── img │ ├── oauth-auth.png │ ├── oauth-logged.png │ └── oauth-login.png ├── users.json ├── oidc-config ├── README.md ├── default.conf.template └── docker-compose.yml ├── app-internal-auth ├── img │ ├── spring-auth.png │ ├── tandoor-auth.png │ └── internal-auth.png ├── docker-compose.yml ├── default.conf.template └── README.md ├── proxy-auth-request ├── img │ ├── oauth-login.png │ ├── auth-request.png │ └── oauth2-proxy.png ├── auth.conf ├── users.json ├── proxy.conf ├── oidc-config ├── oauth_endpoint.conf ├── default.conf.template ├── README.md └── docker-compose.yml └── README.md /proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy.png -------------------------------------------------------------------------------- /proxy-basic-auth/.htpasswd: -------------------------------------------------------------------------------- 1 | user2:$apr1$OaLLh6ME$l1E5rxlGkTpNj4mM4o5ZA. 2 | user:$apr1$1KaWCHcy$I5cGFdJhUe070325jiiYY. 3 | -------------------------------------------------------------------------------- /proxy-header-auth/.htpasswd: -------------------------------------------------------------------------------- 1 | user2:$apr1$OaLLh6ME$l1E5rxlGkTpNj4mM4o5ZA. 2 | user:$apr1$1KaWCHcy$I5cGFdJhUe070325jiiYY. 3 | -------------------------------------------------------------------------------- /app-no-auth/img/no-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-no-auth/img/no-auth.png -------------------------------------------------------------------------------- /app-oauth-auth/img/oauth-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-oauth-auth/img/oauth-auth.png -------------------------------------------------------------------------------- /app-oauth-auth/img/oauth-logged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-oauth-auth/img/oauth-logged.png -------------------------------------------------------------------------------- /app-oauth-auth/img/oauth-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-oauth-auth/img/oauth-login.png -------------------------------------------------------------------------------- /proxy-basic-auth/img/basic-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-basic-auth/img/basic-auth.png -------------------------------------------------------------------------------- /proxy-basic-auth/img/proxy-basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-basic-auth/img/proxy-basic.png -------------------------------------------------------------------------------- /app-internal-auth/img/spring-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-internal-auth/img/spring-auth.png -------------------------------------------------------------------------------- /app-internal-auth/img/tandoor-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-internal-auth/img/tandoor-auth.png -------------------------------------------------------------------------------- /proxy-auth-request/img/oauth-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-auth-request/img/oauth-login.png -------------------------------------------------------------------------------- /app-internal-auth/img/internal-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/app-internal-auth/img/internal-auth.png -------------------------------------------------------------------------------- /proxy-auth-request/auth.conf: -------------------------------------------------------------------------------- 1 | auth_request /oauth2/auth; 2 | error_page 401 = http://oauth2.apps.localhost/oauth2/sign_in?rd=$scheme://$host$request_uri; -------------------------------------------------------------------------------- /proxy-auth-request/img/auth-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-auth-request/img/auth-request.png -------------------------------------------------------------------------------- /proxy-auth-request/img/oauth2-proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-auth-request/img/oauth2-proxy.png -------------------------------------------------------------------------------- /proxy-header-auth/img/proxy-header-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-header-auth/img/proxy-header-auth.png -------------------------------------------------------------------------------- /proxy-header-auth/img/firefly-header-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-header-auth/img/firefly-header-auth.png -------------------------------------------------------------------------------- /proxy-header-auth/img/tandoor-header-auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/morganridel/proxy-authn-docker-demo/HEAD/proxy-header-auth/img/tandoor-header-auth.png -------------------------------------------------------------------------------- /app-oauth-auth/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "SIMPLE_OIDC_USER", 4 | "email": "user@localhost.com", 5 | "email_verified": true, 6 | "name": "User Mock", 7 | "nickname": "user", 8 | "password": "password", 9 | "groups": ["users"] 10 | } 11 | ] -------------------------------------------------------------------------------- /proxy-auth-request/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "SIMPLE_OIDC_USER", 4 | "email": "user@localhost.com", 5 | "email_verified": true, 6 | "name": "User Mock", 7 | "nickname": "user", 8 | "password": "password", 9 | "groups": ["users"] 10 | } 11 | ] -------------------------------------------------------------------------------- /app-no-auth/README.md: -------------------------------------------------------------------------------- 1 | # No authentication 2 | 3 | ![](img/no-auth.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.localhost 17 | * No authentication required 18 | * http://app2.localhost 19 | * No authentication required -------------------------------------------------------------------------------- /app-internal-auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | ports: 9 | - "80:80" 10 | 11 | app1: 12 | image: vabene1111/recipes:1.0.3 13 | environment: 14 | - GUNICORN_MEDIA=1 15 | 16 | app2: 17 | image: hubae/jwt-spring-security-demo:2.0.0 -------------------------------------------------------------------------------- /app-no-auth/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | server { 4 | listen 80; 5 | server_name app1.localhost; 6 | 7 | location / { 8 | set $upstream_app1 app1:19999; 9 | proxy_pass http://$upstream_app1; 10 | } 11 | } 12 | 13 | server { 14 | listen 80; 15 | server_name app2.localhost; 16 | 17 | location / { 18 | set $upstream_app2 app2:80; 19 | proxy_pass http://$upstream_app2; 20 | } 21 | } -------------------------------------------------------------------------------- /app-internal-auth/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | server { 4 | listen 80; 5 | server_name app1.localhost; 6 | 7 | location / { 8 | set $upstream_app1 app1:8080; 9 | proxy_pass http://$upstream_app1; 10 | } 11 | } 12 | 13 | server { 14 | listen 80; 15 | server_name app2.localhost; 16 | 17 | location / { 18 | set $upstream_app2 app2:8080; 19 | proxy_pass http://$upstream_app2; 20 | } 21 | } -------------------------------------------------------------------------------- /proxy-auth-request/proxy.conf: -------------------------------------------------------------------------------- 1 | 2 | #Timeout if the real server is dead 3 | proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; 4 | 5 | # Advanced Proxy Config 6 | send_timeout 5m; 7 | proxy_read_timeout 360; 8 | proxy_send_timeout 360; 9 | proxy_connect_timeout 360; 10 | 11 | # Basic Proxy Config 12 | proxy_set_header Host $host; 13 | proxy_set_header X-Real-IP $remote_addr; 14 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 15 | proxy_set_header X-Forwarded-Proto $scheme; 16 | proxy_set_header X-Forwarded-Host $http_host; 17 | proxy_set_header X-Forwarded-Uri $request_uri; -------------------------------------------------------------------------------- /app-internal-auth/README.md: -------------------------------------------------------------------------------- 1 | # Internal authentication 2 | 3 | ![](img/internal-auth.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.localhost 17 | * Authentication required in the app 18 | * Superuser can be created on first use 19 | * http://app2.localhost 20 | * Authentication required in the app 21 | * Credentials: admin/admin 22 | 23 | ## Screenshots 24 | 25 | ![](img/tandoor-auth.png) 26 | ![](img/spring-auth.png) -------------------------------------------------------------------------------- /app-oauth-auth/oidc-config: -------------------------------------------------------------------------------- 1 | { 2 | "idp_name": "http://auth.localhost/", 3 | "port": 9000, 4 | "client_config": [ 5 | { 6 | "client_id": "foo", 7 | "client_secret": "bar", 8 | "redirect_uris": [ 9 | "http://app1.localhost/api/callback" 10 | ] 11 | }, 12 | { 13 | "client_id": "oof", 14 | "client_secret": "rab", 15 | "redirect_uris": [ 16 | "http://app2.localhost/api/callback" 17 | ] 18 | } 19 | ], 20 | "claim_mapping": { 21 | "openid": [ "sub" ], 22 | "email": [ "email", "email_verified" ], 23 | "profile": [ "name", "nickname" ] 24 | } 25 | } -------------------------------------------------------------------------------- /proxy-auth-request/oidc-config: -------------------------------------------------------------------------------- 1 | { 2 | "idp_name": "http://auth.apps.localhost/", 3 | "port": 9000, 4 | "client_config": [ 5 | { 6 | "client_id": "oauth2-proxy", 7 | "client_secret": "secret", 8 | "redirect_uris": [ 9 | "http://oauth2.apps.localhost/oauth2/callback" 10 | ] 11 | }, 12 | { 13 | "client_id": "oof", 14 | "client_secret": "rab", 15 | "redirect_uris": [ 16 | "http://app2.apps.localhost/api/callback" 17 | ] 18 | } 19 | ], 20 | "claim_mapping": { 21 | "openid": [ "sub" ], 22 | "email": [ "email", "email_verified" ], 23 | "profile": [ "name", "nickname" ] 24 | } 25 | } -------------------------------------------------------------------------------- /proxy-basic-auth/README.md: -------------------------------------------------------------------------------- 1 | # Proxy Basic Auth 2 | 3 | ![](img/proxy-basic.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.localhost 17 | * Authentication (auth_basic) required 18 | * Credentials: user/password OR user2/password2 19 | * http://app2.localhost 20 | * Authentication (auth_basic) required 21 | * Credentials: user/password OR user2/password2; 22 | 23 | Apps that don't have internal authentication are protected with basic auth. 24 | 25 | ## Screenshots 26 | 27 | ![](img/basic-auth.png) -------------------------------------------------------------------------------- /proxy-basic-auth/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | server { 4 | listen 80; 5 | server_name app1.localhost; 6 | auth_basic "Restricted area"; 7 | auth_basic_user_file /etc/nginx/.htpasswd; 8 | 9 | location / { 10 | set $upstream_app1 app1:19999; 11 | proxy_pass http://$upstream_app1; 12 | } 13 | } 14 | 15 | server { 16 | listen 80; 17 | server_name app2.localhost; 18 | 19 | auth_basic "Restricted area"; 20 | auth_basic_user_file /etc/nginx/.htpasswd; 21 | 22 | location / { 23 | set $upstream_app2 app2:80; 24 | proxy_pass http://$upstream_app2; 25 | } 26 | } -------------------------------------------------------------------------------- /app-no-auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | ports: 9 | - "80:80" 10 | 11 | app1: 12 | image: netdata/netdata:v1.32.1 13 | ports: 14 | - 19999:19999 15 | cap_add: 16 | - SYS_PTRACE 17 | security_opt: 18 | - apparmor:unconfined 19 | volumes: 20 | - /etc/passwd:/host/etc/passwd:ro 21 | - /etc/group:/host/etc/group:ro 22 | - /proc:/host/proc:ro 23 | - /sys:/host/sys:ro 24 | - /etc/os-release:/host/etc/os-release:ro 25 | 26 | app2: 27 | image: dahuss/a-dark-room:2017.08.04 -------------------------------------------------------------------------------- /proxy-header-auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | - ./.htpasswd:/etc/nginx/.htpasswd 9 | ports: 10 | - "80:80" 11 | 12 | app1: 13 | image: vabene1111/recipes:1.0.3 14 | environment: 15 | - GUNICORN_MEDIA=1 16 | - REVERSE_PROXY_AUTH=1 17 | 18 | app2: 19 | image: fireflyiii/core:version-5.6.9 20 | environment: 21 | - APP_KEY=NtrY8ftJgwdt4OC8dNVEtRoNxFVS8PeA 22 | - DB_CONNECTION=sqlite 23 | - AUTHENTICATION_GUARD=remote_user_guard 24 | - APP_URL=http://app2.localhost 25 | - TRUSTED_PROXIES=** 26 | -------------------------------------------------------------------------------- /proxy-basic-auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | - ./.htpasswd:/etc/nginx/.htpasswd 9 | ports: 10 | - "80:80" 11 | 12 | app1: 13 | image: netdata/netdata:v1.32.1 14 | ports: 15 | - 19999:19999 16 | cap_add: 17 | - SYS_PTRACE 18 | security_opt: 19 | - apparmor:unconfined 20 | volumes: 21 | - /etc/passwd:/host/etc/passwd:ro 22 | - /etc/group:/host/etc/group:ro 23 | - /proc:/host/proc:ro 24 | - /sys:/host/sys:ro 25 | - /etc/os-release:/host/etc/os-release:ro 26 | 27 | app2: 28 | image: dahuss/a-dark-room:2017.08.04 -------------------------------------------------------------------------------- /proxy-auth-request/oauth_endpoint.conf: -------------------------------------------------------------------------------- 1 | location /oauth2/ { 2 | proxy_set_header Host $host; 3 | proxy_set_header X-Real-IP $remote_addr; 4 | proxy_set_header X-Scheme $scheme; 5 | proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; 6 | 7 | set $oauth2 oauth2-proxy:4180; 8 | proxy_pass http://$oauth2; 9 | } 10 | location = /oauth2/auth { 11 | proxy_set_header Host $host; 12 | proxy_set_header X-Real-IP $remote_addr; 13 | proxy_set_header X-Scheme $scheme; 14 | # nginx auth_request includes headers but not body 15 | proxy_set_header Content-Length ""; 16 | proxy_pass_request_body off; 17 | 18 | set $oauth2 oauth2-proxy:4180; 19 | proxy_pass http://$oauth2; 20 | } -------------------------------------------------------------------------------- /proxy-header-auth/README.md: -------------------------------------------------------------------------------- 1 | # Proxy Header Authentication 2 | 3 | ![](img/proxy-header-auth.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.localhost 17 | * Authentication (auth_basic) required 18 | * Credentials: user/password OR user2/password2 19 | * http://app2.localhost 20 | * Authentication (auth_basic) required 21 | * Credentials: user/password OR user2/password2; 22 | 23 | Apps trust a HTTP header set by the proxy as an authenticated user. In this example, the header is set based on auth_basic. 24 | 25 | ## Screenshots 26 | 27 | ![](img/tandoor-header-auth.png) 28 | ![](img/firefly-header-auth.png) -------------------------------------------------------------------------------- /app-oauth-auth/README.md: -------------------------------------------------------------------------------- 1 | # OpenID Connect Authentication 2 | 3 | ![](img/oauth-auth.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.localhost 17 | * OpenID Connect Authentication 18 | * http://app2.localhost 19 | * OpenID Connect Authentication 20 | * http://auth.localhost 21 | * OpenID Connect authorization server 22 | * Discovery URL: http://auth.localhost/.well-known/openid-configuration 23 | * Credentials: user@localhost.com/password 24 | 25 | After a first login, user can login in another app without entering his credentials again 26 | 27 | ## Screenshots 28 | 29 | ![](img/oauth-login.png) 30 | ![](img/oauth-logged.png) -------------------------------------------------------------------------------- /proxy-header-auth/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | server { 4 | listen 80; 5 | server_name app1.localhost; 6 | auth_basic "Restricted"; 7 | auth_basic_user_file /etc/nginx/.htpasswd; 8 | 9 | location / { 10 | proxy_set_header Host $http_host; 11 | proxy_set_header Remote-User $remote_user; 12 | 13 | set $upstream_app1 app1:8080; 14 | proxy_pass http://$upstream_app1; 15 | } 16 | } 17 | 18 | server { 19 | listen 80; 20 | server_name app2.localhost; 21 | 22 | auth_basic "Restricted"; 23 | auth_basic_user_file /etc/nginx/.htpasswd; 24 | 25 | location / { 26 | set $upstream_app2 app2:8080; 27 | proxy_pass http://$upstream_app2; 28 | 29 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 30 | proxy_set_header REMOTE_USER $remote_user; 31 | proxy_set_header Host $http_host; 32 | } 33 | } -------------------------------------------------------------------------------- /app-oauth-auth/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | proxy_set_header Host $host; 4 | proxy_set_header X-Real-IP $remote_addr; 5 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 6 | proxy_set_header X-Forwarded-Host $host; 7 | proxy_set_header X-Forwarded-Server $host; 8 | proxy_set_header X-Forwarded-Port $server_port; 9 | proxy_set_header X-Forwarded-Proto $scheme; 10 | 11 | server { 12 | listen 80; 13 | server_name auth.localhost; 14 | 15 | location / { 16 | set $auth_provider oidc-provider:9000; 17 | proxy_pass http://$auth_provider; 18 | } 19 | } 20 | 21 | server { 22 | listen 80; 23 | server_name app1.localhost; 24 | 25 | location / { 26 | set $upstream_app1 oidc-client-1:3000; 27 | proxy_pass http://$upstream_app1; 28 | } 29 | } 30 | 31 | server { 32 | listen 80; 33 | server_name app2.localhost; 34 | 35 | location / { 36 | set $upstream_app2 oidc-client-2:3000; 37 | proxy_pass http://$upstream_app2; 38 | } 39 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Authentication methods with a reverse proxy 2 | 3 | This repository contains code examples of different means of authentication when multiples apps are behind a reverse-proxy. 4 | 5 | It is meant to illustrate my [blog post on authentication behind a proxy](http://morganridel.fr/authentication-for-multiple-apps-behind-a-reverse-proxy) and assumes no control over the source code of the upstream apps. 6 | 7 | ![](proxy.png) 8 | 9 | ## Running the examples 10 | 11 | Make sure that all the subdomains (`*.localhost`) redirects to the nginx server ip! 12 | Every `*.localhost` URL shoud send you to 127.0.0.1 by default but you may need to modify your /etc/hosts file to make this work. 13 | 14 | Cache issues may arise between examples. If you enconter problem, clean your cache or try in a private browsing window. 15 | 16 | * **App-based authentication** 17 | * [No authentication](./app-no-auth) 18 | * [Internal authentication](./app-internal-auth) 19 | * [OpenID Connect authentication](./app-oauth-auth) 20 | * **Proxy-based authentication** 21 | * [Basic authentication](./proxy-basic-auth) 22 | * [HTTP header authentication](./proxy-header-auth) 23 | * [Auth request authentication](./proxy-auth-request) -------------------------------------------------------------------------------- /app-oauth-auth/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | ports: 9 | - "80:80" 10 | 11 | oidc-provider: 12 | image: qlik/simple-oidc-provider:0.2.5 13 | environment: 14 | - CONFIG_FILE=/etc/config.json 15 | - USERS_FILE=/etc/users.json 16 | volumes: 17 | - ./oidc-config:/etc/config.json:ro 18 | - ./users.json:/etc/users.json:ro 19 | 20 | 21 | oidc-client-1: 22 | image: morganridel/mock-oidc-client:0.0.1 23 | environment: 24 | - ISSUER_BASE_URL=http://auth.localhost 25 | - BASE_URL=http://app1.localhost/api 26 | - CLIENT_ID=foo 27 | - CLIENT_SECRET=bar 28 | - SECRET=random-string-a5t8df86s 29 | extra_hosts: 30 | - "auth.localhost:172.17.0.1" # docker host ip 31 | # - "auth.localhost:192.168.1.x" # This should also work with host lan IP 32 | 33 | oidc-client-2: 34 | image: morganridel/mock-oidc-client:0.0.1 35 | environment: 36 | - ISSUER_BASE_URL=http://auth.localhost 37 | - BASE_URL=http://app2.localhost/api 38 | - CLIENT_ID=oof 39 | - CLIENT_SECRET=rab 40 | - SECRET=random-string-bg8uf3q4a 41 | extra_hosts: 42 | - "auth.localhost:172.17.0.1" # docker host ip -------------------------------------------------------------------------------- /proxy-auth-request/default.conf.template: -------------------------------------------------------------------------------- 1 | resolver 127.0.0.11 valid=15s; # docker resolver 2 | 3 | server { 4 | listen 80; 5 | server_name auth.apps.localhost; 6 | 7 | location / { 8 | proxy_set_header Host $host; 9 | proxy_set_header X-Real-IP $remote_addr; 10 | 11 | set $auth_provider oidc-provider:9000; 12 | proxy_pass http://$auth_provider; 13 | } 14 | } 15 | 16 | server { 17 | listen 80; 18 | server_name oauth2.apps.localhost; 19 | 20 | location / { 21 | proxy_set_header Host $host; 22 | proxy_set_header X-Real-IP $remote_addr; 23 | 24 | set $oauth2 oauth2-proxy:4180; 25 | proxy_pass http://$oauth2; 26 | } 27 | } 28 | 29 | server { 30 | listen 80; 31 | server_name app1.apps.localhost; 32 | 33 | include /config/nginx/oauth_endpoint.conf; 34 | 35 | location / { 36 | include /config/nginx/auth.conf; 37 | 38 | set $upstream_app1 app1:8080; 39 | proxy_pass http://$upstream_app1; 40 | } 41 | } 42 | 43 | server { 44 | listen 80; 45 | server_name app2.apps.localhost; 46 | 47 | include /config/nginx/oauth_endpoint.conf; 48 | 49 | location / { 50 | include /config/nginx/auth.conf; 51 | 52 | set $upstream_app2 app2:3000; 53 | proxy_pass http://$upstream_app2; 54 | } 55 | } -------------------------------------------------------------------------------- /proxy-auth-request/README.md: -------------------------------------------------------------------------------- 1 | # Proxy Auth Request 2 | 3 | ![](img/auth-request.png) 4 | 5 | This schema represents the concept and not the exact architcture in the code. 6 | ## Run 7 | 8 | ``` 9 | docker-compose up 10 | ``` 11 | 12 | ## Usage 13 | 14 | The following apps are available: 15 | 16 | * http://app1.apps.localhost 17 | * Auth request authentication + internal authentication 18 | * Authentication at the proxy doesn't prevent internal auth if the app isn't aware of it 19 | * http://app2.apps.localhost 20 | * Auth request authentication + OpenID Connect Authentication 21 | * User doesn't need to enter his credential again after accessing the app because the same authorization server is used. 22 | * http://oauth2.apps.localhost 23 | * Auth Request server 24 | * Uses http://auth.apps.localhost as an authentication backend 25 | * http://auth.apps.localhost 26 | * OpenID Connect authorization server 27 | * Discovery URL: http://auth.apps.localhost/.well-known/openid-configuration 28 | * Credentials: user@localhost.com/password 29 | 30 | **Special case here**: cookies can't be set for domain `.localhost` because it does not have at least 2 dots like a real domain. Therefore all the apps will be under `.apps.localhost` in this example. 31 | 32 | Each app is protected by a request to the auth request server. 33 | 34 | Auth request server could be anything that can respond 20x or 40x to subrequests. Here [OAuth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/) uses an OpenID Connect authorization server to validate requests. 35 | 36 | Since http://app2.apps.localhost is an OAuth2 client, it can use the same authorization server. 37 | 38 | ## Screenshots 39 | 40 | ![](img/oauth2-proxy.png) 41 | ![](img/oauth-login.png) -------------------------------------------------------------------------------- /proxy-auth-request/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | proxy: 5 | image: nginx:1.21.4 6 | volumes: 7 | - ./default.conf.template:/etc/nginx/templates/default.conf.template 8 | - ./auth.conf:/config/nginx/auth.conf 9 | - ./oauth_endpoint.conf:/config/nginx/oauth_endpoint.conf 10 | - ./proxy.conf:/config/nginx/proxy.conf 11 | ports: 12 | - "80:80" 13 | 14 | oidc-provider: 15 | image: qlik/simple-oidc-provider:0.2.5 16 | healthcheck: 17 | test: wget -nv -t1 --spider 'http://127.0.0.1:9000/.well-known/openid-configuration' || exit 1 18 | interval: 5s 19 | timeout: 10s 20 | retries: 3 21 | start_period: 5s 22 | environment: 23 | - CONFIG_FILE=/etc/config.json 24 | - USERS_FILE=/etc/users.json 25 | volumes: 26 | - ./oidc-config:/etc/config.json:ro 27 | - ./users.json:/etc/users.json:ro 28 | 29 | oauth2-proxy: 30 | image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 31 | depends_on: 32 | oidc-provider: 33 | condition: service_healthy 34 | environment: 35 | - OAUTH2_PROXY_PROVIDER=oidc 36 | - OAUTH2_PROXY_OIDC_ISSUER_URL=http://auth.apps.localhost/ 37 | - OAUTH2_PROXY_CLIENT_ID=oauth2-proxy 38 | - OAUTH2_PROXY_CLIENT_SECRET=secret 39 | - OAUTH2_PROXY_REDIRECT_URL=http://oauth2.apps.localhost/oauth2/callback 40 | - OAUTH2_PROXY_COOKIE_SECURE=false 41 | - OAUTH2_PROXY_COOKIE_HTTPONLY=true 42 | - OAUTH2_PROXY_COOKIE_EXPIRE=168h0m0s 43 | - OAUTH2_PROXY_COOKIE_SAMESITE=lax 44 | - OAUTH2_PROXY_COOKIE_REFRESH=0 45 | - OAUTH2_PROXY_COOKIE_DOMAINS=.apps.localhost 46 | - OAUTH2_PROXY_WHITELIST_DOMAINS=.localhost 47 | - OAUTH2_PROXY_COOKIE_SECRET=abcdefghiklmnlop 48 | - OAUTH2_PROXY_EMAIL_DOMAINS=localhost.com 49 | - OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180 50 | - OAUTH2_PROXY_REVERSE_PROXY=true 51 | extra_hosts: 52 | - "auth.apps.localhost:172.17.0.1" 53 | 54 | app1: 55 | image: vabene1111/recipes:1.0.3 56 | environment: 57 | - GUNICORN_MEDIA=1 58 | 59 | app2: 60 | image: morganridel/mock-oidc-client:0.0.1 61 | environment: 62 | - ISSUER_BASE_URL=http://auth.apps.localhost 63 | - BASE_URL=http://app2.apps.localhost/api 64 | - CLIENT_ID=oof 65 | - CLIENT_SECRET=rab 66 | - SECRET=random-string-a5t8df86s 67 | extra_hosts: 68 | - "auth.apps.localhost:172.17.0.1" 69 | --------------------------------------------------------------------------------