auth

package
v0.2.8 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2026 License: MIT Imports: 29 Imported by: 4

Documentation

Index

Constants

View Source
const AuthorizationHeader = "Authorization"

Variables

View Source
var (
	Base      = Select("base")
	Propagate = Select("propagate")
)

Commonly used selectors for choosing authenticators in typical scenarios.

Functions

func GetDefaultCacheFileName

func GetDefaultCacheFileName() (string, error)

func NameOfTokener

func NameOfTokener(tokener BearerTokener) (string, bool)

func RunAsyncTokener

func RunAsyncTokener(ctx context.Context, tokener BearerTokener) (error, bool)

func StreamClientInterceptor

func StreamClientInterceptor(
	logger *slog.Logger,
	auths map[Selector]Authenticator,
	explicit bool,
) grpc.StreamClientInterceptor

func UnaryClientInterceptor

func UnaryClientInterceptor(
	logger *slog.Logger,
	auths map[Selector]Authenticator,
	explicit bool,
) grpc.UnaryClientInterceptor

Types

type AsynchronouslyRenewableFileCachedTokener

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

func NewAsynchronouslyRenewableFileCachedTokener

func NewAsynchronouslyRenewableFileCachedTokener(
	cacheFile string,
	tokener NamedTokener,
	safetyMargin time.Duration,
	logger *slog.Logger,
) *AsynchronouslyRenewableFileCachedTokener

func (*AsynchronouslyRenewableFileCachedTokener) BearerToken

func (*AsynchronouslyRenewableFileCachedTokener) HandleError

func (f *AsynchronouslyRenewableFileCachedTokener) HandleError(
	ctx context.Context, token BearerToken, checkErr error,
) error

func (*AsynchronouslyRenewableFileCachedTokener) Name

func (*AsynchronouslyRenewableFileCachedTokener) Run

func (*AsynchronouslyRenewableFileCachedTokener) SetCacheThrottle

func (f *AsynchronouslyRenewableFileCachedTokener) SetCacheThrottle(throttle time.Duration)

func (*AsynchronouslyRenewableFileCachedTokener) Unwrap

type Authenticator

type Authenticator interface {
	// Auth enriches the provided [context.Context] with necessary gRPC metadata for authentication.
	Auth(context.Context) (context.Context, error)

	// HandleError processes errors from gRPC calls that fail with the Unauthenticated status code.
	// It receives the [context.Context] returned by [Authenticator.Auth] and the error from the gRPC call.
	// If HandleError returns nil, the system will attempt to re-authenticate and retry the call.
	// If the call should not be retried, HandleError should return the original error.
	HandleError(context.Context, error) error
}

Authenticator is an interface for adding authentication data to the context.Context in gRPC interceptors. There are two main implementations: AuthenticatorFromBearerTokener and PropagateAuthorizationHeader, but custom implementations can also be provided.

type AuthenticatorFromBearerTokener

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

AuthenticatorFromBearerTokener is an Authenticator that uses a BearerTokener to populate the AuthorizationHeader with a "Bearer " prefix.

func NewAuthenticatorFromBearerTokener

func NewAuthenticatorFromBearerTokener(tokener BearerTokener) AuthenticatorFromBearerTokener

NewAuthenticatorFromBearerTokener returns an Authenticator that uses a BearerTokener to populate the AuthorizationHeader with a "Bearer " prefix.

func (AuthenticatorFromBearerTokener) Auth

func (AuthenticatorFromBearerTokener) HandleError

func (a AuthenticatorFromBearerTokener) HandleError(ctx context.Context, err error) error

type BearerToken

type BearerToken struct {
	Token     string
	ExpiresAt time.Time // ExpiresAt is the time when the token expires. If it is zero, the token does not expire.
}

BearerToken is a token used in the Bearer authentication scheme.

func (BearerToken) Empty

func (t BearerToken) Empty() bool

func (BearerToken) Equal

func (t BearerToken) Equal(other BearerToken) bool

func (BearerToken) IsExpired

func (t BearerToken) IsExpired() bool

func (BearerToken) MarshalYAML

func (t BearerToken) MarshalYAML() (any, error)

func (BearerToken) NotEmpty

func (t BearerToken) NotEmpty() bool

func (BearerToken) String

func (t BearerToken) String() string

func (*BearerToken) UnmarshalYAML

func (t *BearerToken) UnmarshalYAML(node *yaml.Node) error

type BearerTokener

