token

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 16, 2024 License: AGPL-3.0, MIT Imports: 14 Imported by: 0

Documentation

Overview

Package token provides authentication strategy, to authenticate HTTP requests based on token.

Example
authFunc := AuthenticateFunc(func(ctx context.Context, r *http.Request, token string) (auth.Info, time.Time, error) {
	if token == "90d64460d14870c08c81352a05dedd3465940a7" {
		// hit DB or authorization server to retrieve information about the access token.
		info := auth.NewDefaultUser("example", "1", nil, nil)
		exp := time.Now().Add(time.Hour)
		WithNamedScopes(info, "example:read")
		return info, exp, nil
	}
	return nil, time.Time{}, fmt.Errorf("Invalid user token")
})

cache := libcache.LRU.New(0)
scope := NewScope("example:read", "/example", "GET")
opt := SetScopes(scope)
strategy := New(authFunc, cache, opt)

r, _ := http.NewRequest("PUT", "/eample", nil)
r.Header.Set("Authorization", "Bearer 90d64460d14870c08c81352a05dedd3465940a7")

_, err := strategy.Authenticate(r.Context(), r)
fmt.Println(err)
Output:

strategies/token: The access token scopes do not grant access to the requested resource

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrTokenScopes is returned by token scopes verification when,
	// token scopes do not grant access to the requested resource.
	ErrTokenScopes = errors.New("strategies/token: The access token scopes do not grant access to the requested resource")

	// ErrInvalidToken indicate a hit of an invalid token format.
	// And it's returned by Token Parser.
	ErrInvalidToken = errors.New("strategies/token: Invalid token")

	// ErrTokenNotFound is returned by authenticating functions for token strategies,
	// when token not found in their store.
	ErrTokenNotFound = errors.New("strategies/token: Token does not exists")

	// ErrNOOP is a soft error similar to EOF,
	// returned by NoOpAuthenticate function to indicate there no op,
	// and signal the caller to unauthenticate the request.
	ErrNOOP = errors.New("strategies/token: NOOP")
)

Functions

func GetNamedScopes

func GetNamedScopes(info auth.Info) (scopes []string)

GetNamedScopes return's all named scopes from auth.info. Typically used internally when token scopes verification enabled.

func New

func New(fn AuthenticateFunc, ac auth.Cache, opts ...auth.Option) auth.Strategy

New return new token strategy that caches the invocation result of authenticate function.

Example
authFunc := AuthenticateFunc(func(ctx context.Context, r *http.Request, token string) (auth.Info, time.Time, error) {
	fmt.Print("authFunc called ")
	if token == "90d64460d14870c08c81352a05dedd3465940a7" {
		return auth.NewDefaultUser("example", "1", nil, nil), time.Now().Add(time.Hour), nil
	}
	return nil, time.Time{}, fmt.Errorf("Invalid user token")
})

cache := libcache.LRU.New(0)
strategy := New(authFunc, cache)

r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", "Bearer 90d64460d14870c08c81352a05dedd3465940a7")

// first request when authentication decision not cached
info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(err, info.GetID())

// second request where authentication decision cached and authFunc will not be called
info, err = strategy.Authenticate(r.Context(), r)
fmt.Println(err, info.GetID())
Output:

authFunc called <nil> 1
<nil> 1
Example (Apikey)
r, _ := http.NewRequest("GET", "/something?api_key=token", nil)
parser := QueryParser("api_key")
opt := SetParser(parser)

authFunc := AuthenticateFunc(func(ctx context.Context, r *http.Request, token string) (auth.Info, time.Time, error) {
	if token == "token" {
		return auth.NewDefaultUser("example", "1", nil, nil), time.Now().Add(time.Hour), nil
	}
	return nil, time.Time{}, fmt.Errorf("Invalid user token")
})

cache := libcache.LRU.New(0)
strategy := New(authFunc, cache, opt)

info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(info.GetUserName(), err)
Output:

example <nil>

func NewStatic

func NewStatic(tokens map[string]auth.Info, opts ...auth.Option) auth.Strategy

NewStatic returns static auth.Strategy, populated from a map.

Example
strategy := NewStatic(map[string]auth.Info{
	"90d64460d14870c08c81352a05dedd3465940a7": auth.NewDefaultUser("example", "1", nil, nil),
})
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", "Bearer 90d64460d14870c08c81352a05dedd3465940a7")
info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(err, info.GetID())
Output:

<nil> 1
Example (Apikey)
r, _ := http.NewRequest("GET", "/something?api_key=token", nil)
parser := QueryParser("api_key")
opt := SetParser(parser)
tokens := map[string]auth.Info{
	"token": auth.NewDefaultUser("example", "1", nil, nil),
}
strategy := NewStatic(tokens, opt)
info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(info.GetUserName(), err)
Output:

example <nil>

func NewStaticFromFile

func NewStaticFromFile(path string, opts ...auth.Option) (auth.Strategy, error)

NewStaticFromFile returns static auth.Strategy, populated from a CSV file. The CSV file must contain records in one of following formats basic record: `token,username,userid` intermediate record: `token,username,userid,"group1,group2"` full record: `token,username,userid,"group1,group2","extension=1,example=2"`

