Documentation
¶
Overview ¶
Package oauth2 provides a middelware that introspects the auth token on behalf of PACE services and populate the request context with useful information when the token is valid, otherwise aborts the request.
Example ¶
r := mux.NewRouter()
middleware := Middleware{}
r.Use(middleware.Handler)
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
userid, _ := UserID(r.Context())
log.Printf("AUDIT: User %s does something", userid)
if HasScope(r.Context(), "dtc:codes:write") {
_, err := fmt.Fprintf(w, "User has scope.")
if err != nil {
panic(err)
}
return
}
_, err := fmt.Fprintf(w, "Your client may not have the right scopes to see the secret code")
if err != nil {
panic(err)
}
})
srv := &http.Server{
Handler: r,
Addr: "127.0.0.1:8000",
}
log.Fatal(srv.ListenAndServe())
Example (MultipleBackends) ¶
package main
import (
"context"
"fmt"
"net/http/httptest"
"github.com/pace/bricks/http/oauth2"
)
var _ oauth2.TokenIntrospecter = (*multiAuthBackends)(nil)
type multiAuthBackends []oauth2.TokenIntrospecter
func (b multiAuthBackends) IntrospectToken(ctx context.Context, token string) (resp *oauth2.IntrospectResponse, err error) {
for _, backend := range b {
resp, err = backend.IntrospectToken(ctx, token)
if resp != nil && err == nil {
return
}
}
return nil, oauth2.ErrInvalidToken
}
type authBackend [2]string
func (b *authBackend) IntrospectToken(ctx context.Context, token string) (*oauth2.IntrospectResponse, error) {
if b[1] == token {
return &oauth2.IntrospectResponse{
Active: true,
Backend: b,
}, nil
}
return nil, oauth2.ErrInvalidToken
}
func main() {
// In case you have multiple authorization backends, you can use the
// oauth2.Backend(context.Context) function to retrieve the backend that
// authorized the request. The actual value used for the backend depends on
// your implementation: you can use constants or pointers, like in this
// example.
authorizer := oauth2.NewAuthorizer(multiAuthBackends{
&authBackend{"A", "token-a"},
&authBackend{"B", "token-b"},
&authBackend{"C", "token-c"},
}, nil)
r := httptest.NewRequest("GET", "/some/endpoint", nil)
r.Header.Set("Authorization", "Bearer token-b")
if authorizer.CanAuthorizeRequest(r) {
ctx, ok := authorizer.Authorize(r, nil)
usedBackend, _ := oauth2.Backend(ctx)
fmt.Printf("%t %s", ok, usedBackend.(*authBackend)[0])
}
}
Output: true B
Index ¶
- Variables
- func Backend(ctx context.Context) (interface{}, bool)
- func BearerToken(ctx context.Context) (string, bool)deprecated
- func ClientID(ctx context.Context) (string, bool)
- func ContextTransfer(sourceCtx context.Context, targetCtx context.Context) context.Context
- func HasScope(ctx context.Context, scope Scope) bool
- func Request(r *http.Request) *http.Request
- func Scopes(ctx context.Context) []string
- func UserID(ctx context.Context) (string, bool)
- func WithBearerToken(ctx context.Context, bearerToken string) context.Contextdeprecated
- type Authorizer
- type Config
- type Flow
- type IntrospectResponse
- type Middlewaredeprecated
- type Scope
- type TokenIntrospecter
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrBadUpstreamResponse = errors.New("bad upstream response when introspecting token")
ErrBadUpstreamResponse the response from the server has the wrong format
var ErrInvalidToken = errors.New("user token is invalid")
ErrInvalidToken in case the token is not valid or expired
var ErrUpstreamConnection = errors.New("problem connecting to the introspection endpoint")
ErrUpstreamConnection connection issue
Functions ¶
func Backend ¶ added in v0.1.27
Backend returns the backend stored in the context. It identifies the authorization backend for the token.
func BearerToken
deprecated
func ContextTransfer ¶ added in v0.1.12
ContextTransfer sources the oauth2 token from the sourceCtx and returning a new context based on the targetCtx
func HasScope ¶
HasScope extracts an access token from context and checks if the permissions represented by the provided scope are included in the valid scope.
func WithBearerToken
deprecated
added in
v0.1.14
Deprecated: WithBearerToken was moved to the security package, because it's used by api key and oauth2 authorization. returns a new context with the given bearer token Use security.BearerToken() to retrieve the token. Use Request() to obtain a request with the Authorization header set accordingly.
Types ¶
type Authorizer ¶ added in v0.1.17
type Authorizer struct {
// contains filtered or unexported fields
}
Authorizer is an implementation of security.Authorizer for OAuth2 it uses introspection to get user data and can check the scope
func NewAuthorizer ¶ added in v0.1.17
func NewAuthorizer(introspector TokenIntrospecter, cfg *Config) *Authorizer
NewAuthorizer creates an Authorizer for a specific TokenIntrospecter This Authorizer does not check the scope
func (*Authorizer) Authorize ¶ added in v0.1.17
func (a *Authorizer) Authorize(r *http.Request, w http.ResponseWriter) (context.Context, bool)
Authorize authorizes a request with an introspection and validates the scope Success: returns context with the introspection result and true Error: writes all errors directly to response, returns unchanged context and false
func (*Authorizer) CanAuthorizeRequest ¶ added in v0.1.27
func (a *Authorizer) CanAuthorizeRequest(r *http.Request) bool
CanAuthorizeRequest returns true, if the request contains a token in the configured header, otherwise false
func (*Authorizer) WithScope ¶ added in v0.1.17
func (a *Authorizer) WithScope(tok string) *Authorizer
WithScope returns a new Authorizer with the same TokenIntrospecter and the same Config that also checks the scope of a request
type Config ¶ added in v0.1.17
type Config struct {
Description string
Implicit *Flow
Password *Flow
ClientCredentials *Flow
AuthorizationCode *Flow
}
Config contains the configuration from the api definition - currently not used
type Flow ¶ added in v0.1.17
type Flow struct {
AuthorizationURL string
TokenURL string
RefreshURL string
Scopes map[string]string
}
Flow is a part of the OAuth2 config from the security schema
type IntrospectResponse ¶ added in v0.1.11
type IntrospectResponse struct {
Active bool `json:"active"`
Scope string `json:"scope"`
ClientID string `json:"client_id"`
UserID string `json:"user_id"`
// Backend identifies the backend used for introspection. This attribute
// exists as a convenience if you have more than one authorization backend
// and need to distinguish between those.
Backend interface{} `json:"-"`
}
IntrospectResponse in case of a successful check of the oauth2 request
type Middleware
deprecated
type Middleware struct {
Backend TokenIntrospecter
}
Deprecated: Middleware holds data necessary for Oauth processing - Deprecated for generated apis, use the generated Authentication Backend of the API with oauth2.Authorizer
func NewMiddleware
deprecated
func NewMiddleware(backend TokenIntrospecter) *Middleware
Deprecated: NewMiddleware creates a new Oauth middleware - Deprecated for generated apis, use the generated AuthenticationBackend of the API with oauth2.Authorizer
type Scope ¶ added in v0.1.11
type Scope string
Scope represents an OAuth 2 access token scope
func (*Scope) IsIncludedIn ¶ added in v0.1.11
IsIncludedIn checks if the permissions of a scope s are also included in the provided scope t. This can be useful to check if a scope has all required permissions to access an endpoint.
type TokenIntrospecter ¶ added in v0.1.11
type TokenIntrospecter interface {
IntrospectToken(ctx context.Context, token string) (*IntrospectResponse, error)
}
TokenIntrospecter needs to be implemented for token lookup