device

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package device implements RFC 8628's OAuth 2.0 Device Authorization Grant: the "visit this URL and enter this code" flow used by headless or browser-less CLIs (no local browser or listening port assumed — see https://datatracker.ietf.org/doc/html/rfc8628).

This package deliberately does not mint a credential itself. A successful PollDeviceToken tells the caller which user approved the request; the host application decides what to hand the CLI in response — a authit/user session, a authit/pat token, or its own credential shape. This keeps device flow reusable regardless of what kind of token a given host application issues.

Rate-limiting guesses against the (short, low-entropy-by-design) user_code at the approval endpoint is the host application's responsibility (RFC 8628 §5.2) — typically ordinary HTTP-layer rate-limiting middleware in front of ApproveDeviceAuthorization/ DenyDeviceAuthorization.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAuthorizationPending = errors.New("authit/device: authorization pending")
	ErrSlowDown             = errors.New("authit/device: polling too frequently")
	ErrAccessDenied         = errors.New("authit/device: access denied")
	ErrExpiredToken         = errors.New("authit/device: device code expired or invalid")
	ErrInvalidUserCode      = errors.New("authit/device: invalid, already-used, or expired user code")
)

These map directly to RFC 8628 §3.5's token-endpoint error codes; a host application's HTTP layer translates them to the matching "error" field (authorization_pending, slow_down, access_denied, expired_token).

Functions

This section is empty.

Types

type Authorization

type Authorization struct {
	DeviceCode string
	UserCode   string
	ExpiresIn  time.Duration
	Interval   time.Duration
}

Authorization is what StartDeviceAuthorization hands back to the CLI. Building the full verification_uri / verification_uri_complete is left to the host application, which is the only party that knows its own domain and routing.

type Config

type Config struct {
	// DeviceCodeTTL is how long a device authorization request stays valid
	// before the user must restart it. Defaults to 15 minutes (matches
	// GitHub's device flow).
	DeviceCodeTTL time.Duration
	// PollInterval is the minimum gap the CLI is told to leave between
	// polls. Defaults to 5 seconds.
	PollInterval time.Duration
	// SlowDownIncrement is added to a device authorization's effective
	// interval, permanently, the first time the CLI is caught polling
	// faster than instructed. Defaults to 5 seconds, per RFC 8628 §3.5.
	SlowDownIncrement time.Duration
	// AuditLogger receives security-relevant events (approval, denial).
	// Nil means events are not recorded — see package audit.
	AuditLogger audit.Logger
}

Config tunes the device package's flows.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service implements the device-authorization-grant flow.

func NewService

func NewService(stores Stores, cfg Config) (*Service, error)

NewService constructs a Service. Config.AuditLogger may be nil, in which case audit.NoopLogger is used.

func (*Service) ApproveDeviceAuthorization

func (s *Service) ApproveDeviceAuthorization(ctx context.Context, callerUserID, userCode string) error

ApproveDeviceAuthorization marks the device authorization identified by userCode as approved by callerUserID. Call this from an already-authenticated web session after the user types/confirms the code — device does not itself authenticate callerUserID.

func (*Service) DenyDeviceAuthorization

func (s *Service) DenyDeviceAuthorization(ctx context.Context, userCode string) error

DenyDeviceAuthorization marks the device authorization identified by userCode as denied, so the CLI's poll terminates with ErrAccessDenied.

func (*Service) PollDeviceToken

func (s *Service) PollDeviceToken(ctx context.Context, rawDeviceCode string) (userID, scope string, err error)

PollDeviceToken is what the CLI calls repeatedly with the device_code it received from StartDeviceAuthorization. On success it returns the ID of the user who approved the request (and the scope that was requested) — it is then the host application's job to mint whatever credential it wants to hand the CLI. Once a device authorization resolves to a terminal outcome (approved or denied), the record is deleted so it cannot be polled again.

func (*Service) StartDeviceAuthorization

func (s *Service) StartDeviceAuthorization(ctx context.Context, clientID, scope string) (Authorization, error)

StartDeviceAuthorization begins a new device-authorization-grant request for the given clientID/scope (both host-application-defined and optional — pass "" for either if the host doesn't distinguish clients or scopes).

type Stores

type Stores struct {
	Authorizations store.DeviceAuthorizationStore
}

Stores groups the persistence ports the device package needs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL