authentication

package
v0.1.417 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2024 License: Apache-2.0 Imports: 29 Imported by: 16

Documentation

Index

Constants

View Source
const (
	RedirectURL     = "http://127.0.0.1"
	RedirectPort    = "9998"
	DefaultAuthURL  = "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/auth"
	CallbackHandler = "/oauth/callback"
)
View Source
const (
	// #nosec G101
	DefaultTokenURL     = "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token"
	DefaultClientID     = "cloud-services"
	DefaultClientSecret = ""
)

Default values:

View Source
const (
	DeviceAuthURL = "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/auth/device"
)

Variables

View Source
var DefaultScopes = []string{
	"openid",
}

DefaultScopes is the ser of scopes used by default:

Functions

func BearerFromContext

func BearerFromContext(ctx context.Context) (result string, err error)

BearerFromContext extracts the bearer token of the user from the context. If no user is found in the context then the result will be the empty string.

func ContextWithToken

func ContextWithToken(parent context.Context, token *jwt.Token) context.Context

ContextWithToken creates a new context containing the given token.

func InitiateAuthCode added in v0.1.394

func InitiateAuthCode(clientID string) (string, error)

func TokenFromContext

func TokenFromContext(ctx context.Context) (result *jwt.Token, err error)

TokenFromContext extracts the JSON web token of the user from the context. If no token is found in the context then the result will be nil.

Types

type DeviceAuthConfig added in v0.1.394

type DeviceAuthConfig struct {
	DeviceAuthResponse *oauth2.DeviceAuthResponse
	ClientID           string
	// contains filtered or unexported fields
}

func (*DeviceAuthConfig) InitiateDeviceAuth added in v0.1.394

func (d *DeviceAuthConfig) InitiateDeviceAuth(ctx context.Context) (*DeviceAuthConfig, error)

Step 1: Initiates device code flow and returns the device auth config. After running, use your DeviceAuthConfig to display the user code and verification URI

fmt.Printf("To continue login, navigate to %v and enter code %v\n", deviceAuthResp.VerificationURI, deviceAuthResp.UserCode)
fmt.Printf("Checking status every %v seconds...\n", deviceAuthResp.Interval)

func (*DeviceAuthConfig) PollForTokenExchange added in v0.1.394

func (d *DeviceAuthConfig) PollForTokenExchange(ctx context.Context) (string, error)

Step 2: Initiates polling for token exchange and returns a refresh token

type Handler

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

Handler is an HTTP handler that checks authentication using the JWT tokens from the authorization header.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is the implementation of the HTTP handler interface.

type HandlerBuilder

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

HandlerBuilder contains the data and logic needed to create a new authentication handler. Don't create objects of this type directly, use the NewHandler function instead.

func NewHandler

func NewHandler() *HandlerBuilder

NewHandler creates a builder that can then be configured and used to create authentication handlers.

func (*HandlerBuilder) ACLFile

func (b *HandlerBuilder) ACLFile(value string) *HandlerBuilder

ACLFile sets a file that contains items of the access control list. This should be a YAML file with the following format:

  • claim: email pattern: ^.*@redhat\.com$

  • claim: sub pattern: ^f:b3f7b485-7184-43c8-8169-37bd6d1fe4aa:myuser$

The claim field is the name of the claim of the JWT token that will be checked. The pattern field is a regular expression. If the claim matches the regular expression then access will be allowed.

If the ACL is empty then access will be allowed to all JWT tokens.

If the ACL has at least one item then access will be allowed only to tokens that match at least one of the items.

func (*HandlerBuilder) Build

func (b *HandlerBuilder) Build() (handler *Handler, err error)

Build uses the data stored in the builder to create a new authentication handler.

func (*HandlerBuilder) Cookie added in v0.0.329

func (b *HandlerBuilder) Cookie(value string) *HandlerBuilder

Cookie sets the name of the cookie where the bearer token will be extracted from when the `Authorization` header isn't present. The default is `cs_jwt`.

func (*HandlerBuilder) Error added in v0.0.329

func (b *HandlerBuilder) Error(value string) *HandlerBuilder

Error sets the error identifier that will be used to generate JSON error responses. For example, if the value is `123` then the JSON for error responses will be like this:

{
	"kind": "Error",
	"id": "11",
	"href": "/api/clusters_mgmt/v1/errors/11",
	"code": "CLUSTERS-MGMT-11",
	"reason": "Bearer token is expired"
}

