Documentation
¶
Overview ¶
Package auth handles OAuth2 credentials and their storage. Secrets live in the OS keychain wherever one is available; the encrypted-file fallback exists for headless Linux boxes that have no Secret Service daemon.
Index ¶
- Constants
- Variables
- func Authorize(ctx context.Context, creds ClientCredentials, onURL func(url string)) (*oauth2.Token, error)
- func Config(c ClientCredentials, redirectURL string) *oauth2.Config
- func HasBuiltin() bool
- func OpenBrowser(url string) error
- func TokenSource(ctx context.Context, creds ClientCredentials, tok *oauth2.Token, store *Store) oauth2.TokenSource
- type ClientCredentials
- type Store
- func (s *Store) Backend() string
- func (s *Store) Clear() error
- func (s *Store) LoadAccount() (string, error)
- func (s *Store) LoadClient() (ClientCredentials, error)
- func (s *Store) LoadToken() (*oauth2.Token, error)
- func (s *Store) SaveAccount(addr string) error
- func (s *Store) SaveClient(c ClientCredentials) error
- func (s *Store) SaveToken(t *oauth2.Token) error
Constants ¶
const ( ClientIDEnv = "POSTLINE_CLIENT_ID" ClientSecretEnv = "POSTLINE_CLIENT_SECRET" )
Environment overrides for the OAuth client. These let someone point Postline at their own Google Cloud project without rebuilding it, which matters for anyone who would rather not be counted against this project's user cap.
const AuthTimeout = 5 * time.Minute
AuthTimeout bounds how long the loopback server waits for consent.
const (
// PassphraseEnv supplies the encryption key for the file fallback.
PassphraseEnv = "POSTLINE_PASSPHRASE"
)
Variables ¶
var ErrNoBackend = errors.New( "auth: no OS keychain available and " + PassphraseEnv + " is unset; " + "set " + PassphraseEnv + " to enable encrypted file storage")
ErrNoBackend means neither the OS keychain nor a passphrase is available.
var ErrNotFound = errors.New("auth: not found")
ErrNotFound means the requested secret has never been stored.
var Scopes = []string{
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.send",
}
Scopes are deliberately narrow. gmail.modify covers reading and all label changes including moves to Trash; gmail.send covers delivery. The broader https://mail.google.com/ scope would additionally permit permanent deletion, which Postline never needs.
Functions ¶
func Authorize ¶
func Authorize(ctx context.Context, creds ClientCredentials, onURL func(url string)) (*oauth2.Token, error)
Authorize runs the loopback OAuth2 flow with PKCE.
It binds a listener on a random localhost port, hands the consent URL to onURL (which typically opens a browser), and waits for Google to redirect back with an authorization code. The redirect URI is never public, the verifier never leaves this process, and state is checked on return.
func Config ¶
func Config(c ClientCredentials, redirectURL string) *oauth2.Config
Config builds the OAuth2 configuration for a given loopback redirect.
func HasBuiltin ¶
func HasBuiltin() bool
HasBuiltin reports whether sign-in can proceed without the setup wizard.
func OpenBrowser ¶
OpenBrowser launches the system browser at url. Failure is reported so the caller can fall back to showing the URL for manual copying, which is the normal path over SSH.
func TokenSource ¶
func TokenSource(ctx context.Context, creds ClientCredentials, tok *oauth2.Token, store *Store) oauth2.TokenSource
TokenSource returns a source that transparently refreshes the access token and persists any renewed token back to the store.
Types ¶
type ClientCredentials ¶
type ClientCredentials struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
}
ClientCredentials identifies the OAuth client an authorization runs through. It is either the one compiled into the binary (see Builtin) or one the user created in their own Google Cloud project via the setup wizard.
func Builtin ¶
func Builtin() (ClientCredentials, bool)
Builtin returns the OAuth client this binary was built with. The environment wins over the compiled-in value so an override needs no rebuild.
func (ClientCredentials) Valid ¶
func (c ClientCredentials) Valid() bool
Valid reports whether both halves are present.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists secrets. Callers do not choose the backend; New picks the strongest one available on this machine.
func (*Store) LoadAccount ¶
LoadAccount returns the authenticated address.
func (*Store) LoadClient ¶
func (s *Store) LoadClient() (ClientCredentials, error)
LoadClient retrieves the OAuth client credentials.
func (*Store) SaveAccount ¶
SaveAccount records the authenticated address for display.
func (*Store) SaveClient ¶
func (s *Store) SaveClient(c ClientCredentials) error
SaveClient stores the OAuth client credentials.