oidc

package
v3.0.0-rc49 Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package oidc logs a user in at an OpenID Connect provider, from a command line program, and refreshes the tokens it obtained.

The login is the authorization code grant with PKCE, its redirect landing on a listener of the loopback address the browser of the user reaches, as RFC 8252 says a native application does. Where no browser runs on the machine of the program, as over ssh, the device authorization grant of RFC 8628 logs the user in from a browser anywhere.

The client is a public one: it holds no secret, its PKCE verifier proving the code is redeemed by who asked for it.

Index

Constants

View Source
const (
	// CallbackPath is the path of the redirect the loopback listener
	// serves. The redirect uri the provider allows is
	// http://127.0.0.1:<any port>/callback.
	CallbackPath = "/callback"

	// LoginTimeout bounds the time the user is given to log in.
	LoginTimeout = 5 * time.Minute
)

Variables

View Source
var ErrNoBrowser = errors.New("no browser to open")

ErrNoBrowser is returned when no browser can be opened on this machine.

View Source
var ErrNoRefreshToken = errors.New("no refresh token")

ErrNoRefreshToken is returned on a refresh asked with no refresh token.

Functions

func CheckEndpoint

func CheckEndpoint(s string) error

CheckEndpoint refuses an endpoint url that is not a web address the user can trust with credentials: an https one, or an http one of this machine.

The authorization endpoint is opened in the browser of the user, by a program that hands it whatever the url names, a local file or the handler of another scheme included.

func HasBrowser

func HasBrowser() bool

HasBrowser says whether a browser can be opened on this machine.

func OpenBrowser

func OpenBrowser(url string) error

OpenBrowser opens the browser of the user on url.

On linux and the other unixes, a browser needs a graphical session: one reached through ssh has none, and its user is asked to log in with a device code instead.

The url is handed to the opener of the system, which opens whatever it names: a web address is checked to be one, so it names no local file nor the handler of another scheme.

Types

type Provider

type Provider struct {
	Issuer                      string   `json:"issuer"`
	AuthorizationEndpoint       string   `json:"authorization_endpoint"`
	TokenEndpoint               string   `json:"token_endpoint"`
	DeviceAuthorizationEndpoint string   `json:"device_authorization_endpoint,omitempty"`
	ScopesSupported             []string `json:"scopes_supported,omitempty"`
}

Provider is what the discovery document of an issuer says of it.

func Discover

func Discover(ctx context.Context, issuer string) (*Provider, error)

Discover reads the discovery document of an issuer.

The issuer is named by the server the program connects to, so it is not followed through redirects, which could lead the request somewhere the server did not name, and the document must name the issuer it was asked for.

func (*Provider) LoginBrowser

func (p *Provider) LoginBrowser(ctx context.Context, clientID string, open func(url string) error) (*Token, error)

LoginBrowser logs the user in with the authorization code grant and PKCE.

It listens on a port of 127.0.0.1, and hands the authorization url to open, which opens the browser of the user on it, or tells them to. The browser lands back on the listener with the code, which is redeemed with the verifier only this call knows.

func (*Provider) LoginDevice

func (p *Provider) LoginDevice(ctx context.Context, clientID string, prompt func(verificationURI, userCode, verificationURIComplete string)) (*Token, error)

LoginDevice logs the user in with the device authorization grant: prompt is told the url to open and the code to enter there, from any browser, and the call returns once the user approved.

func (*Provider) Scopes

func (p *Provider) Scopes() []string

Scopes returns the scopes to ask: the wanted ones the provider supports, all of them when it does not say what it supports.

type Token

type Token struct {
	AccessToken  string
	AccessExpiry time.Time

	// RefreshToken is empty when the provider gave none.
	RefreshToken string

	// RefreshExpiry is zero when the provider does not say when the
	// refresh token expires, as most do not: it is then tried until it
	// is refused.
	RefreshExpiry time.Time
}

Token is what a login or a refresh obtained.

func Refresh

func Refresh(ctx context.Context, tokenEndpoint, clientID, refreshToken string) (*Token, error)

Refresh obtains a new access token from a refresh token, at the token endpoint of the provider. The provider may rotate the refresh token, and the new one is returned then.

Jump to

Keyboard shortcuts

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