Documentation
¶
Overview ¶
Package devidp implements a development-only OpenID Provider.
The provider authenticates by letting a developer select a user from a TOML roster; it never checks a credential. It implements Authorization Code with mandatory S256 PKCE, RFC 8628 Device Authorization, RS256 ID Tokens published through a JWKS endpoint, discovery metadata, and UserInfo.
The package is host-only tooling. It must never be imported by an application binary: pw build rejects a project that does. Everything it issues lives in memory and dies with the process.
Index ¶
- Constants
- Variables
- type Client
- type ClientSpec
- type Config
- type Credentials
- type Options
- type Provider
- func (p *Provider) Close() error
- func (p *Provider) Endpoint(path string) string
- func (p *Provider) Handler() http.Handler
- func (p *Provider) Issuer() string
- func (p *Provider) LoginUser() string
- func (p *Provider) RegisterClient(spec ClientSpec) (Credentials, error)
- func (p *Provider) RegisterPublicDeviceClient(spec PublicDeviceClientSpec) (Credentials, error)
- func (p *Provider) Reload(config Config) error
- func (p *Provider) SetLoginUser(subject string) error
- func (p *Provider) Users() []User
- type PublicDeviceClientSpec
- type Server
- type User
Constants ¶
const ( DefaultTokenTTL = time.Hour DefaultCodeTTL = time.Minute )
Defaults applied when the roster leaves a lifetime unset.
const ( GrantAuthorizationCode = "authorization_code" GrantDeviceCode = "device_code" )
Variables ¶
var ( // ErrConfig reports an unusable roster file or Config value. ErrConfig = errors.New("devidp: invalid configuration") // ErrUnknownUser reports a subject that is absent from the roster. ErrUnknownUser = errors.New("devidp: unknown user") )
var ErrClosed = errors.New("devidp: provider is closed")
ErrClosed reports use of a provider after Close.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
ID string
Secret string
RedirectURIs []string
ValidScopes []string
GrantTypes []string
// LoopbackRedirects accepts any loopback redirect URI instead of matching
// RedirectURIs exactly. Only a client registered by the running tool may
// set it; see RegisterClient.
LoopbackRedirects bool
}
Client is a relying party allowed to obtain tokens.
type ClientSpec ¶
type ClientSpec struct {
// ID is generated when empty.
ID string
// RedirectURIs are matched exactly unless LoopbackRedirects is set.
RedirectURIs []string
// LoopbackRedirects accepts any loopback callback, which lets a tool
// register before it knows the application port or callback path.
LoopbackRedirects bool
ValidScopes []string
}
ClientSpec describes a client the running tool registers for itself.
type Config ¶
type Config struct {
// Issuer is the absolute base URL. Start fills it from the listener when empty.
Issuer string
ValidScopes []string
TokenTTL time.Duration
CodeTTL time.Duration
// SigningKey signs ID Tokens. New generates an ephemeral key when nil.
SigningKey *rsa.PrivateKey
Clients []Client
Users []User
// contains filtered or unexported fields
}
Config is the resolved provider configuration.
func LoadConfig ¶
LoadConfig reads a roster file. Paths inside it resolve from its directory.
type Credentials ¶
Credentials are the generated secrets for a registered client.
type Options ¶
type Options struct {
Now func() time.Time
Random io.Reader
Logf func(format string, args ...any)
// LoginUser pre-selects a subject so authorization skips the login screen.
LoginUser string
}
Options tunes provider behavior. The zero value is production-shaped for a development tool: real clock, crypto/rand, no logging, manual login.
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider serves the development OpenID Provider endpoints.
func New ¶
New builds a provider from a validated configuration.
The environment lock is here rather than only in Start, because Handler is exported and a provider built here serves the same endpoints whether or not this package opened the listener. Gating only Start left the whole thing reachable to anyone who mounted Handler on their own mux — which is a documented way to use this package — and a plain `go build` of that application published an OpenID Provider that issues a token for any subject in the roster to anyone who asks.
`pw build` refuses an application that imports this package, and that remains the first line of defence. It is a toolchain check, though, and a Dockerfile or CI job that calls `go build` directly never runs it. This one travels with the code.
func (*Provider) RegisterClient ¶
func (p *Provider) RegisterClient(spec ClientSpec) (Credentials, error)
RegisterClient adds an ephemeral client and returns its generated credentials. The secret exists only in memory and is not recoverable after Close.
func (*Provider) RegisterPublicDeviceClient ¶
func (p *Provider) RegisterPublicDeviceClient(spec PublicDeviceClientSpec) (Credentials, error)
RegisterPublicDeviceClient adds an ephemeral RFC 8628 public client. It returns no secret because a value embedded in a constrained device cannot authenticate that device.
func (*Provider) Reload ¶
Reload replaces the roster and scope set in place. Registered clients, the issuer, and the signing key survive, so an edited roster reaches the running application without restarting it or reissuing its injected credentials.
A pre-selected login user that left the roster is cleared rather than kept as a dangling subject.
func (*Provider) SetLoginUser ¶
SetLoginUser pre-selects a subject so the login screen is skipped. An empty subject restores manual selection.
type PublicDeviceClientSpec ¶
type Server ¶
type Server struct {
*Provider
// contains filtered or unexported fields
}
Server is a provider bound to a listener.