Overview
Sometimes, integrating authentication and access control in your application can take a lot of time, especially when you are initially developing a new application and just want to validate "fit for purpose" before investing a lot of development effort to integrate with an SSO solution. One way to simplify this is by using a tool like OAuth2 Proxy. OAuth2 Proxy can be placed in front of your application like a reverse proxy and enforce authentication for your application and pass various OAuth2/OpenID parameters to your application as headers. This makes the burden to test authentication much lower and allows tighter integration later, once the application is determined to have value and should have more development time allocated.
Getting Started
For demonstration purposes, this tutorial will use Podman, but the resources we will use should be compatible to be deployed on Kubernetes as well.
Thus, the first step is to create a ConfigMap or a Secret to hold the configuration data. An example configuration is shown below:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
proxy.yaml: |
server:
BindAddress: 0.0.0.0:4180
SecureBindAddress: "-"
upstreamConfig:
upstreams:
- flushInterval: 1s
id: whoami
passHostHeader: true
path: /
proxyWebSockets: true
uri: http://localhost:80/
injectRequestHeaders:
- name: X-Forwarded-Groups
values:
- claim: groups
- name: X-Forwarded-User
values:
- claim: user
- name: X-Forwarded-Email
values:
- claim: email
- name: X-Forwarded-Preferred-Username
values:
- claim: preferred_username
- name: X-Forwarded-Access-Token
values:
- claim: access_token
- name: Authorization
values:
- claim: access_token
prefix: "Bearer "
providers:
- clientID: <Your OpenID client ID>
clientSecret: <Your OpenID client secret>
id: <arbitrary id>
oidcConfig:
emailClaim: email
groupsClaim: groups
# insecureAllowUnverifiedEmail: true
# insecureSkipNonce: true
userIDClaim: email
issuerURL: http://keycloak:8080/auth/realms/<Your Keycloak Realm (for example)>
audienceClaims:
- aud
provider: oidcA full reference of all possible configuration options is available HERE
A Deployment Using oauth2-proxy
Next, define your Deployment. The example below shows running two containers in a single Pod and exposing the oauth2-proxy port while keeping the actual application listener port hidden within the pod. This means that the ONLY way that requests can reach the application by successfully getting through the proxy.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
replicas: 3
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
volumes:
- name: oauth2-config
configMap: ## Or a Secret is possible as well!
name: oauth2-config
items:
- key: proxy.yaml
path: proxy.yaml
containers:
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
ports:
- containerPort: 4180
hostPort: 8080 ## On Kubernetes, you would connect this port to a `Service` instead of defining a `hostPort`
env:
- name: OAUTH2_PROXY_COOKIE_SECURE
value: "false"
- name: OAUTH2_PROXY_COOKIE_SECRET
value: <REDACTED> # Generate a strong random set of characters which will be used to encrypt the cookies used by oauth2-proxy
- name: OAUTH2_PROXY_COOKIE_REFRESH
value: 4m30s
- name: OAUTH2_PROXY_EMAIL_DOMAINS
value: '*' # You can limit the e-mail domains which will be accepted
- name: OAUTH2_PROXY_SKIP_PROVIDER_BUTTON
value: "true" # Should the OAuth2 login button be shown or should the user be immediately redirected to the SSO provider?
volumeMounts:
- name: oauth2-config
mountPath: /proxy.yaml # Referenced in the `args` below
args:
- --alpha-config
- /proxy.yaml
- name: whoami
image: docker.io/traefik/whoami:latest
# ports: # You do not need to expose this port since oauth2-proxy is part of the same pod and uses the same network namespace
# - containerPort: 80Deploy To Podman
By combining the 2 yaml files above you can deploy them both using Podman and test out your configuration:
podman kube play combined.yamlDeploy To Kubernetes
The only changes you need to make to the above items is to add a Service resource and either an Ingress or Route resource to expose the service outside of the cluster