Help us shape the future of Go! Take the 2026 Go Developer Survey

auth

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package auth authenticates requests and seeds the built-in principals (decision 0005). Passwords are Argon2id hashes in PHC string form, so the cost parameters travel with each hash and can be raised without breaking the hashes already stored.

Index

Constants

View Source
const (
	// DefaultCacheSize bounds the verified-credentials cache. An entry is a
	// 32-byte key and an expiry, so the bound costs well under a megabyte.
	DefaultCacheSize = 10_000
	// DefaultCacheTTL is how long a verified password skips Argon2. The JFrog
	// CLI sends Basic credentials on every request, so without the cache a
	// large upload would pay 64 MiB and tens of milliseconds per call.
	DefaultCacheTTL = 5 * time.Minute
)

Defaults for the zero Options fields.

View Source
const (
	DefaultLoginAttempts      = 5
	DefaultPasswordMaxAgeDays = 60
)

The policies' defaults when nothing is stored, as Artifactory ships them.

View Source
const (
	AdminUser          = "admin"
	ReadersGroup       = "readers"
	AnythingPermission = "Anything"
	// AnyRemotePermission covers every remote repository and grants no one
	// anything. Artifactory has shipped it without anonymous since 7.84.3, so
	// a request without credentials reaches remote content only through a
	// permission an administrator writes for anonymous.
	AnyRemotePermission = "Any Remote"
)

Names of the built-in principals Artifactory ships (research 05).

View Source
const AnonymousUser = "anonymous"

AnonymousUser is the name of the built-in anonymous user.

Variables

View Source
var (
	// ErrBadCredentials answers credentials that do not verify.
	ErrBadCredentials = apierror.New(http.StatusUnauthorized, "Bad credentials")
	// ErrUnauthenticated answers a request that needs a user and has none.
	ErrUnauthenticated = apierror.New(http.StatusUnauthorized, "Authentication is required")
	// ErrForbidden answers an authenticated user without the right.
	ErrForbidden = apierror.New(http.StatusForbidden, "Forbidden")
)

The messages JFrog clients print. No public source documents Artifactory's exact wording; jfrog-client-go shows errors[].message as it comes.

View Source
var Anonymous = Principal{Name: AnonymousUser, Anonymous: true}

Anonymous is the principal of a request without credentials when anonymous access is on.

View Source
var ErrAccountLocked = apierror.New(http.StatusForbidden,
	"User is Locked.\nContact System Administrator to Unlock The Account.")

ErrAccountLocked answers any password for a locked account. 403, as Artifactory's entry point answers a locked user, with the message of its UserLockedException, newline included (OSS 6.20; decision 0005). It differs from the temporary suspension's 403 (suspension.go), which ends by itself, where this lasts until an administrator unlocks the account.

View Source
var ErrBasicAuthDisabled = apierror.New(http.StatusUnauthorized,
	"Basic authentication with a password is disabled; use an access token")

ErrBasicAuthDisabled answers a user name and password while the platform accepts only tokens (basic_authentication_enabled is false).

View Source
var ErrHashFormat = errors.New("auth: unsupported password hash")

ErrHashFormat reports a stored password hash that is not an Argon2id PHC string this package can verify.

View Source
var ErrInvalidToken = errors.New("invalid token")

ErrInvalidToken reports a token that does not verify: malformed, badly signed, expired, revoked, or of a subject that is not a user. Verifiers wrap it; the request answers ErrBadCredentials.

View Source
var ErrLoginSuspended = errors.New("auth: login temporarily suspended")

ErrLoginSuspended reports a Basic login refused because its user name is suspended. The error also carries the 403 the client gets.

View Source
var ErrPasswordExpired = apierror.New(http.StatusForbidden, "Password has expired")

ErrPasswordExpired answers a correct password the expiration policy, or an administrator, has expired. It is reported only after the password verifies, so it tells nothing to someone without it. 403 rather than 401, with Artifactory's message: its entry point answers a CredentialsExpiredException as it does a locked account (decision 0005).

Functions

func AccessLockSettings

func AccessLockSettings(
	ctx context.Context,
	settings store.SettingsStore,
) (types.AccessLockSettings, error)

AccessLockSettings returns the stored Access user lock settings, or types.DefaultAccessLockSettings.

func BasicAuthEnabled

func BasicAuthEnabled(ctx context.Context, settings store.SettingsStore) (bool, error)

BasicAuthEnabled reports whether user names and passwords are accepted over HTTP Basic. Unset means on, as Artifactory ships.

func CheckPassword

func CheckPassword(stored []byte, password string) (bool, error)

CheckPassword reports whether password matches the stored hash.

func ExpirationPolicy

func ExpirationPolicy(
	ctx context.Context,
	settings store.SettingsStore,
) (types.PasswordExpirationPolicy, error)

ExpirationPolicy returns the stored password expiration policy, or the default.

func HashPassword

func HashPassword(password string) ([]byte, error)

HashPassword returns the Argon2id hash of password in PHC form, with the production parameters.

func HashPasswordWith