type BearerTokener interface {
	// BearerToken returns a [BearerToken] for use in the [AuthorizationHeader].
	BearerToken(context.Context) (BearerToken, error)

	// HandleError processes errors from gRPC calls that fail with the Unauthenticated status code.
	// It receives the [BearerToken] returned by [BearerTokener.BearerToken] and the error from the gRPC call.
	// If HandleError returns nil, the system will attempt to re-authenticate and retry the call.
	// If the call should not be retried, HandleError should return the original error.
	HandleError(context.Context, BearerToken, error) error
}

BearerTokener is an interface for providing a BearerToken for authentication. Most implementations provided in this package are decorators, allowing you to layer additional behavior on top of a base implementation. These can be combined or extended to fit custom authentication requirements.

type CachedBearerTokener

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

CachedBearerTokener is a BearerTokener decorator that caches the BearerToken. Method CachedBearerTokener.HandleError invalidates the cache on any error.

func NewCachedBearerTokener

func NewCachedBearerTokener(tokener BearerTokener) *CachedBearerTokener

NewCachedBearerTokener returns a decorated BearerTokener that caches the BearerToken.

func (*CachedBearerTokener) BearerToken

func (c *CachedBearerTokener) BearerToken(ctx context.Context) (BearerToken, error)

func (*CachedBearerTokener) HandleError

func (c *CachedBearerTokener) HandleError(ctx context.Context, token BearerToken, err error) error

func (*CachedBearerTokener) Unwrap

func (c *CachedBearerTokener) Unwrap() BearerTokener

type CachedServiceAccount

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

CachedServiceAccount is a ServiceAccountReader decorator that caches the ServiceAccount.

func NewCachedServiceAccount

func NewCachedServiceAccount(reader ServiceAccountReader) *CachedServiceAccount

NewCachedServiceAccount returns a decorated ServiceAccountReader that caches the ServiceAccount.

func (*CachedServiceAccount) ServiceAccount

func (c *CachedServiceAccount) ServiceAccount(ctx context.Context) (ServiceAccount, error)

type CachedServiceTokener

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

CachedServiceTokener is a BearerTokener decorator that enhances its functionality with BearerToken caching and automatic background refresh to ensure that token is always valid.

Recommended parameters from the IAM team:

  • lifetime: 0.9 of token lifespan (90% of the token lifespan)
  • initial retry: 1 second
  • max retry: 1 minute

func NewCachedServiceTokener

func NewCachedServiceTokener(
	logger *slog.Logger,
	tokener BearerTokener,
	lifetime float64,
	initialRetry time.Duration,
	retryMultiplier float64,
	maxRetry time.Duration,
) *CachedServiceTokener

NewCachedServiceTokener returns a decorated BearerTokener that enhances its functionality with BearerToken caching and automatic background refresh to ensure that token is always valid.

Recommended parameters from the IAM team:

  • lifetime: 0.9 of token lifespan (90% of the token lifespan)
  • initial retry: 1 second
  • max retry: 1 minute

func (*CachedServiceTokener) BearerToken

func (c *CachedServiceTokener) BearerToken(ctx context.Context) (BearerToken, error)

func (*CachedServiceTokener) HandleError

func (c *CachedServiceTokener) HandleError(ctx context.Context, token BearerToken, err error) error

func (*CachedServiceTokener) Run

func (*CachedServiceTokener) Unwrap

func (c *CachedServiceTokener) Unwrap() BearerTokener

type Disable

type Disable struct {
	grpc.EmptyCallOption
}

Disable is a grpc.CallOption that disables authentication for a specific gRPC request.

type Error

type Error struct {
	Cause error
}

Error wraps an authentication-related error.

It intentionally does not provide an Unwrap method to avoid unintended behavior or bugs. To access the underlying error, use errors.As as follows:

var authErr *auth.Error
if errors.As(err, &authErr) {
	underlyingErr := authErr.Cause
}

func (*Error) Error

func (e *Error) Error() string

type ExchangeTokenRequester

type ExchangeTokenRequester interface {
	GetExchangeTokenRequest(context.Context) (*iampb.ExchangeTokenRequest, error)
}

type ExchangeableBearerTokener

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

ExchangeableBearerTokener is a BearerTokener that exchanges tokens using the iampb.TokenExchangeServiceClient.Exchange method. It relies on an ExchangeTokenRequester to generate the request payload for the exchange.

func NewExchangeableBearerTokener

func NewExchangeableBearerTokener(
	creds ExchangeTokenRequester,
	client iampb.TokenExchangeServiceClient,
) *ExchangeableBearerTokener

