oauth2

package
v0.3.61 Latest Latest
Warning

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

Go to latest
Published: Jan 17, 2024 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrKeyFormat is raised when something is wrong with the
	// encryption keys.
	ErrKeyFormat = errors.New("key format error")

	// ErrTokenVerification is raised when token verification fails.
	ErrTokenVerification = errors.New("failed to verify token")

	// ErrContextError is raised when a required value cannot be retrieved
	// from a context.
	ErrContextError = errors.New("value missing from context")
)

Functions

func Issue

func Issue(i *jose.JWTIssuer, r *http.Request, subject string, uclaims *UnikornClaims, scope *ScopeList, expiresAt time.Time) (string, error)

Issue issues a new JWT token.

func NewContextWithClaims

func NewContextWithClaims(ctx context.Context, claims *Claims) context.Context

NewContextWithClaims injects the given claims into a new context.

Types

type APIScope

type APIScope string

APIScope defines security context scopes for an API request.

const (
	// ScopeProject tells us the claims token is project scoped.
	ScopeProject APIScope = "project"
)

type Authenticator

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

Authenticator provides Keystone authentication functionality.

func New

func New(options *Options, issuer *jose.JWTIssuer, keystone *keystone.Authenticator) *Authenticator

New returns a new authenticator with required fields populated. You must call AddFlags after this.

func (*Authenticator) Authorization

func (a *Authenticator) Authorization(w http.ResponseWriter, r *http.Request)

Authorization redirects the client to the OIDC autorization endpoint to get an authorization code. Note that this function is responsible for either returning an authorization grant or error via a HTTP 302 redirect, or returning a HTML fragment for errors that cannot follow the provided redirect URI.

func (*Authenticator) OIDCCallback

func (a *Authenticator) OIDCCallback(w http.ResponseWriter, r *http.Request)

OIDCCallback is called by the authorization endpoint in order to return an authorization back to us. We then exchange the code for an ID token, and refresh token. Remember, as far as the client is concerned we're still doing the code grant, so return errors in the redirect query.

func (*Authenticator) Token

Token issues an OAuth2 access token from the provided autorization code.

type Claims

type Claims struct {
	jwt.Claims `json:",inline"`

	// Scope is the set of scopes for a JWT as defined by oauth2.
	// These also correspond to security requirements in the OpenAPI schema.
	Scope *ScopeList `json:"scope,omitempty"`

	// UnikornClaims are claims required by this application.
	UnikornClaims *UnikornClaims `json:"unikorn,omitempty"`
}

Claims is an application specific set of claims. TODO: this technically isn't conformant to oauth2 in that we don't specify the client_id claim, and there are probably others.

func ClaimsFromContext

func ClaimsFromContext(ctx context.Context) (*Claims, error)

ClaimsFromContext extracts the claims from a context.

func Verify

func Verify(i *jose.JWTIssuer, r *http.Request, tokenString string) (*Claims, error)

Verify checks the token parses and validates.

type Code

type Code struct {
	// ClientID is the client identifier.
	ClientID string `json:"cid"`
	// ClientRedirectURI is the redirect URL requested by the client.
	ClientRedirectURI string `json:"cri"`
	// ClientCodeChallenge records the client code challenge so we can
	// authenticate we are handing the authorization token back to the
	// correct client.
	ClientCodeChallenge string `json:"ccc"`
	// ClientScope records the requested client scope.
	ClientScope Scope `json:"csc,omitempty"`
	// ClientNonce is injected into a OIDC id_token.
	ClientNonce string `json:"cno,omitempty"`
	// KeystoneToken is the exchanged keystone token.
	KeystoneToken string `json:"kst"`
	// KeystoneUserID is exactly that.
	KeystoneUserID string `json:"kui"`
	// Email is exactly that.
	Email string `json:"email"`
	// Expiry is when the token expires.
	Expiry time.Time `json:"exp"`
}

