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 ¶
- Variables
- type Authorization
- type Config
- type Service
- func (s *Service) ApproveDeviceAuthorization(ctx context.Context, callerUserID, userCode string) error
- func (s *Service) DenyDeviceAuthorization(ctx context.Context, userCode string) error
- func (s *Service) PollDeviceToken(ctx context.Context, rawDeviceCode string) (userID, scope string, err error)
- func (s *Service) StartDeviceAuthorization(ctx context.Context, clientID, scope string) (Authorization, error)
- type Stores
Constants ¶
This section is empty.
Variables ¶
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 ¶
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 ¶
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.