NewExchangeableBearerTokener returns a BearerTokener that exchanges tokens using the iampb.TokenExchangeServiceClient.Exchange method. It relies on an ExchangeTokenRequester to generate the request payload for the exchange.

func NewExchangeableBearerTokenerWithDeferredClient

func NewExchangeableBearerTokenerWithDeferredClient(
	creds ExchangeTokenRequester,
	clientFunc func() (iampb.TokenExchangeServiceClient, error),
) *ExchangeableBearerTokener

NewExchangeableBearerTokenerWithDeferredClient returns a BearerTokener that exchanges tokens using the iampb.TokenExchangeServiceClient.Exchange method. It relies on an ExchangeTokenRequester to generate the request payload for the exchange. The gRPC client is provided via a function, allowing for lazy initialization.

func (*ExchangeableBearerTokener) BearerToken

func (*ExchangeableBearerTokener) HandleError

func (*ExchangeableBearerTokener) SetClient

SetClient updates the gRPC client.

Note: This method is not thread-safe and should be called during initialization.

type FederatedCredentials

type FederatedCredentials string

type FederatedCredentialsReader

type FederatedCredentialsReader interface {
	GetFederatedCredentials() (FederatedCredentials, error)
}

type FederatedCredentialsTokenRequester

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

func NewFederatedCredentialsTokenRequester

func NewFederatedCredentialsTokenRequester(serviceAccountID string, reader FederatedCredentialsReader) *FederatedCredentialsTokenRequester

func (*FederatedCredentialsTokenRequester) GetExchangeTokenRequest

GetExchangeTokenRequest implements ExchangeTokenRequester.

type FileFederatedCredentialsReader

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

func NewFileFederatedCredentialsReader

func NewFileFederatedCredentialsReader(filePath string) *FileFederatedCredentialsReader

func (*FileFederatedCredentialsReader) GetFederatedCredentials

func (f *FileFederatedCredentialsReader) GetFederatedCredentials() (FederatedCredentials, error)

type FileTokener

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

func NewFileTokener

func NewFileTokener(
	path string,
	refreshPeriod time.Duration,
) (*FileTokener, error)

func (*FileTokener) BearerToken

func (c *FileTokener) BearerToken(ctx context.Context) (BearerToken, error)

func (*FileTokener) HandleError

func (c *FileTokener) HandleError(ctx context.Context, token BearerToken, err error) error

type IMDSTokenizer

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

IMDSTokenizer is a BearerTokener that serves token from IMDS HTTP endpoint, requesting it every time. The endpoint is expected to return JSON-encoded Token.

func NewIMDSTokenizer

func NewIMDSTokenizer(endpoint string, maxAttempts int, baseBackoff time.Duration) (*IMDSTokenizer, error)

NewIMDSTokenizer returns a BearerTokener that serves token from IMDS HTTP endpoint, requesting it every time.

func (*IMDSTokenizer) BearerToken

func (t *IMDSTokenizer) BearerToken(ctx context.Context) (BearerToken, error)

func (*IMDSTokenizer) HandleError

func (t *IMDSTokenizer) HandleError(ctx context.Context, token BearerToken, err error) error

type InAppSyncTokener

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

InAppSyncTokener is a BearerTokener decorator that synchronizes requests to [BearerTokener.BearerToken] within a single process.

func NewInAppSyncTokener

func NewInAppSyncTokener(tokener BearerTokener) *InAppSyncTokener

NewInAppSyncTokener returns a decorated BearerTokener that synchronizes requests to [BearerTokener.BearerToken] within a single process.

func (*InAppSyncTokener) BearerToken

func (t *InAppSyncTokener) BearerToken(ctx context.Context) (BearerToken, error)

func (*InAppSyncTokener) HandleError

func (t *InAppSyncTokener) HandleError(
	ctx context.Context,
	token BearerToken,
	err error,
) error

func (*InAppSyncTokener) Unwrap

func (t *InAppSyncTokener) Unwrap() BearerTokener

type MultiprocessSyncTokener

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

MultiprocessSyncTokener is a BearerTokener decorator that synchronizes requests to [BearerTokener.BearerToken] across multiple processes using a lock file in the default cache directory.

func NewMultiprocessSyncTokener

func NewMultiprocessSyncTokener(tokener BearerTokener) (*MultiprocessSyncTokener, error)

NewMultiprocessSyncTokener returns a decorated BearerTokener that synchronizes requests to [BearerTokener.BearerToken] across multiple processes using a lock file in the default cache directory.

func (*MultiprocessSyncTokener) BearerToken

