Run the DLS login proxy#
This is for the scrap admins at DLS. Every DLS user’s scrap (installed with Install scrap at DLS) logs in through one central oauth2-proxy against DLS Keycloak. This page sets it up and keeps it running.
How it fits together#
The proxy runs in its own namespace,
scrapby default. Only that namespace holds the Keycloak client secret and the proxy’s cookie secret; users never see them.Each user’s scrap has two Ingresses on
scrap-<fedid>.diamond.ac.uk. The main one sends every request to the proxy first (ingress-nginx’sauth-url), which needs a DLS login; scrap then lets in only that user’s fedid, from the token the proxy passes on. The other has no login and carries/mcp(scrap’s bearer token guards it) and/oauth2, which reaches the proxy through anExternalNameService in the user’s namespace.The proxy has no fixed callback address and no cookie domain, so each user’s login and cookie belong to that user’s host alone. That is why Keycloak needs one exact redirect URI per user.
Any DLS login passes the proxy, on any user’s host: the
auth-urlcarries noallowed_emails, because DLS’s ingress-nginx refuses an@or%in it. Each user’s scrap admits only its owner, by the fedid in the access token (preferred_username): another DLS user who logs in there gets scrap’s401. DLS Keycloak does not verify emails, so the proxy runs withinsecure_oidc_allow_unverified_email; the email is not what lets anyone in.The proxy passes the user’s Keycloak access token on (
pass_access_token), and scrap checks it on every request (45. scrap verifies the login proxy’s Keycloak token). argus users cannot make NetworkPolicies, so a pod in the cluster can reach a user’s scrap Service directly, but without a valid Keycloak token for that user it gets401;/mcpneeds its bearer token. The proxy refreshes the session every minute, inside the access token’s 5 minutes. Withoutoffline_access, a user stays logged in only as long as their DLS Keycloak session; when it ends, the next refresh fails and they log in again.
The chart side is authProxy (A central oauth2-proxy with ingress-nginx). The proxy is the upstream oauth2-proxy
chart, pinned in deploy/dls/auth-proxy/install.sh, with deploy/dls/auth-proxy/values.yaml.
1. Request the Keycloak client#
Ask the DLS Keycloak team for one client in the dls realm
(https://identity.diamond.ac.uk/realms/dls):
Confidential (client authentication on), standard flow only, with PKCE method
S256.Client scopes
openid,emailandprofileonly (nooffline_access).An audience mapper that adds the client’s own ID to the access token’s audience: oauth2-proxy checks it.
Valid redirect URIs: one exact entry per user,
https://scrap-<fedid>.diamond.ac.uk/oauth2/callback. No wildcards. Start with your own.Access tokens that carry
preferred_username(the fedid): scrap reads it from the access token, not the ID token. Keycloak’s defaultprofileclient scope maps it into the access token; check it has not been changed to the ID token only. The tokens also carryemail, which the proxy checks againstemail_domains; it need not be verified.Confirmation that users cannot change their username in the
dlsrealm: “Edit username” off, and not “Email as username” with emails users can edit. And that the access token’spreferred_usernamecomes from Keycloak’s built-in username mapper, not from an attribute users can edit. scrap trusts it to name the owner.
Keep the client ID and secret for the next step.
Also ask the argus admins to confirm that user namespaces may have ExternalName Services, and
that their ingress-nginx allows the auth-url and auth-signin annotations (its
annotations-risk-level setting can block them).
2. Install the proxy#
You need the namespace (scrap, or another that only the admins use) and the right to make
Secrets and Deployments in it. On a DLS machine:
module load argus
git clone https://github.com/gilesknap/scrap.git
cd scrap
sh deploy/dls/auth-proxy/install.sh
The first run asks for the client ID and secret (the secret is not shown as you type). It makes
the Secret oauth2-proxy-keycloak with the keys client-id, client-secret and a generated
cookie-secret, then installs the chart as the release oauth2-proxy: two pods, a disruption
budget, and no Ingress. The proxy answers inside the cluster at
oauth2-proxy.scrap.svc.cluster.local, where every user’s installer points by default.
Re-run the script after changing values.yaml or the pinned chart version. It keeps the Secret.
A run that makes the Secret (the first, or after you deleted it) also restarts the proxy, since
its pods read the Secret only when they start.
With a namespace other than scrap, users must set SCRAP_AUTH_NAMESPACE to it when they
run their installer.
3. Add users#
After installing, each user asks you to add their login address,
https://scrap-<fedid>.diamond.ac.uk/oauth2/callback. Collect them and send them to the Keycloak
team in batches, to add to the client’s valid redirect URIs. Until a user’s address is added, their
login fails with Keycloak’s “Invalid parameter: redirect_uri”.
Rotate the client secret#
Ask the Keycloak team for a new client secret, then put it in the Secret from a private file and restart the proxy:
tmp=$(mktemp -d)
chmod 700 "$tmp"
printf 'New client secret: '; stty -echo; read -r s; stty echo; echo
printf '{"data":{"client-secret":"%s"}}' "$(printf %s "$s" | base64 | tr -d '\n')" >"$tmp/patch.json"
unset s
kubectl -n scrap patch secret oauth2-proxy-keycloak --type merge --patch-file "$tmp/patch.json"
rm -rf "$tmp"
kubectl -n scrap rollout restart deploy/oauth2-proxy
To sign everyone out, replace cookie-secret the same way, with 32 random bytes in URL-safe
base64 (head -c 32 /dev/urandom | base64 | tr -- '+/' '-_').
Check it#
kubectl -n scrap get pods,svc,pdb
kubectl -n scrap logs deploy/oauth2-proxy
curl -sI https://scrap-<fedid>.diamond.ac.uk/ | head -n 3
The pods are ready, and the curl answers 302 to /oauth2/start on the same host. Opened in a
browser, the address goes to the DLS login and then back to scrap. A 500 from the user’s host
usually means the proxy is down or the user’s Ingress names the wrong Service: check the
authProxy.service in their release (helm -n <fedid> get values scrap).