oauth2

package
v1.20.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package oauth2 ships Harbor's V1 default OAuth provider driver (closes issue #116 and the deferred construction gap).

The driver implements the §4.4 seam pattern for OAuth flow strategies: it self-registers under the canonical driver name `"oauth2"` via init() so operators declaring `tools.oauth_providers[].driver: oauth2` in `harbor.yaml` get a working provider at boot with zero Go wiring code.

The OAuth2 + PKCE Authorization Code flow

The driver delegates to `internal/tools/auth.Provider` (the concrete `OAuthProvider`), which already implements the full Authorization Code + PKCE + RFC 7591 dynamic registration + metadata discovery flow. This package's responsibility is the operator-config → `Provider` boundary: read env-var-indirected credentials, validate fail-loud, build the underlying `auth.OAuthConfig`, and call `auth.NewProvider`.

Source ID binding (V1 simplification)

The `*Provider.Token(ctx, source)` API keys by `tools.ToolSourceID` — each provider holds one `OAuthConfig` per source. For V1, the `oauth2` driver constructs ONE `*Provider` per `tools.oauth_providers[]` entry with a single `OAuthConfig` whose `Source = tools.ToolSourceID(cfg.Name)`. The catalog wrapper (`internal/tools/catalog.WrapWithOAuth`) passes the underlying tool's source ID, which may not match the provider name; the driver transparently substitutes by wrapping the `*Provider` in a small adapter that retargets every `Token` call onto the operator- configured source.

Future per-vendor drivers (Google Workspace, GitHub, Slack, ...) may implement more sophisticated multi-source mappings; the V1 default keeps the operator's mental model simple: one provider declaration → one OAuth attachment.

Fail-loud at construction

CLAUDE.md §13 amendment — operator-facing seams demand explicit configuration. The driver fails closed on:

  • A nil `cfg.CredentialSource` (BuildProviders always threads one).
  • A resolved credential with an empty `client_id` (the env var named by `ClientIDEnv` was unset or empty).
  • A resolved credential with an empty `client_secret`.
  • Missing `cfg.TokenURL` AND `cfg.AuthURL` (no server endpoints configured; OAuth2/PKCE requires both).
  • Missing `cfg.RedirectURL`.
  • Missing deps (Store / Bus / Redactor / Coordinator).

The client credential resolves through the §4.4 credential-source seam. The generic `oauth2` driver supports the `env` source only — the interactive flow bakes the credential at construction, so it resolves EAGERLY here; the config validator restricts `remote` to the non-interactive `tokenexchange` driver.

Every failure mode surfaces a wrapped error naming the offending config field; the dev stack propagates the error up so the boot banner names the field the operator needs to set.

Index

Constants

View Source
const DriverName = "oauth2"

DriverName is the canonical name the driver registers under. The `internal/config` validator's `allowedOAuthDrivers` allowlist mirrors this constant.

Variables

View Source
var (
	// ErrMissingClientID — the credential resolved through the source
	// seam carried an empty client_id (the env var named by
	// client_id_env was unset or empty). Fail-loud per §13 amendment.
	ErrMissingClientID = errors.New("auth/oauth2: resolved client_id is empty (the env var named by client_id_env was unset or empty)")
	// ErrMissingClientSecret — the resolved credential carried an empty
	// client_secret. Same fail-loud rationale as `ErrMissingClientID`.
	ErrMissingClientSecret = errors.New("auth/oauth2: resolved client_secret is empty (the env var named by client_secret_env was unset or empty)")
	// ErrMissingEndpoints — both `cfg.AuthURL` and `cfg.TokenURL` are
	// empty. OAuth2/PKCE requires the authorization-server endpoints;
	// driver-specific drivers may infer them, but the generic
	// `oauth2` driver does NOT do discovery — the operator MUST
	// declare both.
	ErrMissingEndpoints = errors.New("auth/oauth2: both auth_url and token_url must be set (the oauth2 driver does not auto-discover endpoints — declare them in tools.oauth_providers[])")
	// ErrMissingRedirectURL — `cfg.RedirectURL` was empty. The
	// redirect_uri names the callback endpoint; `harbor dev` mounts
	// Harbor's production handler (`auth.CallbackHandler`)
	// at `GET /v1/tools/oauth/callback`, so the dev
	// value is `http://<bind>/v1/tools/oauth/callback`. Headless
	// embedders mount the same handler on their own mux (see
	// docs/recipes/steer-and-resume-a-run.md).
	ErrMissingRedirectURL = errors.New("auth/oauth2: redirect_url must not be empty (point it at the mounted auth.CallbackHandler — harbor dev serves GET /v1/tools/oauth/callback)")
)

Sentinel errors specific to the oauth2 driver. Driver-internal / upstream-server failures continue to use the parent package's sentinels (`auth.ErrAuthRequired`, `auth.ErrExchangeFailed`, etc.).

View Source
var ErrMissingCredentialSource = errors.New("auth/oauth2: CredentialSource is nil (BuildProviders threads the source; direct callers pass credsource.Static)")

ErrMissingCredentialSource — cfg.CredentialSource was nil at construction. BuildProviders always threads one; a nil source is a direct-construction bug.

Functions

func New

New constructs the `oauth2` driver's OAuthProvider for one operator-config entry.

The function is registered as the `oauth2` driver's `auth.Factory`. Per §4.4 the dev stack never calls this directly — `auth.Resolve` dispatches by driver name.

Types

This section is empty.

Jump to

Keyboard shortcuts

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