func (t *MultiprocessSyncTokener) BearerToken(
	ctx context.Context,
) (_ BearerToken, deferError error)

func (*MultiprocessSyncTokener) HandleError

func (t *MultiprocessSyncTokener) HandleError(
	ctx context.Context,
	token BearerToken,
	err error,
) error

func (*MultiprocessSyncTokener) Unwrap

type NameWrapper

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

NameWrapper is a wrapper around a BearerTokener that adds a name to the tokener if the tokener does not have a name.

func NewNameWrapper

func NewNameWrapper(name string, tokener BearerTokener) *NameWrapper

func (*NameWrapper) BearerToken

func (n *NameWrapper) BearerToken(ctx context.Context) (BearerToken, error)

func (*NameWrapper) HandleError

func (n *NameWrapper) HandleError(ctx context.Context, token BearerToken, err error) error

func (*NameWrapper) Name

func (n *NameWrapper) Name() string

func (*NameWrapper) Unwrap

func (n *NameWrapper) Unwrap() BearerTokener

type NamedTokener

type NamedTokener interface {
	BearerTokener
	Name() string
}

func NewFederatedCredentialsTokener

func NewFederatedCredentialsTokener(
	serviceAccountID string,
	fileName string,
	clientFunc func() (iampb.TokenExchangeServiceClient, error),
) NamedTokener

NewFederatedCredentialsTokener creates a BearerTokener serving token from federated credentials stored in a file. Don't forget to wrap in NewAsynchronouslyRenewableFileCachedTokener or NewCachedServiceTokener

func NewPureFileCachedTokener

func NewPureFileCachedTokener(
	cacheFile string,
	name string,
	logger *slog.Logger,
) NamedTokener

func NewServiceAccountTokener

func NewServiceAccountTokener(
	id string,
	publicKeyID string,
	privateKey string,
	getIAMClient func() (iampb.TokenExchangeServiceClient, error),
) NamedTokener

type PrivateKeyFileParser

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

PrivateKeyFileParser is a ServiceAccountReader that reads and parses a PEM-encoded PKCS1 or PKCS8 private key from a file.

func NewPrivateKeyFileParser

func NewPrivateKeyFileParser(
	fs fs.FS,
	privateKeyPath string,
	publicKeyID string,
	serviceAccountID string,
) PrivateKeyFileParser

NewPrivateKeyFileParser returns a ServiceAccountReader that reads and parses a PEM-encoded PKCS1 or PKCS8 private key from a file.

If fs is nil, the default file system will be used.

func (PrivateKeyFileParser) ServiceAccount

type PrivateKeyParser

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

PrivateKeyParser is a ServiceAccountReader that parses a PEM-encoded PKCS1 or PKCS8 private key.

func NewPrivateKeyParser

func NewPrivateKeyParser(privateKey []byte, publicKeyID string, serviceAccountID string) PrivateKeyParser

NewPrivateKeyParser returns a ServiceAccountReader that parses a PEM-encoded PKCS1 or PKCS8 private key.

func (PrivateKeyParser) ServiceAccount

func (p PrivateKeyParser) ServiceAccount(context.Context) (ServiceAccount, error)

type PropagateAuthorizationHeader

type PropagateAuthorizationHeader struct{}

PropagateAuthorizationHeader is an Authenticator that transfers the AuthorizationHeader from incoming gRPC metadata to outgoing metadata.

func NewPropagateAuthorizationHeader

func NewPropagateAuthorizationHeader() PropagateAuthorizationHeader

NewPropagateAuthorizationHeader returns an Authenticator that transfers the AuthorizationHeader from incoming gRPC metadata to outgoing metadata.

func (PropagateAuthorizationHeader) Auth

func (PropagateAuthorizationHeader) HandleError

type RenewableFileCachedTokener

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

func NewFileCachedTokener

func NewFileCachedTokener(
	cacheFile string,
	tokener NamedTokener,
	safetyMargin time.Duration,
	logger *slog.Logger,
) *RenewableFileCachedTokener

func (*RenewableFileCachedTokener) BearerToken

func (*RenewableFileCachedTokener) HandleError

func (f *RenewableFileCachedTokener) HandleError(
	ctx context.Context, token BearerToken, checkErr error,
) error

func (*RenewableFileCachedTokener) Name

func (*RenewableFileCachedTokener) SetCacheThrottle

func (f *RenewableFileCachedTokener) SetCacheThrottle(throttle time.Duration)

func (*RenewableFileCachedTokener) Unwrap

type Runnable

