No description
  • Go 92.3%
  • Just 7.7%
Find a file
2026-06-28 13:28:46 -07:00
internal init 2026-06-28 13:28:46 -07:00
.gitignore init 2026-06-28 13:28:46 -07:00
go.mod init 2026-06-28 13:28:46 -07:00
justfile init 2026-06-28 13:28:46 -07:00
main.go init 2026-06-28 13:28:46 -07:00
README.md init 2026-06-28 13:28:46 -07:00

kubectl-oidc-device

A kubectl exec plugin that authenticates against an OIDC provider using the RFC 8628 device authorization grant. It exists for machines that have no local browser — SSH sessions, provisioned VMs, containers — where the usual kubelogin authorization-code flow (which redirects to http://localhost:PORT) can't work.

The plugin prints a URL and a short code to stderr; you open the URL on any device with a browser, log in, approve, and the plugin's polling receives the token set and emits a kubectl ExecCredential on stdout.

kubectl oidc-device get-token --oidc-issuer-url=... --oidc-client-id=...

Install

go install git.navicore.tech/navicore/kubectl-oidc-device@latest

Ensure $GOPATH/bin (or $GOBIN) is on your $PATH. kubectl auto-discovers any binary named kubectl-* as a plugin, so kubectl-oidc-device becomes kubectl oidc-device.

kubeconfig

Use it exactly like kubelogin, but swap the exec.command and drop the redirect_uri (device-flow clients have no redirect target):

apiVersion: v1
kind: Config
clusters:
  - cluster:
      server: https://k8s-api.example.com
      insecure-skip-tls-verify: true   # or a CA bundle
    name: homelab
contexts:
  - context:
      cluster: homelab
      user: oidc-device
    name: homelab
current-context: homelab
users:
  - name: oidc-device
    user:
      exec:
        apiVersion: client.authentication.k8s.io/v1beta1
        command: kubectl-oidc-device
        args:
          - get-token
          - --oidc-issuer-url=https://auth.example.com/realms/homelab
          - --oidc-client-id=kubectl-oidc-device
          - --oidc-extra-scope=groups
        interactiveMode: IfAvailable

Token cache

id_token + refresh_token are cached at ~/.kube/cache/oidc-device/<sha256(issuer|client)> (mode 0600, dir 0700). On each invocation the plugin:

  1. returns the cached id_token if it has >30s of life left
  2. else tries the refresh_token grant silently (no browser)
  3. else runs the interactive device flow

This mirrors kubelogin's caching behavior, so refresh + re-login cadence feels the same on both flows.

Server requirements

The OIDC provider must advertise a device_authorization_endpoint and support the urn:ietf:params:oauth:grant-type:device_code grant (RFC 8628), with PKCE S256. The client must be registered for device flow. This plugin contains nothing anz-specific; any compliant provider works.

The k8s API server must list the device-flow client_id in its --oidc-client-id (or accept it via --oidc-required-claim/audiences) so tokens minted by this plugin validate the same way kubelogin tokens do.

Flags

Flag Required Description
--oidc-issuer-url yes OIDC issuer URL (e.g. https://auth.example.com/realms/homelab)
--oidc-client-id yes OAuth client_id registered for device flow
--oidc-extra-scope no extra scope to request (repeatable; openid is always included)
--oidc-client-secret no client_secret for confidential clients (public clients omit)

Build from source

just build    # → ./bin/kubectl-oidc-device
just test     # unit tests
just ci       # fmt-check + vet + test + build
just install  # go install into $GOPATH/bin