oauth2

package
v0.4.22 Latest Latest
Warning

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

Go to latest
Published: Apr 12, 2024 License: MIT Imports: 9 Imported by: 0

README

OAuth2

Oauth2 middleware for http.

Environment based configuration

  • OAUTH2_URL default: "https://cp-1-prod.pacelink.net"
    • URL of the Oauth server that provides /oauth2/introspect
  • OAUTH2_CLIENT_ID
    • ID of the oauth2 client
  • OAUTH2_CLIENT_SECRET
    • Secret of the oauth2 client

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())
Output:

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

Examples

Constants

This section is empty.

Variables

View Source
var ErrBadUpstreamResponse = errors.New("bad upstream response when introspecting token")

ErrBadUpstreamResponse the response from the server has the wrong format

View Source
var ErrInvalidToken = errors.New("user token is invalid")

ErrInvalidToken in case the token is not valid or expired

View Source
var ErrUpstreamConnection = errors.New("problem connecting to the introspection endpoint")

ErrUpstreamConnection connection issue

Functions

func AddScope added in v0.4.6

func AddScope(ctx context.Context, scope string) context.Context

func AuthTime added in v0.4.21

func AuthTime(ctx context.Context) (int64, bool)

AuthTime returns the auth time stored in ctx as unix timestamp

func Backend added in v0.1.27

func Backend(ctx context.Context) (interface{}, bool)

Backend returns the backend stored in the context. It identifies the authorization backend for the token.

func BearerToken deprecated

func BearerToken(ctx context.Context) (string, bool)

Deprecated: BearerToken was moved to the security package, because it's used by apiKey and oauth2 authorization. BearerToken returns the bearer token stored in ctx

func ClientID

func ClientID(ctx context.Context) (string, bool)

ClientID returns the clientID stored in ctx

func ContextTransfer added in v0.1.12

func ContextTransfer(sourceCtx context.Context, targetCtx context.Context) context.Context

ContextTransfer sources the oauth2 token from the sourceCtx and returning a new context based on the targetCtx

func HasScope

func HasScope(ctx context.Context, scope Scope) bool

HasScope extracts an access token from context and checks if the permissions represented by the provided scope are included in the valid scope.

func Request

func Request(r *http.Request) *http.Request

Request adds Authorization token to r

func Scopes

func Scopes(ctx context.Context) []string

Scopes returns the scopes stored in ctx

func UserID

func UserID(ctx context.Context) (string, bool)

UserID returns the userID stored in ctx

func WithBearerToken deprecated added in v0.1.14

func WithBearerToken(ctx context.Context, bearerToken string) context.Context

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"`
	AuthTime int64  `json:"auth_time"`

	// 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

func (*Middleware) Handler

func (m *Middleware) Handler(next http.Handler) http.Handler

Handler will parse the bearer token, introspect it, and put the token and other relevant information back in the context.

type Scope added in v0.1.11

type Scope string

Scope represents an OAuth 2 access token scope

func (*Scope) Add added in v0.4.6

func (s *Scope) Add(scope string) Scope

func (*Scope) IsIncludedIn added in v0.1.11

func (s *Scope) IsIncludedIn(t Scope) bool

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

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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