Example
strategy, _ := NewStaticFromFile("testdata/valid.csv")
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", "Bearer testUserToken")
info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(err, info.GetID())
Output:

<nil> 1

func NoOpAuthenticate

func NoOpAuthenticate(ctx context.Context, r *http.Request, token string) (auth.Info, time.Time, error)

NoOpAuthenticate implements AuthenticateFunc, it return nil, time.Time{}, ErrNOOP, commonly used when token refreshed/mangaed directly using cache or Append function, and there is no need to parse token and authenticate request.

Example
cache := libcache.LRU.New(0)
strategy := New(NoOpAuthenticate, cache)

// user verified and add the user token to strategy using append or cache
cache.Store("token", auth.NewDefaultUser("example", "1", nil, nil))

// first request where authentication decision added to cached
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", "Bearer token")
info, err := strategy.Authenticate(r.Context(), r)
fmt.Println(err, info.GetID())
Output:

<nil> 1

func SetHash

func SetHash(h crypto.Hash, key []byte) auth.Option

SetHash apply token hashing based on HMAC with h and key, To prevent precomputation and length extension attacks, and to mitigates hash map DOS attacks via collisions.

func SetParser

func SetParser(p Parser) auth.Option

SetParser sets the strategy token parser.

func SetScopes

func SetScopes(scopes ...Scope) auth.Option

SetScopes sets the scopes to be used when verifying user access token.

func SetType deprecated

func SetType(t Type) auth.Option

SetType sets the authentication token type or scheme, used for HTTP WWW-Authenticate header.

Deprecated: No longer used.

func WithNamedScopes

func WithNamedScopes(info auth.Info, scopes ...string)

WithNamedScopes add all the provided named scopes to the provided auth.info. Typically used when token scopes verification enabled and need to add token scopes to the auth info.

token.WithNamedScopes(info, "read:repo", "read:user")

Types

type AuthenticateFunc

type AuthenticateFunc func(ctx context.Context, r *http.Request, token string) (auth.Info, time.Time, error)

AuthenticateFunc declare function signature to authenticate request using token. Any function that has the appropriate signature can be registered to the token strategy. AuthenticateFunc must return authenticated user info and token expiry time, otherwise error.

type Parser

type Parser interface {
	Token(r *http.Request) (string, error)
}

Parser parse and extract token from incoming HTTP request.

func AuthorizationParser

func AuthorizationParser(key string) Parser

AuthorizationParser return a token parser, where token extracted form Authorization header.

Example
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set("Authorization", "Bearer token")
parser := AuthorizationParser("Bearer")
token, err := parser.Token(r)
fmt.Println(token, err)
Output:

token <nil>

func CookieParser

func CookieParser(key string) Parser

CookieParser return a token parser, where token extracted form HTTP Cookie.

Example
name := "api_key"
r, _ := http.NewRequest("GET", "/", nil)
cookie := &http.Cookie{Name: name, Value: "token"}
r.AddCookie(cookie)
parser := CookieParser(name)
token, err := parser.Token(r)
fmt.Println(token, err)
Output:

token <nil>

func JSONBodyParser

func JSONBodyParser(key string) Parser

JSONBodyParser return a token parser, where token extracted extracted form request body.

func QueryParser

func QueryParser(key string) Parser

QueryParser return a token parser, where token extracted form HTTP query string.

Example
r, _ := http.NewRequest("GET", "/something?api_key=token", nil)
parser := QueryParser("api_key")
token, err := parser.Token(r)
fmt.Println(token, err)
Output:

token <nil>

func XHeaderParser

func XHeaderParser(header string) Parser

XHeaderParser return a token parser, where token extracted form "X-" header.

Example
header := "X-API-TOKE"
r, _ := http.NewRequest("GET", "/", nil)
r.Header.Set(header, "token")
parser := XHeaderParser(header)
token, err := parser.Token(r)
fmt.Println(token, err)
Output:

token <nil>

type Scope

type Scope interface {
	// Name return's scope name.
	GetName() string
	// Verify is called after the user authenticated to verify the user token,
	// grants access to the requested resource/endpoint.
	Verify(ctx context.Context, r *http.Request, info auth.Info, token string) (ok bool)
}

Scope provide a way to manage permissions to protected resources.

Scope is not an authorization alternative and should be only used to limit the access token.

func NewScope

func NewScope(name, endpoint, method string) Scope

NewScope return's a new scope instance. the returned scope verify the request by matching the scope endpoint to the request path and the scope method to the request method.

The endpoint and method parameters will be passed to regexp.MustCompile to get a Regexp object to be used later in verification.

Example:

token.NewScope("admin.write","/admin|/system","POST|PUT")
token.NewScope("read:repo","/repo","GET")

type Type

type Type string

Type is Authentication token type or scheme. A common type is Bearer.

const (
	// Bearer Authentication token type or scheme.
	Bearer Type = "Bearer"
	// APIKey Authentication token type or scheme.
	APIKey Type = "ApiKey"
)

Jump to

Keyboard shortcuts

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