An OpenID Connect (OIDC) authentication proxy based on Openresty and using the lua-resty-openidc library.
This has been tested with Keycloak, however this should be able to be used with any OIDC provider.
A Docker compose configuration is included in this directory to show an example of this image in use. To use it, simply run docker-compose up
.
Note: This configuration relies on the containers using
localhost
to communicate, so it uses the host network. Due to docker/for-mac#1031 this means that it not work correctly on a Mac.
The following containers will be started:
- Keycloak - The OIDC provider to be used for authentication
- MariaDB - Used as the backend database for the Keycloak server
- httpbin - The upstream application behind the auth proxy
- ACP Auth Proxy - This repo's image
Once the message "starting nginx..." is shown from the auth-proxy container, then all of the containers should be up and ready to use. The Keycloak server will be running on port 8080, so you can go to the admin console by going to localhost:8080
and login using the admin credentials ("admin" for both the username and the password).
There is a bootstrap.sh
script that runs in the auth proxy image before starting nginx. This script will create a new realm, client and user in Keycloak for use with the auth proxy. See compose/auth-test-realm.json for the specific configuration.
To use the auth proxy, go to localhost:8081
and login using "testuser" for the username and "securepassword" for the password. You should successfully log in and be sent to httpbin, which is running on port 80. You can also logout again by going adding /logout
to the url.
Here is an example of how you can use this image in a Kubernetes cluster:
...
- name: auth-proxy
image: quay.io/ukhomeofficedigital/acp-auth-proxy
ports:
- containerPort: 8080
name: http
- containerPort: 10443
name: https
env:
- name: DISCOVERY_URL
value: "<OpenID issuer URL>"
- name: CLIENT_ID
value: "my-client"
- name: CLIENT_SECRET
value: "my-secret"
- name: SESSION_SECRET
value: "d4ceec19c5d948539739dbac2efff26f"
- name: UPSTREAM_URL
value: "https://google.com"
securityContext:
runAsUser: 1000
runAsNonRoot: true
livenessProbe:
httpGet:
path: /oauth/health
port: 10443
scheme: HTTPS
initialDelaySeconds: 5
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /oauth/health
port: 10443
scheme: HTTPS
initialDelaySeconds: 5
timeoutSeconds: 1
volumeMounts:
...
Variable | Description | Required | Default |
---|---|---|---|
CLIENT_ID | The Oauth client ID for the application | Y | N/A |
CLIENT_SECRET | The Oauth client secret for the application | Y | N/A |
DISCOVERY_URL | The URL to get the OpenID configuration and endpoints. This adds /.well-known/openid-configuration to the end of this so this should be the issuer url. Example: http://localhost/auth/realms/my-realm |
Y | N/A |
SESSION_SECRET | The secret used to encrypt the session state | Y | N/A |
UPSTREAM_URL | The upstream endpoint this proxies to after successfully authenticating | Y | N/A |
CLIENT_AUTH_METHOD | The auth method used for the client (currently this only supports client_secret_post and client_secret_basic ) |
N | client_secret_post |
HTTP_LISTEN_PORT | The port this should listen on | N | 8080 |
HTTPS_LISTEN_PORT | The TLS port this should listen on | N | 10443 |
GROUPS_CLAIM | The claim that should be used to get the groups from the access token. This does not support nested values (note: this is used to set the X-Auth-Groups header) |
N | N\A |
JSON_LOGGING_ENABLED | Should NGINX log using JSON? (note: this only affects the access logs) | N | true |
NGINX_RESOLVER | The DNS server NGINX should use | N | 8.8.8.8 |
LOG_LEVEL | The NGINX log level | N | info |
LOGOUT_PATH | The path used to logout of the provider | N | /oauth/logout |
REDIRECT_URL | The path the provider will send the user to after authenticating (this can be a path or a full url e.g. http://localhost/myapp/callback ) |
N | /oauth/callback |
REVOKE_TOKENS_ON_LOGOUT | Should the provider revoke the user's access and refresh tokens when they log out? (note: revocation_endpoint must be in the list of endpoints returned by the discovery url for this to work. This failing will not stop a logout) |
N | true |
ROLES_CLAIM | The claim that should be used to get the roles from the access token. This does not support nested values (note: this is used to set the X-Auth-Roles header) |
N | ['realm_access']['roles'] |
SET_AUTH_HEADER | Should the Authorization: Bearer header be set? |
N | true |
SET_TOKEN_HEADER | Should the X-Auth-Token header be set? |
N | true |
SCOPES | What additional scopes should be used (openid will always be used). Accepted formats: scope1 scope2 ; scope1, scope2 ; scope1, scope2 |
N | N/A |
SILENT_TOKEN_RENEWAL | Should this silently try to renew the access token when it expires? (if a refresh token is available) | N | false |
TLS_CERT | Path the the TLS cert | N | /certs/tlscert.crt (note: this is self-signed) |
TLS_PRIVATE_KEY | Path the the TLS private key | N | /certs/tlskey.key (note: this is self-signed) |
There is a default Nginx configuration provided at that can be found here and the image's entrypoint script will substitute in values (such as the listen ports) as needed.
We provide some default location blocks here, that will force authentication on every path except for /oauth/health
. It will also set various headers that may be useful for the upstream application to consume. The /oauth/health
location block is intended to be used for checking the health of the container, and requests to it will not be logged. The Lua code that does the authentication can be found here.
When using the default Nginx config, you can add extra location blocks by adding them to the /usr/local/openresty/nginx/conf/locations/
directory (any file with the .conf
extension will be included). /usr/local/openresty/nginx/conf/lua/?.lua
is included in Lua's package path, so if you want to add your own functions/modules, you can add them to that directory and use them in your locations
While an Nginx config, location blocks and Lua code for authentication is all provided, these can all be overridden via volume mounts to suit your application's needs. For example, you can override the default location block with your own configuration:
docker run \
<other configuration options>
-v my-custom-default-location.conf:/usr/local/openresty/nginx/conf/locations/default.conf
quay.io/ukhomeofficedigital/acp-auth-proxy
Or if you want to change the Nginx config, you could override it with your own.
Note: If you override the Nginx config with a volume mount, then you should explicitly set the values in that file, and you may want to override the default command for the image as the
sed
commands will not work assed
cannot do an in-place replacement on mounted files (e.g. instead of puttinglisten $http_listen_port
like in the default config, set it to an actual value:listen 8080
).