oauth2

package
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2021 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package oauth2 provides model implementations for and functionality for the OAuth2 server. This also provides an interface for implementations of OAuth2 clients to allow for authentication against the server.

Index

Constants

This section is empty.

Variables

View Source
var (
	Permissions = []Permission{
		Read,
		Write,
		Delete,
	}

	Resources = []Resource{
		Build,
		Invite,
		Image,
		Namespace,
		Object,
		Variable,
		Key,
		Cron,
		Webhook,
	}
)
View Source
var (
	ErrAuth = errors.New("authentication failed")
)

Functions

func AppModel

func AppModel(aa []*App) func(int) database.Model

AppModel is called along with database.ModelSlice to convert the given slice of App models to a slice of database.Model interfaces.

func CodeModel

func CodeModel(cc []*Code) func(int) database.Model

CodeModel is called along with database.ModelSlice to convert the given slice of Code models to a slice of database.Model interfaces.

func SelectToken

func SelectToken(col string, opts ...query.Option) query.Query

SelectToken returns SELECT query that will select the given column from the oauth_tokens table with the given query options applied.

func TokenModel

func TokenModel(tt []*Token) func(int) database.Model

TokenModel is called along with database.ModelSlice to convert the given slice of Token models to a slice of database.Model interfaces.

Types

type App

type App struct {
	ID           int64     `db:"id"`
	UserID       int64     `db:"user_id"`
	ClientID     string    `db:"client_id"`
	ClientSecret []byte    `db:"client_secret"`
	Name         string    `db:"name"`
	Description  string    `db:"description"`
	HomeURI      string    `db:"home_uri"`
	RedirectURI  string    `db:"redirect_uri"`
	CreatedAt    time.Time `db:"created_at"`

	User *user.User `db:"-"`
}

App is the type that represents an OAuth app created by a user.

func (*App) Bind

func (a *App) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to a user.User model.

func (*App) Endpoint

func (a *App) Endpoint(uri ...string) string

Endpoint returns the endpoint for the current App, and appends any of the given uri parts to the returned endpoint.

func (*App) IsZero

func (a *App) IsZero() bool

IsZero implements the database.Model interface.

func (*App) JSON

func (*App) JSON(_ string) map[string]interface{}

JSON implements the database.Model interface. This is a stub method and returns an empty map.

func (*App) Primary

func (a *App) Primary() (string, int64)

Primary implements the database.Model interface.

func (*App) SetPrimary

func (a *App) SetPrimary(id int64)

SetPrimary implements the database.Model interface.

func (*App) Values

func (a *App) Values() map[string]interface{}

Values implements the database.Model interface. This will return a map with the following values, user_id, client_id, client_secret, name, description, home_uri and redirect_uri.

type AppForm

type AppForm struct {
	Apps        *AppStore `schema:"-"`
	App         *App      `schema:"-"`
	Name        string    `schema:"name"`
	Description string    `schema:"description"`
	HomepageURI string    `schema:"homepage_uri"`
	RedirectURI string    `schema:"redirect_uri"`
}

AppForm if the type that represents input data for creating a new App.

func (AppForm) Fields

func (f AppForm) Fields() map[string]string

Fields returns a map of the name, description, homepage_uri, and redirect_uri fields for the current AppForm.

func (AppForm) Validate

func (f AppForm) Validate() error