func HashPasswordWith(p HashParams, password string) ([]byte, error)

HashPasswordWith is HashPassword with the given parameters.

func LockPolicy

func LockPolicy(ctx context.Context, settings store.SettingsStore) (types.UserLockPolicy, error)

LockPolicy returns the stored user lock policy, or the default.

func LooksLikeToken

func LooksLikeToken(s string) bool

LooksLikeToken reports whether a Basic password is an access or reference token rather than a password: the JFrog CLI sends tokens as the password of a Basic credential.

func PasswordExpired

func PasswordExpired(u types.User, p types.PasswordExpirationPolicy, now time.Time) bool

PasswordExpired reports whether u must set a new password. An administrator's expiry applies whatever the policy; age counts only from a recorded change, so users whose password predates the record (the seeded admin of an older install) are not locked out by enabling it.

func Seed

func Seed(ctx context.Context, st store.Store, adminPassword string, now time.Time) (bool, error)

Seed creates, in one transaction, the admin user with adminPassword, the anonymous user, the readers group, the Anything and Any Remote permissions and the artifactory-build-info repository, then marks the store seeded. It reports whether this call seeded: false when the store already was, including when another instance sharing the database won a race to seed it first.

func SeedHashed

func SeedHashed(
	ctx context.Context,
	st store.Store,
	adminHash []byte,
	now time.Time,
) (bool, error)

SeedHashed is Seed with the admin password already hashed (HashPassword or HashPasswordWith).

func Seeded

func Seeded(ctx context.Context, st store.Store) (bool, error)

Seeded reports whether the built-in principals have been created.

func WithExpiredToken

func WithExpiredToken(ctx context.Context, r Refresher) context.Context

WithExpiredToken returns ctx carrying the expired access token a refresh request presented as its credential (Authenticator.ExpiredToken).

func WithPrincipal

func WithPrincipal(ctx context.Context, p Principal) context.Context

WithPrincipal returns ctx carrying p.

Types

type Authenticator

type Authenticator struct {
	// contains filtered or unexported fields
}

Authenticator verifies credentials against the user store.

func NewAuthenticator

func NewAuthenticator(
	users store.UserStore,
	settings store.SettingsStore,
	o Options,
) (*Authenticator, error)

NewAuthenticator returns an Authenticator over users and settings.

func (*Authenticator) AnonymousAllowed

func (a *Authenticator) AnonymousAllowed(ctx context.Context) (bool, error)

AnonymousAllowed reports whether requests without credentials act as the anonymous user. The setting is a JSON boolean; unset means off, as in Artifactory.

func (*Authenticator) Basic

func (a *Authenticator) Basic(ctx context.Context, name, password string) (Principal, error)

Basic verifies a user name and password. Wrong credentials, an unknown or disabled user, and a user without an internal password all answer ErrBadCredentials alike; while basic authentication is switched off, every password answers ErrBasicAuthDisabled. A locked account answers ErrAccountLocked whatever the password. A correct but expired password answers ErrPasswordExpired with the principal, marked PasswordExpired. While the name is temporarily suspended after failed logins, every password answers ErrLoginSuspended (suspension.go).

func (*Authenticator) ExpiredToken

func (a *Authenticator) ExpiredToken(ctx context.Context, raw string) (Refresher, bool)

ExpiredToken verifies raw as an access token whatever its expiry, and whose user is still enabled. Only the refresh grant asks: the JFrog CLI refreshes with the access token it is replacing, by then often expired, as the Bearer credential (Access) or the access_token form field (legacy).

func (*Authenticator) ForgetPolicies

func (a *Authenticator) ForgetPolicies()

ForgetPolicies drops the cached policies, so a change made through this instance applies to its next login.

func (*Authenticator) Token

func (a *Authenticator) Token(ctx context.Context, raw, user string) (Principal, error)

Token verifies a token presented as Bearer, as X-JFrog-Art-Api, or as the password of a Basic credential whose user name is user ("" for the first two). A Basic user name must name the token's subject (decision 0005). The subject must still be an enabled user: disabling a user disables their tokens.

type ExpiredVerifier

type ExpiredVerifier interface {
	VerifyExpired(ctx context.Context, raw string) (types.Token, error)
}

ExpiredVerifier is a TokenVerifier that also verifies an access token whose only fault is its expiry. internal/auth/token implements it.

type HashParams

type HashParams struct {
	MemoryKiB uint32
	Time      uint32
	Threads   uint8
}

HashParams are Argon2id's cost parameters. The zero value means the production parameters; the only other use is tests, which hash with tiny costs to stay fast. Nothing in configuration or on the command line can set them: verification reads the cost from each stored hash, so a cheap hash only ever comes from code that asked for one.

type Options