type Runnable interface {
	Run(ctx context.Context) error
}

type Selector

type Selector struct {
	grpc.EmptyCallOption
	Name string
}

Selector is a grpc.CallOption that allows specifying which authenticator to use for a particular gRPC request. The selected authenticator must be pre-configured in the client.

func Select

func Select(name string) Selector

Select returns a Selector for specifying an authenticator by name to use for a particular gRPC request.

type ServiceAccount

type ServiceAccount struct {
	PrivateKey       *rsa.PrivateKey
	PublicKeyID      string
	ServiceAccountID string
}

type ServiceAccountCredentials

type ServiceAccountCredentials struct {
	SubjectCredentials SubjectCredentials `json:"subject-credentials"`
}

ServiceAccountCredentials represents the structure of a service account credentials file.

type ServiceAccountCredentialsFileParser

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

ServiceAccountCredentialsFileParser is a ServiceAccountReader that parses a JSON file containing service account credentials.

func NewServiceAccountCredentialsFileParser

func NewServiceAccountCredentialsFileParser(fs fs.FS, credentialsPath string) ServiceAccountCredentialsFileParser

NewServiceAccountCredentialsFileParser is a ServiceAccountReader that parses a JSON file containing service account credentials. The file format is following:

{
  "subject-credentials": {
    "alg": "RS256",
    "private-key": "PKCS#8 PEM with new lines escaped as \n",
    "kid": "publickey-...",
    "iss": "serviceaccount-...",
    "sub": "serviceaccount-..."
  }
}

Note: Field names follow standard abbreviations, similar to JWT standards or RFC 7515.

If fs is nil, the default file system will be used.

func (ServiceAccountCredentialsFileParser) ServiceAccount

func (ServiceAccountCredentialsFileParser) SubjectCredentials

type ServiceAccountExchangeTokenRequester

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

ServiceAccountExchangeTokenRequester is an ExchangeTokenRequester that generates a signed JWT using the credentials of a ServiceAccount. The JWT is intended for exchange to obtain a BearerToken via a token exchange service.

func NewServiceAccountExchangeTokenRequester

func NewServiceAccountExchangeTokenRequester(account ServiceAccountReader) ServiceAccountExchangeTokenRequester

NewServiceAccountExchangeTokenRequester returns an ExchangeTokenRequester that generates a signed JWT using the credentials of a ServiceAccount. The JWT is intended for exchange to obtain a BearerToken via a token exchange service.

func (ServiceAccountExchangeTokenRequester) GetExchangeTokenRequest

type ServiceAccountReader

type ServiceAccountReader interface {
	ServiceAccount(context.Context) (ServiceAccount, error)
}

type StaticBearerToken

type StaticBearerToken string

StaticBearerToken is a BearerTokener that always returns a fixed BearerToken.

func NewStaticBearerToken

func NewStaticBearerToken(token string) StaticBearerToken

NewStaticBearerToken returns a BearerTokener that always returns a fixed BearerToken.

func (StaticBearerToken) BearerToken

func (StaticBearerToken) HandleError

func (t StaticBearerToken) HandleError(_ context.Context, _ BearerToken, err error) error

type StaticFederatedCredentialsReader

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

func NewStaticFederatedCredentialsReader

func NewStaticFederatedCredentialsReader(credentials FederatedCredentials) *StaticFederatedCredentialsReader

func (*StaticFederatedCredentialsReader) GetFederatedCredentials

func (s *StaticFederatedCredentialsReader) GetFederatedCredentials() (FederatedCredentials, error)

type StaticServiceAccount

type StaticServiceAccount ServiceAccount

StaticServiceAccount is a ServiceAccountReader that always returns a fixed ServiceAccount.

func NewStaticServiceAccount

func NewStaticServiceAccount(sa ServiceAccount) StaticServiceAccount

NewStaticServiceAccount returns a ServiceAccountReader that always returns a fixed ServiceAccount.

func (StaticServiceAccount) ServiceAccount

type SubjectCredentials

type SubjectCredentials struct {
	Type       string `json:"type,omitempty"`
	Alg        string `json:"alg"`
	PrivateKey string `json:"private-key"` // PrivateKey is a PEM-encoded PKCS8 string.
	KeyID      string `json:"kid"`
	Issuer     string `json:"iss"`
	Subject    string `json:"sub"`
}

type Token

type Token struct {
	AccessToken string    `json:"access_token"`
	ExpiresAt   time.Time `json:"expires_at"`
}

type Wrapper

type Wrapper interface {
	Unwrap() BearerTokener
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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