Validate checks to see if the Name field is present in the form, and is unique. This uniqueness check is skipped if an App is set on the form, and the Name field already matches that name (assuming it's being edited). The Homepage, and Redirect URIs are checked for presence too, and if they are valid URLs.

type AppStore

type AppStore struct {
	database.Store

	// User is the bound user.User model. If not nil this will bind the
	// user.User model to any App models that are created. If not nil this
	// will append a WHERE clause on the user_id column for all SELECT queries
	// performed.
	User *user.User
	// contains filtered or unexported fields
}

AppStore is the type for creating and modfiying App models in the database. The AppStore type can have an underlying crypto.AESGCM for encrypting the App's secret.

func NewAppStore

func NewAppStore(db *sqlx.DB, mm ...database.Model) *AppStore

NewAppStore returns a new AppStore for querying the oauth_apps table. Each database passed to this function will be bound to the returned AppStore.

func NewAppStoreWithCrypto added in v1.1.0

func NewAppStoreWithCrypto(db *sqlx.DB, crypto *crypto.AESGCM, mm ...database.Model) *AppStore

NewAppStoreWithCrypto is functionally the same as NewAppStore, however it gets the crypto.AESGCM to use on the returned AppStore. This will allow for encryption of the App's secret.

func (*AppStore) All

func (s *AppStore) All(opts ...query.Option) ([]*App, error)

All returns a slice of App models, applying each query.Option that is given. The database.Where option is applied to the bound User database.

func (*AppStore) Auth

func (s *AppStore) Auth(id, secret string) (*App, error)

Auth finds the App database for the given client ID and checks that the given client secret matches what is in the database. If it matches, then the App database is returned. If authentication fails then ErrAuth is returned, if any other errors occur then they are wrapped via errors.Err.

func (*AppStore) Bind

func (s *AppStore) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to a user.User model.

func (*AppStore) Create

func (s *AppStore) Create(name, description, homepage, redirect string) (*App, error)

Create creates a new app with the given name and description, and homepage and redirect URIs. This will generate a random ID for the newly created App, and secret.

func (*AppStore) Delete

func (s *AppStore) Delete(ids ...int64) error

Delete delets the Apps of the given ids from the database.

func (*AppStore) Get

func (s *AppStore) Get(opts ...query.Option) (*App, error)

Get returns a single App database, applying each query.Option that is given. The database.Where option is applied to the bound User database.

func (*AppStore) New

func (s *AppStore) New() *App

New returns a new App binding any non-nil models to it from the current AppStore.

func (*AppStore) Reset

func (s *AppStore) Reset(id int64) error

Reset generates a new secret for the App of the given id, and updates it in the database. This will error if the underlying crypto.AESGCM is not set.

func (*AppStore) Update

func (s *AppStore) Update(id int64, name, description, homepage, redirect string) error

Update updates the App of the given id, and updates the name, description, homepage, and redirect properties in the database to what is given.

type AuthorizeForm

type AuthorizeForm struct {
	Authorize   bool   `schema:"bool"`
	ClientID    string `schema:"client_id"`
	Handle      string `schema:"handle"`
	Password    string `schema:"password"`
	Scope       string `schema:"scope"`
	State       string `schema:"state"`
	RedirectURI string `schema:"redirect_uri"`
}

AuthorizeForm is the type that represents input data of the OAuth authorization page, for when a user authorizes an App's access to their account.

func (AuthorizeForm) Fields

func (f AuthorizeForm) Fields() map[string]string

Fields returns a map of fields for the current AuthorizeForm. This map will contain the Handle field of the current AuthorizeForm.

func (AuthorizeForm) Validate

func (f AuthorizeForm) Validate() error

Validate checks to see if the Handle, and Password fields are present in the current AuthorizeForm.

type Code

type Code struct {
	ID        int64     `db:"id"`
	UserID    int64     `db:"user_id"`
	AppID     int64     `db:"app_id"`
	Code      string    `db:"code"`
	Scope     Scope     `db:"scope"`
	ExpiresAt time.Time `db:"expires_at"`

	User *user.User `db:"-"`
	App  *App       `db:"-"`
}

Code is the struct of the OAuth codes that are issued to generate the final token for authentication over the API.

func (*Code) Bind

func (c *Code) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or an App model.

func (*Code) Endpoint

func (*Code) Endpoint(_ ...string) string

Endpoint implements the database.Model interface. This is a stub method and returns an empty string.

func (*Code) IsZero

func (c *Code) IsZero() bool

IsZero implements the database.Model interface.

func (*Code) JSON

func (*Code) JSON(_ string) map[string]interface{}

JSON implements the database.Model interface. This is a stub method and returns an empty map.

func (*Code) Primary

func (c *Code) Primary() (string, int64)

Primary implements the database.Model interface.

func (*Code) SetPrimary

func (c *Code) SetPrimary(id int64)

SetPrimary implements the database.Model interface.

func (*Code) Values

func (c *Code) Values() map[string]interface{}

Values implements the database.Model interface. This will return a map with the following values, code, scope, and expires_at.

type CodeStore

type CodeStore struct {
	database.Store

	// User is the bound user.User model. If not nil this will bind the
	// user.User model to any Code models that are created. If not nil this
	// will append a WHERE clause on the user_id column for all SELECT queries
	// performed.
	User *user.User

	// App is the bound App model. If not nil this will bind the App model to
	// any Code models that are created. If not nil this will append a WHERE
	// clause on the app_id column for all SELECT queries performed.
	App *App
}

CodeStore is the type for creating and modifying Code models in the database.

func NewCodeStore

func NewCodeStore(db *sqlx.DB, mm ...database.Model) *CodeStore

NewCodeStore returns a new CodeStore for querying the oauth_codes table. Each database passed to this function will be bound to the returned CodeStore.

func (*CodeStore) Bind

func (s *CodeStore) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or an App model.

func (*CodeStore) Create

func (s *CodeStore) Create(scope Scope) (*Code, error)

Create creates a new code with the given scope. This will set the code's expiration to 10 minutes from when this is called.

func (*CodeStore) Delete

func (s *CodeStore) Delete(ids ...int64) error

Delete deletes the codes of the given ids from the database.

func (*CodeStore) Get

func (s *CodeStore) Get(opts ...query.Option) (*Code, error)

Get returns a single Code database, applying each query.Option that is given. The database.Where option is applied to the bound User database and bound App database.

func (*CodeStore) New

func (s *CodeStore) New() *Code

New returns a new Code binding any non-nil models to it from the current CodeStore.

type Permission

type Permission int

Permission represents what a scope can do to a resource, this will be either Read, Write, or Delete.

const (
	Read   Permission = 1 << iota // read
	Write                         // write
	Delete                        // delete
)

func (Permission) Expand

func (p Permission) Expand() []Permission

func (Permission) Has

func (p Permission) Has(mask Permission) bool

Determine if the given permission mask exists in the permission.

func (Permission) String

func (i Permission) String() string

type Resource

type Resource int

Resource is the resource that the OAuth server makes available.

const (
	Build     Resource = 1 + iota // build
	Invite                        // invite
	Image                         // image
	Namespace                     // namespace
	Object                        // object
	Variable                      // variable
	Key                           // key
	Cron                          // cron
	Webhook                       // webhook
)

func (Resource) String

func (i Resource) String() string

type Scope

type Scope []scopeItem

In the database token scopes are stored as a byte array of pairs, where the first item in the pair is the resource, and the second is the bitmask of permissions. For example the byte array

2, 3

would be the scope,

build:read,write

or as code,

scopeItem{
  Resource:   Build,
  Permission: Read|Write,
}

func NewScope

func NewScope() Scope

NewScope returns a new Scope for resource permissions to be added to.

func ScopeDiff

func ScopeDiff(a, b Scope) Scope

Diff returns the a new Scope that is the difference between Scopes a and b. You would typically check the length of the returned Scope to see if there was a difference like so,

if len(ScopeDiff(a, b)) > 0 {
    ...
}

func UnmarshalScope

func UnmarshalScope(s string) (Scope, error)

UnmarshalScope takes a space delimited scope string in the format of resource:permission and returns the unmarshalled Scope. An error is returned if the given scope string is invalid.

func (*Scope) Add

func (sc *Scope) Add(res Resource, perm Permission)

Add adds the given resource and permissions to the current scope. If the resource already exists in the current scope then the permissions are updated with the new permission.

func (*Scope) Scan

func (sc *Scope) Scan(val interface{}) error

Scan scans the underlying byte slice value of the given interface into the curent Scope if it is valid.

func (*Scope) Spread

func (sc *Scope) Spread() []string

Spread returns a slice of resource:permission strings.

func (*Scope) String

func (sc *Scope) String() string

String returns a space delimited string of all the resources and their respective permissions as a single string, for example,

build:read,write namespace:read variable:read,write,delete

func (*Scope) UnmarshalText

func (sc *Scope) UnmarshalText(b []byte) error

UnmarshalText unmarshals the given byte slice into the current Scope if it is valid. Under the hood this calls UnmarshalScope, so the byte slice is expected to be a space delimited string.

func (Scope) Value

func (sc Scope) Value() (driver.Value, error)

Value returns the raw byte pairs of a Scope that can be inserted into the database.

type Token

type Token struct {
	ID        int64         `db:"id"`
	UserID    int64         `db:"user_id"`
	AppID     sql.NullInt64 `db:"app_id"`
	Name      string        `db:"name"`
	Token     string        `db:"token"`
	Scope     Scope         `db:"scope"`
	CreatedAt time.Time     `db:"created_at"`
	UpdatedAt time.Time     `db:"updated_at"`

	User *user.User `db:"-"`
	App  *App       `db:"-"`
}

Token is the type that represents an OAuth Token in the database.

func TokenFromContext

func TokenFromContext(ctx context.Context) (*Token, bool)

TokenFromContext returns the Token model from the given context, if any.

func (*Token) Bind

func (t *Token) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or an App model.

func (*Token) Endpoint

func (t *Token) Endpoint(uri ...string) string

Endpoint returns the endpoint for the current Token with the appended URI parts.

func (*Token) IsZero

func (t *Token) IsZero() bool

IsZero implements the database.Model interface.

func (*Token) JSON

func (*Token) JSON(_ string) map[string]interface{}

JSON implements the database.Model interface. This is a stub method and returns an empty map.

func (*Token) Permissions

func (t *Token) Permissions() map[string]struct{}

Permissions turns the current Token's permission into a map. This will spread out the Token's scope into a space delimited string of resource:permission values. Each part of the space delimited string will be a key in the returned map, for example,

build:read,write namespace:read

would become the map,

map[string]struct{}{
    "build:read":     {},
    "build:write":    {},
    "namespace:read": {},
}

func (*Token) Primary

func (t *Token) Primary() (string, int64)

Primary implements the database.Model interface.

func (*Token) SetPrimary

func (t *Token) SetPrimary(id int64)

SetPrimary implements the database.Model interface.

func (*Token) Values

func (t *Token) Values() map[string]interface{}

Values implements the database.Model interface. This will return a map with the following values, user_id, app_id, name, token, scope, and updated_at.

type TokenForm

type TokenForm struct {
	Tokens *TokenStore `schema:"-"`
	Token  *Token      `schema:"-"`
	Name   string      `schema:"name"`
	Scope  []string    `schema:"scope[]"`
}

TokenForm is the type that represents the input data for creating a new Token.

func (TokenForm) Fields

func (f TokenForm) Fields() map[string]string

Fields returns a map of the Name, and Scope fields in the current TokenForm. The Scope field is serialized into a space delimited string of the scopes.

func (TokenForm) Validate

func (f TokenForm) Validate() error

Validate cheks to see if the Name field is present in the form, and if it is unique. This uniquess check is skipped if a Token is set on the form, and Name field matches that.

type TokenStore

type TokenStore struct {
	database.Store

	// User is the bound user.User model. If not nil this will bind the
	// user.User model to any Token models that are created. If not nil this
	// will append a WHERE clause on the user_id column for all SELECT queries
	// performed.
	User *user.User

	// App is the bound App model. If not nil this will bind the App model to
	// any Token models that are created. If not nil this will append a WHERE
	// clause on the app_id column for all SELECT queries performed.
	App *App
}

TokenStore is the type for creating and modifying Token models in the database.

func NewTokenStore

func NewTokenStore(db *sqlx.DB, mm ...database.Model) *TokenStore

NewTokenStore returns a new TokenStore for querying the oauth_tokens table. Each database passed to this function will be bound to the returned TokenStore.

func (*TokenStore) All

func (s *TokenStore) All(opts ...query.Option) ([]*Token, error)

All returns a slice Token models, applying each query.Option that is given. The database.Where option is applied to the bound User database and bound App database.

func (*TokenStore) Bind

func (s *TokenStore) Bind(mm ...database.Model)

Bind implements the database.Binder interface. This will only bind the model if it is a pointer to either a user.User model or an App model.

func (*TokenStore) Create

func (s *TokenStore) Create(name string, sc Scope) (*Token, error)

Create creates a new token with the given name, and scopes.

func (*TokenStore) Delete

func (s *TokenStore) Delete(ids ...int64) error

Delete deletes the token of the given ids from the database.

func (*TokenStore) Get

func (s *TokenStore) Get(opts ...query.Option) (*Token, error)

Get returns a single Token database, applying each query.Option that is given. The database.Where option is applied to the bound User database and bound App database.

func (*TokenStore) New

func (s *TokenStore) New() *Token

New returns a new Token binding any non-nil models to it from the current TokenStore.

func (*TokenStore) Reset

func (s *TokenStore) Reset(id int64) error

Reset generates a new token value for the Token of the given id.

func (*TokenStore) Revoke

func (s *TokenStore) Revoke(appId int64) error

Revoke deletes all of the tokens for the given appId.

func (*TokenStore) Update

func (s *TokenStore) Update(id int64, name string, sc Scope) error

Update updates a Token for the given id with the new name and scope.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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