When this isn't explicitly provided the value will be `401`. Note that changing this doesn't change the HTTP response status, that will always be 401.

func (*HandlerBuilder) KeysCAs

func (b *HandlerBuilder) KeysCAs(value *x509.CertPool) *HandlerBuilder

KeysCAs sets the certificate authorities that will be trusted when verifying the certificate of the web server where keys are loaded from.

func (*HandlerBuilder) KeysFile

func (b *HandlerBuilder) KeysFile(value string) *HandlerBuilder

KeysFile sets the location of a file containing a JSON web key set that will be used to verify the signatures of the tokens. The keys from this file will be loaded when a token is received containing an unknown key identifier.

At least one keys file or one keys URL is mandatory.

func (*HandlerBuilder) KeysInsecure

func (b *HandlerBuilder) KeysInsecure(value bool) *HandlerBuilder

KeysInsecure sets the flag that indicates that the certificate of the web server where the keys are loaded from should not be checked. The default is false and changing it to true makes the token verification insecure, so refrain from doing that in security sensitive environments.

func (*HandlerBuilder) KeysURL

func (b *HandlerBuilder) KeysURL(value string) *HandlerBuilder

KeysURL sets the URL containing a JSON web key set that will be used to verify the signatures of the tokens. The keys from these URLs will be loaded when a token is received containing an unknown key identifier.

At least one keys file or one keys URL is mandatory.

func (*HandlerBuilder) Logger

func (b *HandlerBuilder) Logger(value logging.Logger) *HandlerBuilder

Logger sets the logger that the middleware will use to send messages to the log. This is mandatory.

func (*HandlerBuilder) Next

func (b *HandlerBuilder) Next(value http.Handler) *HandlerBuilder

Next sets the HTTP handler that will be called when the authentication handler has authenticated correctly the request. This is mandatory.

func (*HandlerBuilder) OperationID added in v0.0.329

func (b *HandlerBuilder) OperationID(value func(r *http.Request) string) *HandlerBuilder

OperationID sets a function that will be called each time an error is detected, passing the details of the request that caused the error. The value returned by the function will be included in the `operation_id` field of the JSON error response. For example, if the function returns `123` the generated JSON error response will be like this:

{
	"kind": "Error",
	"id": "401",
	"href": "/api/clusters_mgmt/v1/errors/401",
	"code": "CLUSTERS-MGMT-401",
	"reason": "Bearer token is expired".
	"operation_id": "123"
}

For example, if the operation identifier is available in an HTTP header named `X-Operation-ID` then the handler can be configured like this to use it:

handler, err := authentication.NewHandler().
	Logger(logger).
	KeysURL("https://...").
	OperationID(func(r *http.Request) string {
		return r.Header.Get("X-Operation-ID")
	}).
	Next(next).
	Build()
if err != nil {
	...
}

If the function returns an empty string then the `operation_id` field will not be added.

By default there is no function configured for this, so no `operation_id` field will be added.

func (*HandlerBuilder) Public

func (b *HandlerBuilder) Public(value string) *HandlerBuilder

Public sets a regular expression that defines the parts of the URL space that considered public, and therefore require no authentication. This method may be called multiple times and then all the given regular expressions will be used to check what parts of the URL space are public.

func (*HandlerBuilder) Service added in v0.0.329

func (b *HandlerBuilder) Service(value string) *HandlerBuilder

Service sets the identifier of the service that will be used to generate error codes. For example, if the value is `my_service` then the JSON for error responses will be like this:

{
	"kind": "Error",
	"id": "401",
	"href": "/api/clusters_mgmt/v1/errors/401",
	"code": "MY-SERVICE-401",
	"reason": "Bearer token is expired"
}

When this isn't explicitly provided the value will be extracted from the second segment of the request path. For example, if the request URL is `/api/clusters_mgmt/v1/cluster` the value will be `clusters_mgmt`.

func (*HandlerBuilder) Tolerance added in v0.0.329

func (b *HandlerBuilder) Tolerance(value time.Duration) *HandlerBuilder

Tolerance sets the maximum time that a token will be considered valid after it has expired. For example, to accept requests with tokens that have expired up to five minutes ago:

handler, err := authentication.NewHandler().
	Logger(logger).
	KeysURL("https://...").
	Tolerance(5 * time.Minute).
	Next(next).
	Build()
if err != nil {
	...
}

The default value is zero tolerance.

type TransportWrapper added in v0.0.329

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

TransportWrapper contains the data and logic needed to wrap an HTTP round tripper with another one that adds authorization tokens to requests.