type Options struct {
	CacheSize int
	CacheTTL  time.Duration
	// Concurrency bounds the password hashes computed at once; zero means
	// GOMAXPROCS. Each costs the hash's memory parameter, so without a bound
	// a flood of wrong passwords could exhaust memory.
	Concurrency int
	// Now supplies the time; nil means time.Now.
	Now func() time.Time
	// Hash is the cost of the dummy hash checked for unknown users; the
	// zero value means the production parameters. Tests set tiny costs.
	Hash HashParams
	// Tokens verifies access and reference tokens; nil refuses every token.
	Tokens TokenVerifier
	// Groups names the groups new users join automatically, which the
	// transient user of a transient token joins (types.IdentityTransient);
	// nil means none.
	Groups store.GroupStore
}

Options configures NewAuthenticator.

type Principal

type Principal struct {
	Name      string
	Admin     bool
	Anonymous bool
	Groups    []string
	// Scope is the scope of the access token the request presented; empty
	// for a password or anonymous request, which act with the user's full
	// permissions. Scopes only narrow (decision 0005); the permission
	// evaluator applies them.
	Scope types.Scope
	// TokenID is the id of the access or reference token the request
	// presented; empty for a password or anonymous request. The token API's
	// "me" resolves to it, and encryptedPassword refuses token callers.
	TokenID string
	// TokenExpires is when that token expires; zero for a password, an
	// anonymous request or a token that never expires. A registry token
	// obtained with a token lives no longer (decision 0005).
	TokenExpires time.Time
	// Registry is what a registry token grants, nil for any other
	// credential. Such a principal reaches the registry's routes alone.
	Registry *types.RegistryAccess
	// Identity is how the token's subject resolved to a user: transient or
	// synthetic for a token from an OIDC exchange, transient for one an
	// administrator minted for a name that is no stored user; a registry
	// token obtained with it keeps it (decision 0005).
	Identity types.TokenIdentity
	// TokenParent is, for a registry token, the stored token it descends
	// from: a registry token it obtains descends from the same one.
	TokenParent string
	// PasswordExpired marks a principal whose correct password has expired.
	// The middleware lets it through only to change its own password.
	PasswordExpired bool
	// Password marks a principal that a user name and password
	// authenticated, which the Access token API refuses while
	// token.allow_basic_auth is off (#385). An empty TokenID cannot stand
	// for it: anonymous and hand-built principals have none either.
	Password bool
	// contains filtered or unexported fields
}

Principal is who a request acts as.

func Authorize

func Authorize(ctx context.Context, src authz.Sources, p Principal) (Principal, error)

Authorize evaluates p's permissions once for the request (decision 0006) and returns p with Admin and Groups set to what the evaluator decides: a token scope can remove the admin flag and narrow the groups, and an admin-privilege group makes a member an administrator. Handlers then ask Access() every permission question.

func FromContext

func FromContext(ctx context.Context) (Principal, bool)

FromContext returns the request's principal; ok is false when the request is unauthenticated (no credentials and anonymous access off).

func RequireAdmin

func RequireAdmin(ctx context.Context) (Principal, error)

RequireAdmin returns ErrUnauthenticated without a user and ErrForbidden for a user who is not an administrator, the split Artifactory makes between 401 and 403.

func RequireAuthenticated

func RequireAuthenticated(ctx context.Context) (Principal, error)

RequireAuthenticated returns ErrUnauthenticated unless the request carries a user other than anonymous.

func (Principal) Access

func (p Principal) Access() *authz.Decider

Access returns the request's permission evaluator, or nil before Authorize has run.

func (Principal) Subject

func (p Principal) Subject() authz.Subject

Subject is p as the permission evaluator starts from it: the user's own admin flag and groups, and the token's scope when a token authenticated the request.

type Refresher

type Refresher struct {
	User    string
	TokenID string
}

Refresher is the access token a refresh presents for the token it replaces, and that token's user.

func ExpiredTokenFrom

func ExpiredTokenFrom(ctx context.Context) (Refresher, bool)

ExpiredTokenFrom returns what WithExpiredToken stored.

type TokenVerifier

type TokenVerifier interface {
	Verify(ctx context.Context, raw string) (types.Token, error)
}

TokenVerifier resolves an access token (a JWT) or a reference token to its stored record. internal/auth/token implements it.

Directories

Path Synopsis
Package idtoken verifies ID tokens that an external OpenID Connect provider, typically a CI system, signed: the subject tokens of the Access OIDC token exchange (POST /access/api/v1/oidc/token, research 21).
Package idtoken verifies ID tokens that an external OpenID Connect provider, typically a CI system, signed: the subject tokens of the Access OIDC token exchange (POST /access/api/v1/oidc/token, research 21).
idtokentest
Package idtokentest is a fake OpenID Connect provider for tests: it serves a discovery document and a JWKS, as GitHub Actions, GitLab and other CI systems do, and mints ID tokens signed with its current key.
Package idtokentest is a fake OpenID Connect provider for tests: it serves a discovery document and a JWKS, as GitHub Actions, GitLab and other CI systems do, and mints ID tokens signed with its current key.
Package token issues and verifies Access tokens (decision 0005): RS256 JWTs signed with a per-instance key, reference tokens and refresh tokens.
Package token issues and verifies Access tokens (decision 0005): RS256 JWTs signed with a per-instance key, reference tokens and refresh tokens.

Jump to

Keyboard shortcuts

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