Code is an authorization code to return to the client that can be exchanged for an access token. Much like how we client things in the oauth2 state during the OIDC exchange, to mitigate problems with horizonal scaling and sharing stuff, we do the same here. WARNING: Don't make this too big, the ingress controller will barf if the headers are too hefty.

type Error

type Error string
const (
	ErrorInvalidRequest          Error = "invalid_request"
	ErrorUnauthorizedClient      Error = "unauthorized_client"
	ErrorAccessDenied            Error = "access_denied"
	ErrorUnsupportedResponseType Error = "unsupported_response_type"
	ErrorInvalidScope            Error = "invalid_scope"
	ErrorServerError             Error = "server_error"
)

type IDToken

type IDToken struct {
	// These are default claims you always get.
	Issuer   string   `json:"iss"`
	Subject  string   `json:"sub"`
	Audience []string `json:"aud"`
	Expiry   int64    `json:"exp"`
	IssuedAt int64    `json:"iat"`
	Nonce    string   `json:"nonce,omitempty"`
	ATHash   string   `json:"at_hash,omitempty"`
	// Optional claims that may be asked for by the "email" scope.
	Email string `json:"email,omitempty"`
	// Optional claims that may be asked for by the "profile" scope.
	Picture string `json:"picture,omitempty"`
}

IDToken defines an OIDC id_token.

type Options

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

func (*Options) AddFlags

func (o *Options) AddFlags(f *pflag.FlagSet)

AddFlags to the specified flagset.

type Scope

type Scope []string

Scope wraps up scope functionality.

func NewScope

func NewScope(s string) Scope

NewScope takes a raw scope from a query and return a canonical scope type.

func (Scope) Has

func (s Scope) Has(scope string) bool

Has returns true if a scope exists.

type ScopeList

type ScopeList struct {
	Scopes []APIScope
}

ScopeList defines a list of scopes.

func (*ScopeList) Includes

func (l *ScopeList) Includes(scope APIScope) bool

Includes tells you whether a scurity requirement is fulfilled.

func (*ScopeList) MarshalJSON

func (l *ScopeList) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaller.

func (*ScopeList) UnmarshalJSON

func (l *ScopeList) UnmarshalJSON(value []byte) error

UnmarshalJSON implments json.Unmarshaller.

type State

type State struct {
	// Nonce is the one time nonce used to create the token.
	Nonce string `json:"n"`
	// Code verfier is required to prove our identity when
	// exchanging the code with the token endpoint.
	CodeVerfier string `json:"cv"`
	// ClientID is the client identifier.
	ClientID string `json:"cid"`
	// ClientRedirectURI is the redirect URL requested by the client.
	ClientRedirectURI string `json:"cri"`
	// Client state records the client's OAuth state while we interact
	// with the OIDC authorization server.
	ClientState string `json:"cst,omitempty"`
	// ClientCodeChallenge records the client code challenge so we can
	// authenticate we are handing the authorization token back to the
	// correct client.
	ClientCodeChallenge string `json:"ccc"`
	// ClientScope records the requested client scope.
	ClientScope Scope `json:"csc,omitempty"`
	// ClientNonce is injected into a OIDC id_token.
	ClientNonce string `json:"cno,omitempty"`
}

State records state across the call to the authorization server. This must be encrypted with JWE.

type UnikornClaims

type UnikornClaims struct {
	// Token is the OpenStack Keystone token.
	Token string `json:"token,omitempty"`

	// Project is the Openstack/Unikorn project ID the token is scoped to.
	// This is a unique identifier for the region.
	Project string `json:"projectId,omitempty"`

	// User is the Openstack user ID, the user name is stored in the "sub" claim.
	// This effectively caches the unique user ID so we don't have to translate
	// between names in the scope of the token, and what Openstack APIs expect.
	User string `json:"userId,omitempty"`
}

UnikornClaims are JWT claims we add to the underlying specification. TODO: we should bind the access token to a specific client IP (and validate), or something to that effect in order to mitigate impersonation from another source.

Jump to

Keyboard shortcuts

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