No description
  • Go 38.8%
  • JavaScript 30.1%
  • CSS 16.9%
  • HTML 5.3%
  • Smarty 4.2%
  • Other 4.7%
Find a file
2026-03-14 11:50:27 -04:00
charts/token-getter fix: only render secret data if provided 2026-03-14 11:50:27 -04:00
static add: favicon 2026-03-12 12:00:55 -04:00
tmp initial commit 2026-03-09 23:00:58 -04:00
.gitignore fix: gitignore binary, not charts directory 2026-03-09 23:15:58 -04:00
.prettierrc initial commit 2026-03-09 23:00:58 -04:00
AGENTS.md fix: implement several more checks/fixes in the backend, consolidate the frontend code a bit, and expose a few more environment variables for changing middleware behavior 2026-03-12 11:58:51 -04:00
Dockerfile initial commit 2026-03-09 23:00:58 -04:00
Dockerfile.dev fix: implement a bunch of improvements all over 2026-03-11 19:14:21 -04:00
go.mod initial commit 2026-03-09 23:00:58 -04:00
LICENSE initial commit 2026-03-09 23:00:58 -04:00
main.go fix: implement several more checks/fixes in the backend, consolidate the frontend code a bit, and expose a few more environment variables for changing middleware behavior 2026-03-12 11:58:51 -04:00
Makefile initial commit 2026-03-09 23:00:58 -04:00
README.md fix: implement several more checks/fixes in the backend, consolidate the frontend code a bit, and expose a few more environment variables for changing middleware behavior 2026-03-12 11:58:51 -04:00

Token Getter

A minimal web application that allows users to obtain OIDC access tokens via direct access grant (password credentials flow) from Keycloak, with optional OTP support for 2FA.

This enables us to use more complex authentication flows (requiring Keycloak role membership for flow completion) alongside transparent authn/authz policies (Envoy Gateway SecurityPolicies) to lock API access behind verifiable JWTs that we can more easily access directly for integrating third party applications with those APIs.

You should probably not use this paradigm if you're not acutely aware of:

  • The problems with direct grants
  • The cases where direct grants of OIDC tokens are superior to alternatives (such as fixed tokens)
  • How to configure custom flows for Keycloak and restrict clients to those flows

Disclosure

I built this program over the course of a few days while experimenting with OpenCode and a locally hosted Large Language Model, Qwen 3.5 35B A3B, running in llama.cpp on a Framework Desktop. I was trying to somewhat push the limits of local AI on this (very) powerful chip, with a state-of-the-art Mixture-of-Experts model that best takes advantage of its memory density:compute performance tradeoffs. Absolutely all generated code was reviewed by me personally, and a bunch of it was manually modified (much to OpenCode's dismay) when it wasn't able to produce output that I held up to par. I can't totally speak to the license of the code it generated, but I would feel comfortable arguing that I own enough of it for it to at least be transformative.

If you want to see the plan I started with (mostly true, this got updated a little bit as we went) before arguing with the clanker for a few days, AGENTS.md is available.

Part of that is to say that if you take issue with something here, take issue with me. The other part is to say the exact opposite. Which one I prefer depends on how much you pay your lawyers vs how much I pay mine. I think it's pretty good code at this point - I'm running it, after all.

Features

  • Simple form-based interface for token retrieval
  • One-click copy to clipboard with toast notification
  • Expandable full response/error details

Building and Running Locally

Prerequisites

  • Go 1.21 or later
  • Podman or Docker (for containerized deployments)
  • Environment variables to connect to your OIDC endpoint

Build and Run

go build -o token-getter .
. .env # or export them all yourself like a caveman
./token-getter

Environment Variables

Variable Description Default
PORT Server port 8080
OIDC_ENDPOINT Keycloak OIDC endpoint Required
OIDC_REALM Keycloak realm name sso
OIDC_CLIENT_ID Client ID Required
OIDC_CLIENT_SECRET Client secret Required
OIDC_SCOPE OIDC scope openid profile email
OIDC_TIMEOUT Timeout for OIDC requests 30s
CORS_ALLOWED_ORIGINS Comma-separated allowed CORS origins Same-origin only
TRUST_PROXY_HEADERS Trust X-Forwarded-For headers false
RATE_LIMIT_REQUESTS Max requests per window per IP 10
RATE_LIMIT_WINDOW Rate limiting window duration 1m
READ_TIMEOUT HTTP server read timeout 15s
WRITE_TIMEOUT HTTP server write timeout 15s
IDLE_TIMEOUT HTTP server idle timeout 60s
MAX_HEADER_BYTES Maximum HTTP header bytes 1048576 (1MB)

Most of the Makefile targets respect an .env file:

OIDC_ENDPOINT=https://keycloak.example.com
OIDC_REALM=your-realm
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret

Container Development

# Build and run dev container with hot reload
make dev

Production Container

# Build with git tag as container image tag, and also tag latest
make build

# Push to registry
make push

If you just want to quickly run the built image from my registry, there's a target for that.

# Run locally
make run

The web UI and API should be listening on localhost:8080 after that.

Kubernetes Deployment

Helm Chart

The project includes a Helm chart in charts/token-getter/.

# Install or upgrade
helm upgrade --install token-getter ./charts/token-getter
    --set route.enabled=true \
    --set route.hostname=token.example.com \
    --set-json route.parentRefs='[
        {
            "group": "gateway.networking.k8s.io",
            "kind": "Gateway",
            "name": "my-gateway",
            "namespace": "my-gateway-namespace"
        }
    ]'

See values.yaml for more options and details.

Keycloak Configuration

Enable Direct Access Grants

  1. Navigate to your Keycloak realm
  2. Go to Clients and select your client
  3. Enable "Direct access grants" under "Access settings"
  4. Save changes

For more information, see the Keycloak documentation.

While this grant type is not recommended to be used, we are using it here for cases where we need an access token to get past JWT inspection for authn/authz protection on a particular endpoint, without requiring that that endpoint be aware of the nature of that authn/authz protection.

Token Request Example

If you're not sure if your Keycloak server is configured correctly to provide access tokens for direct grants, the following command will provide JSON output that's suitable to provide an access token directly from Keycloak that you can test with a curl command to your API endpoint directly as a Bearer Token:

curl -X POST "https://keycloak.example.com/realms/your-realm/protocol/openid-connect/token" \
  -d "grant_type=password" \
  -d "client_id=your-client-id" \
  -d "client_secret=your-client-secret" \
  -d "username=user@example.com" \
  -d "password=mypassword" \
  -d "otp=123456"  # Optional for 2FA