micro/auth/auth.go

161 lines
4.4 KiB
Go
Raw Normal View History

2019-11-25 12:30:26 +03:00
// Package auth provides authentication and authorization capability
package auth
2019-11-25 12:33:30 +03:00
import (
2020-03-04 12:54:52 +03:00
"context"
"errors"
2020-05-20 18:11:34 +03:00
"strings"
2019-11-25 12:33:30 +03:00
"time"
)
2020-05-20 13:59:01 +03:00
// BearerScheme used for Authorization header
const BearerScheme = "Bearer "
var (
2020-05-20 13:59:01 +03:00
// ErrInvalidToken is when the token provided is not valid
ErrInvalidToken = errors.New("invalid token provided")
2020-05-20 13:59:01 +03:00
// ErrForbidden is when a user does not have the necessary roles or scoeps to access a resource
ErrForbidden = errors.New("resource forbidden")
)
2019-11-25 12:30:26 +03:00
// Auth providers authentication and authorization
type Auth interface {
// Init the auth
Init(opts ...Option)
// Options set for auth
Options() Options
// Generate a new account
2020-04-01 19:20:02 +03:00
Generate(id string, opts ...GenerateOption) (*Account, error)
2020-05-20 13:59:01 +03:00
// Verify an account has access to a resource using the rules
2020-05-20 18:49:52 +03:00
Verify(acc *Account, res *Resource, opts ...VerifyOption) error
// Inspect a token
Inspect(token string) (*Account, error)
2020-05-20 13:59:01 +03:00
// Token generated using refresh token or credentials
2020-04-01 16:25:00 +03:00
Token(opts ...TokenOption) (*Token, error)
2020-05-20 13:59:01 +03:00
// Grant access to a resource
Grant(rule *Rule) error
// Revoke access to a resource
Revoke(rule *Rule) error
// Rules returns all the rules used to verify requests
Rules() ([]*Rule, error)
// String returns the name of the implementation
2020-02-16 22:36:45 +03:00
String() string
2019-12-18 00:27:05 +03:00
}
// Account provided by an auth provider
type Account struct {
2020-03-31 19:01:51 +03:00
// ID of the account e.g. email
ID string `json:"id"`
// Type of the account, e.g. service
Type string `json:"type"`
// Provider who issued the account
Provider string `json:"provider"`
// Roles associated with the Account
Roles []string `json:"roles"`
// Any other associated metadata
Metadata map[string]string `json:"metadata"`
// Scopes the account has access to
Scopes []string `json:"scopes"`
2020-03-31 20:17:01 +03:00
// Secret for the account, e.g. the password
Secret string `json:"secret"`
}
// HasScope returns a boolean indicating if the account has the given scope
2020-05-20 18:11:34 +03:00
func (a *Account) HasScope(scopes ...string) bool {
if a.Scopes == nil {
return false
}
for _, s := range a.Scopes {
2020-05-20 18:11:34 +03:00
if s == strings.Join(scopes, ".") {
return true
}
}
return false
}
2020-05-11 13:34:22 +03:00
// HasRole returns a boolean indicating if the account has the given role
func (a *Account) HasRole(role string) bool {
if a.Roles == nil {
return false
}
for _, r := range a.Roles {
if r == role {
return true
}
}
return false
}
// Token can be short or long lived
type Token struct {
2020-04-01 16:25:00 +03:00
// The token to be used for accessing resources
AccessToken string `json:"access_token"`
// RefreshToken to be used to generate a new token
RefreshToken string `json:"refresh_token"`
// Time of token creation
2019-11-25 12:30:26 +03:00
Created time.Time `json:"created"`
// Time of token expiry
2019-11-25 12:30:26 +03:00
Expiry time.Time `json:"expiry"`
}
2020-03-04 12:54:52 +03:00
2020-05-20 13:59:01 +03:00
// Expired returns a boolean indicating if the token needs to be refreshed
func (t *Token) Expired() bool {
return t.Expiry.Unix() < time.Now().Unix()
}
// Resource is an entity such as a user or
type Resource struct {
// Name of the resource, e.g. go.micro.service.notes
Name string `json:"name"`
// Type of resource, e.g. service
Type string `json:"type"`
// Endpoint resource e.g NotesService.Create
Endpoint string `json:"endpoint"`
}
// Access defines the type of access a rule grants
type Access int
2020-03-04 12:54:52 +03:00
const (
2020-05-20 13:59:01 +03:00
// AccessGranted to a resource
AccessGranted Access = iota
// AccessDenied to a resource
AccessDenied
2020-03-04 12:54:52 +03:00
)
2020-05-20 13:59:01 +03:00
// Rule is used to verify access to a resource
type Rule struct {
// ID of the rule, e.g. "public"
ID string
// Role the rule requires, a blank role indicates open to the public and * indicates the rule
// applies to any valid account
Role string
// Resource the rule applies to
Resource *Resource
// Access determines if the rule grants or denies access to the resource
Access Access
// Priority the rule should take when verifying a request, the higher the value the sooner the
// rule will be applied
Priority int32
}
type accountKey struct{}
2020-03-04 12:54:52 +03:00
// AccountFromContext gets the account from the context, which
// is set by the auth wrapper at the start of a call. If the account
// is not set, a nil account will be returned. The error is only returned
// when there was a problem retrieving an account
func AccountFromContext(ctx context.Context) (*Account, bool) {
acc, ok := ctx.Value(accountKey{}).(*Account)
return acc, ok
2020-03-04 12:54:52 +03:00
}
// ContextWithAccount sets the account in the context
func ContextWithAccount(ctx context.Context, account *Account) context.Context {
return context.WithValue(ctx, accountKey{}, account)
2020-03-04 12:54:52 +03:00
}