Suncoast Systems Keycloak Auth server
manifests/02-keycloak-configmaps.yaml defines a shared public OIDC client for browser apps:
- client id:
shell-spa-public - realm:
external - issuer URL:
https://auth.suncoast.systems/realms/external - discovery URL:
https://auth.suncoast.systems/realms/external/.well-known/openid-configuration
This client is configured for Authorization Code + PKCE (S256) and includes redirect/web-origin patterns for:
http://localhost/*http://127.0.0.1/*https://*.suncoast.systems/*https://*.app.suncoast.systems/*
The dedicated auth gateway source now lives in:
https://github.com/suncoast-systems/keycloak-auth-gateway
This repo keeps the deployment manifest at manifests/07-auth-gateway.yaml.
The Keycloak external realm client auth-gateway-public is defined in manifests/02-keycloak-configmaps.yaml.
Purpose:
- Centralize Keycloak redirect handling to a single callback URL (for example
https://login.suncoast.systems/callback). - Store allowed apps in a database so a GUI can manage them dynamically.
- Expose APIs for CRUD management of allowed apps.
Database tables created automatically at startup:
auth_gateway_allowed_appsauth_gateway_login_stateauth_gateway_exchange_codes
Runtime flow:
- App sends users to
GET /start?app=<slug>&return_to=<url-or-path>. - Gateway redirects to Keycloak and receives callback at
GET /callback. - Gateway redirects back to app with one-time
gateway_codequery param. - App exchanges that code with
POST /v1/auth/exchange.
Management APIs (for GUI):
GET /v1/appsPOST /v1/appsGET /v1/apps/{slug}PUT /v1/apps/{slug}DELETE /v1/apps/{slug}
GitOps seed job for baseline app registrations:
manifests/09-auth-gateway-seed-apps.yaml- Upserts
shellandexample-mfe-previewon each Argo sync so they survive rebuilds.
If ADMIN_API_TOKEN is set, management APIs require:
Authorization: Bearer <ADMIN_API_TOKEN>
Build/publish is managed in the keycloak-auth-gateway repo via GitHub Actions.
Deployment in this repo expects:
ghcr.io/dotcomrow/keycloak-auth-gateway:latest
kubectl apply -f manifests/07-auth-gateway.yaml
kubectl apply -f manifests/09-auth-gateway-seed-apps.yamlOptional secrets:
kubectl -n keycloak create secret generic auth-gateway-admin-api \
--from-literal=token='<strong-admin-token>'
kubectl -n keycloak create secret generic auth-gateway-oidc-client \
--from-literal=client-secret='<client-secret-if-using-confidential-client>'APISIX example route:
manifests/08-auth-gateway-apisix-route.example.yaml
manifests/04-keycloak-configurator.yaml configures IdPs and imports as much profile data as is available from
external identity providers into Keycloak user attributes. Apps then receive these fields via an OIDC client
scope named user-profile (added as a default client scope for the main app clients in both realms).
picture(avatar URL)profile(profile URL)websitelocalenamegiven_namefamily_namepreferred_usernameemail_verified
- Google:
hd,google_sub - GitHub:
company,location,bio,twitter_username,github_id,github_node_id
- Tokens/userinfo include the above attributes as claims when the client has the
user-profilescope attached. - The configurator also ensures the standard
emailscope is present for app clients that expectemail.
This repo includes a Cloudflare Tunnel deployment at manifests/06-cloudflare-tunnel.yaml.
It runs cloudflared in the keycloak namespace and reads TUNNEL_TOKEN from a Kubernetes Secret named cloudflare-tunnel-token.
That Secret is created by External Secrets using Vault.
Vault policy + role for External Secrets (externalsecrets-keycloak) are created by:
manifests/03-vault-bootstrap-jobs.yaml
- Create a named tunnel in Cloudflare Zero Trust (or with the CLI) and copy the tunnel token.
cloudflared tunnel login
cloudflared tunnel create keycloak
cloudflared tunnel route dns keycloak auth.suncoast.systems
cloudflared tunnel token keycloak- Write the token into Vault (KVv2) at
secret/data/keycloak-cloudflare-tunnel-tokenwith keyvalue.
vault kv put secret/keycloak-cloudflare-tunnel-token value='<PASTE_TUNNEL_TOKEN>'- Sync ArgoCD so these manifests are applied:
manifests/03-vault-bootstrap-jobs.yamlmanifests/06-cloudflare-tunnel.yaml
- In Cloudflare Zero Trust, set the tunnel public hostname and origin service:
- Hostname:
auth.suncoast.systems - Service URL:
http://keycloak.keycloak.svc.cluster.local:8080
kubectl -n keycloak get deploy,pod -l app=cloudflared
kubectl -n keycloak logs deploy/cloudflared --tail=100 -f
kubectl -n keycloak get externalsecret cloudflare-tunnel-token