Documentation
¶
Overview ¶
Device flow (RFC 8628) login against Keycloak via the DBGorilla backend.
Flow:
Discover -- GET {api}/api/v0_1/auth/keycloak/device-config (public). Returns the Keycloak device authorization endpoint, token endpoint, client_id ("dbgorilla-cli"), and verification_uri.
Request device code -- POST to device_authorization_endpoint with client_id. Returns {device_code, user_code, verification_uri, verification_uri_complete, expires_in, interval}.
Display user_code + verification_uri to the user; try to open the browser at verification_uri_complete (which has the code already filled in) so the user just clicks "approve".
Poll token_endpoint until 200 (success), or an error other than authorization_pending / slow_down terminates the flow.
On a headless machine the browser-open is a no-op; the user copies the printed code+URL elsewhere. Same code path either way.
Security notes:
- The discovered endpoints (device_authorization, token) are validated to use https unless --insecure is set. This prevents a malicious backend (or one with a typoed config) from silently downgrading the polling step. We do NOT enforce host-equality with apiURL because Keycloak is often deployed on a separate subdomain -- but we warn loudly when the host differs, so an attacker can't quietly redirect polling to a domain they control.
- When !insecure, the HTTP client refuses to follow redirects to a non-https URL, preventing TLS downgrade via redirect.
Internal username/password login against POST /api/v0_1/auth/token.
Used when the backend has AUTH_PROVIDER=internal (no Keycloak), or when the user explicitly forces password mode via --mode password. The CLI never accepts the password as a flag -- it's read from stdin without echo so it doesn't land in shell history or process listings.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClearTokens ¶
func ClearTokens() error
ClearTokens removes tokens from keychain and fallback file.
func IsDeviceFlowAvailable ¶
IsDeviceFlowAvailable returns true if the backend at apiURL exposes the Keycloak device-config endpoint. Used by `dbg login` to auto-pick mode. Network errors return false (fall back to password mode).
func StoreTokens ¶
StoreTokens persists tokens to the OS keychain. Falls back to a local file with 0600 permissions if the keychain is unavailable, and prints a warning.
Types ¶
type DeviceConfig ¶
type DeviceConfig struct {
DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
ClientID string `json:"client_id"`
VerificationURI string `json:"verification_uri"`
}
DeviceConfig matches GET /api/v0_1/auth/keycloak/device-config.
func DiscoverDeviceConfig ¶
DiscoverDeviceConfig fetches the device-config from the backend and validates the returned endpoints. Returns an error if any required field is missing or (when !insecure) any endpoint URL uses a non-https scheme.
type PasswordCredentials ¶
PasswordCredentials are the inputs collected from the user.
func PromptCredentials ¶
func PromptCredentials(prefill PasswordCredentials) (PasswordCredentials, error)
PromptCredentials reads any missing fields from stdin. Tenant/account are echoed; password is hidden when stdin is a tty.
type Tokens ¶
type Tokens struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresAt time.Time `json:"expires_at"`
// TokenEndpoint is the Keycloak token endpoint for SSO-flow refresh.
TokenEndpoint string `json:"token_endpoint,omitempty"`
// ClientID is the OAuth client used for the SSO-flow refresh grant.
ClientID string `json:"client_id,omitempty"`
}
Tokens holds the OAuth token pair.
TokenEndpoint and ClientID are set only for device/SSO-flow sessions, whose tokens are issued directly by Keycloak. Their presence tells the refresh logic to renew at the Keycloak token endpoint (an OAuth refresh_token grant) rather than the DBGorilla backend's /token/refresh endpoint, which only validates backend-issued (password-flow) tokens. When they are empty (password flow) the backend refresh path is used.
func LoadTokens ¶
LoadTokens reads tokens from keychain or fallback file.
func LoginDevice ¶
LoginDevice runs the full device flow against the given backend URL. Stores tokens in the keychain on success and returns them. Honors ctx cancellation between polls and during HTTP calls.
func LoginPassword ¶
func LoginPassword(apiURL string, insecure bool, creds PasswordCredentials) (*Tokens, error)
LoginPassword exchanges credentials for tokens and stores them. The backend distinguishes USERNAME from EMAIL login via account_type. We default to USERNAME because that is what every documented dev account (sysop, debug-user, integration-test users) uses; EMAIL is a less common path the user can request explicitly later if needed.