func (*TransportWrapper) Client added in v0.0.329

func (w *TransportWrapper) Client() (id, secret string)

Client returns OpenID client identifier and secret that the wrapper is using to request OpenID access tokens.

func (*TransportWrapper) Close added in v0.0.329

func (w *TransportWrapper) Close() error

Close releases all the resources used by the wrapper.

func (*TransportWrapper) Logger added in v0.0.329

func (w *TransportWrapper) Logger() logging.Logger

Logger returns the logger that is used by the wrapper.

func (*TransportWrapper) Scopes added in v0.0.329

func (w *TransportWrapper) Scopes() []string

Scopes returns the OpenID scopes that the wrapper is using to request OpenID access tokens.

func (*TransportWrapper) TokenURL added in v0.0.329

func (w *TransportWrapper) TokenURL() string

TokenURL returns the URL that the connection is using request OpenID access tokens.

func (*TransportWrapper) Tokens added in v0.0.329

func (w *TransportWrapper) Tokens(ctx context.Context, expiresIn ...time.Duration) (access,
	refresh string, err error)

Tokens returns the access and refresh tokens that are currently in use by the wrapper. If it is necessary to request new tokens because they weren't requested yet, or because they are expired, this method will do it and will return an error if it fails.

If new tokens are needed the request will be retried with an exponential backoff.

func (*TransportWrapper) User added in v0.0.329

func (w *TransportWrapper) User() (user, password string)

User returns the user name and password that the wrapper is using to request OpenID access tokens.

func (*TransportWrapper) Wrap added in v0.0.329

func (w *TransportWrapper) Wrap(transport http.RoundTripper) http.RoundTripper

Wrap creates a new round tripper that wraps the given one and populates the authorization header.

type TransportWrapperBuilder added in v0.0.329

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

TransportWrapperBuilder contains the data and logic needed to add to requests the authorization token. Don't create objects of this type directly; use the NewTransportWrapper function instead.

func NewTransportWrapper added in v0.0.329

func NewTransportWrapper() *TransportWrapperBuilder

NewTransportWrapper creates a new builder that can then be used to configure and create a new authentication round tripper.

func (*TransportWrapperBuilder) Agent added in v0.0.329

Agent sets the `User-Agent` header that the round trippers will use in all the HTTP requests. The default is `OCM-SDK` followed by an slash and the version of the SDK, for example `OCM/0.0.0`.

func (*TransportWrapperBuilder) Build added in v0.0.329

func (b *TransportWrapperBuilder) Build(ctx context.Context) (result *TransportWrapper, err error)

Build uses the information stored in the builder to create a new transport wrapper.

func (*TransportWrapperBuilder) Client added in v0.0.329

Client sets OpenID client identifier and secret that will be used to request OpenID tokens. The default identifier is `cloud-services`. The default secret is the empty string. When these two values are provided and no user name and password is provided, the round trippers will use the client credentials grant to obtain the token. For example, to create a connection using the client credentials grant do the following:

// Use the client credentials grant:
wrapper, err := authentication.NewTransportWrapper().
	Client("myclientid", "myclientsecret").
	Build()

Note that some OpenID providers (Keycloak, for example) require the client identifier also for the resource owner password grant. In that case use the set only the identifier, and let the secret blank. For example:

// Use the resource owner password grant:
wrapper, err := authentication.NewTransportWrapper().
	User("myuser", "mypassword").
	Client("myclientid", "").
	Build()

Note the empty client secret.

func (*TransportWrapperBuilder) Insecure added in v0.0.329

Insecure enables insecure communication with the OpenID server. This disables verification of TLS certificates and host names and it isn't recommended for a production environment.

func (*TransportWrapperBuilder) Logger added in v0.0.329

Logger sets the logger that will be used by the wrapper and by the transports that it creates.

func (*TransportWrapperBuilder) MetricsRegisterer added in v0.0.329

MetricsRegisterer sets the Prometheus registerer that will be used to register the metrics. The default is to use the default Prometheus registerer and there is usually no need to change that. This is intended for unit tests, where it is convenient to have a registerer that doesn't interfere with the rest of the system.

func (*TransportWrapperBuilder) MetricsSubsystem added in v0.0.329

func (b *TransportWrapperBuilder) MetricsSubsystem(value string) *TransportWrapperBuilder

MetricsSubsystem sets the name of the subsystem that will be used by the wrapper to register metrics with Prometheus. If this isn't explicitly specified, or if it is an empty string, then no metrics will be registered. For example, if the value is `api_outbound` then the following metrics will be registered:

api_outbound_token_request_count - Number of token requests sent.
api_outbound_token_request_duration_sum - Total time to send token requests, in seconds.
api_outbound_token_request_duration_count - Total number of token requests measured.
api_outbound_token_request_duration_bucket - Number of token requests organized in buckets.

The duration buckets metrics contain an `le` label that indicates the upper bound. For example if the `le` label is `1` then the value will be the number of requests that were processed in less than one second.

code - HTTP response code, for example 200 or 500.

The value of the `code` label will be zero when sending the request failed without a response code, for example if it wasn't possible to open the connection, or if there was a timeout waiting for the response.

Note that setting this attribute is not enough to have metrics published, you also need to create and start a metrics server, as described in the documentation of the Prometheus library.

func (*TransportWrapperBuilder) Scopes added in v0.0.329

Scopes sets the OpenID scopes that will be included in the token request. The default is to use the `openid` scope. If this method is used then that default will be completely replaced, so you will need to specify it explicitly if you want to use it. For example, if you want to add the scope 'myscope' without loosing the default you will have to do something like this:

// Create a wrapper with the default 'openid' scope and some additional scopes:
wrapper, err := authentication.NewTransportWrapper().
	User("myuser", "mypassword").
	Scopes("openid", "myscope", "yourscope").
	Build()

If you just want to use the default 'openid' then there is no need to use this method.

func (*TransportWrapperBuilder) TokenURL added in v0.0.329

TokenURL sets the URL that will be used to request OpenID access tokens. The default is `https://sso.redhat.com/auth/realms/cloud-services/protocol/openid-connect/token`.

func (*TransportWrapperBuilder) Tokens added in v0.0.329

Tokens sets the OpenID tokens that will be used to authenticate. Multiple types of tokens are accepted, and used according to their type. For example, you can pass a single access token, or an access token and a refresh token, or just a refresh token. If no token is provided then the round trippers will the user name and password or the client identifier and client secret (see the User and Client methods) to request new ones.

If the wrapper is created with these tokens and no user or client credentials, it will stop working when both tokens expire. That can happen, for example, if the connection isn't used for a period of time longer than the life of the refresh token.

func (*TransportWrapperBuilder) TransportWrapper added in v0.0.329

TransportWrapper adds a function that will be used to wrap the transports of the HTTP client used to request tokens. If used multiple times the transport wrappers will be called in the same order that they are added.

func (*TransportWrapperBuilder) TransportWrappers added in v0.0.329

func (b *TransportWrapperBuilder) TransportWrappers(
	values ...func(http.RoundTripper) http.RoundTripper) *TransportWrapperBuilder

TransportWrappers adds a list of functions that will be used to wrap the transports of the HTTP client used to request tokens

func (*TransportWrapperBuilder) TrustedCA added in v0.0.329

func (b *TransportWrapperBuilder) TrustedCA(value interface{}) *TransportWrapperBuilder

TrustedCA sets a source that contains he certificate authorities that will be trusted by the HTTP client used to request tokens. If this isn't explicitly specified then the clients will trust the certificate authorities trusted by default by the system. The value can be a *x509.CertPool or a string, anything else will cause an error when Build method is called. If it is a *x509.CertPool then the value will replace any other source given before. If it is a string then it should be the name of a PEM file. The contents of that file will be added to the previously given sources.

func (*TransportWrapperBuilder) TrustedCAs added in v0.0.329

func (b *TransportWrapperBuilder) TrustedCAs(values ...interface{}) *TransportWrapperBuilder

TrustedCAs sets a list of sources that contains he certificate authorities that will be trusted by the HTTP client used to request tokens. See the documentation of the TrustedCA method for more information about the accepted values.

func (*TransportWrapperBuilder) User added in v0.0.329

User sets the user name and password that will be used to request OpenID access tokens. When these two values are provided the round trippers will use the resource owner password grant type to obtain the token. For example:

// Use the resource owner password grant:
wrapper, err := authentication.NewTransportWrapper().
	User("myuser", "mypassword").
	Build()

Note that some OpenID providers (Keycloak, for example) require the client identifier also for the resource owner password grant. In that case use the set only the identifier, and let the secret blank. For example:

// Use the resource owner password grant:
wrapper, err := authentication.NewConnectionBuilder().
	User("myuser", "mypassword").
	Client("myclientid", "").
	Build()

Note the empty client secret.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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