github.com/zak-blake/goa@v1.4.1/client/signers.go (about)

     1  package client
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  )
     7  
     8  type (
     9  	// Signer is the common interface implemented by all signers.
    10  	Signer interface {
    11  		// Sign adds required headers, cookies etc.
    12  		Sign(*http.Request) error
    13  	}
    14  
    15  	// BasicSigner implements basic auth.
    16  	BasicSigner struct {
    17  		// Username is the basic auth user.
    18  		Username string
    19  		// Password is err guess what? the basic auth password.
    20  		Password string
    21  	}
    22  
    23  	// APIKeySigner implements API Key auth.
    24  	APIKeySigner struct {
    25  		// SignQuery indicates whether to set the API key in the URL query with key KeyName
    26  		// or whether to use a header with name KeyName.
    27  		SignQuery bool
    28  		// KeyName is the name of the HTTP header or query string that contains the API key.
    29  		KeyName string
    30  		// KeyValue stores the actual key.
    31  		KeyValue string
    32  		// Format is the format used to render the key, e.g. "Bearer %s"
    33  		Format string
    34  	}
    35  
    36  	// JWTSigner implements JSON Web Token auth.
    37  	JWTSigner struct {
    38  		// TokenSource is a JWT token source.
    39  		// See https://godoc.org/golang.org/x/oauth2/jwt#Config.TokenSource for an example
    40  		// of an implementation.
    41  		TokenSource TokenSource
    42  	}
    43  
    44  	// OAuth2Signer adds a authorization header to the request using the given OAuth2 token
    45  	// source to produce the header value.
    46  	OAuth2Signer struct {
    47  		// TokenSource is an OAuth2 access token source.
    48  		// See package golang/oauth2 and its subpackage for implementations of token
    49  		// sources.
    50  		TokenSource TokenSource
    51  	}
    52  
    53  	// Token is the interface to an OAuth2 token implementation.
    54  	// It can be implemented with https://godoc.org/golang.org/x/oauth2#Token.
    55  	Token interface {
    56  		// SetAuthHeader sets the Authorization header to r.
    57  		SetAuthHeader(r *http.Request)
    58  		// Valid reports whether Token can be used to properly sign requests.
    59  		Valid() bool
    60  	}
    61  
    62  	// A TokenSource is anything that can return a token.
    63  	TokenSource interface {
    64  		// Token returns a token or an error.
    65  		// Token must be safe for concurrent use by multiple goroutines.
    66  		// The returned Token must not be modified.
    67  		Token() (Token, error)
    68  	}
    69  
    70  	// StaticTokenSource implements a token source that always returns the same token.
    71  	StaticTokenSource struct {
    72  		StaticToken *StaticToken
    73  	}
    74  
    75  	// StaticToken implements a token that sets the auth header with a given static value.
    76  	StaticToken struct {
    77  		// Value used to set the auth header.
    78  		Value string
    79  		// OAuth type, defaults to "Bearer".
    80  		Type string
    81  	}
    82  )
    83  
    84  // Sign adds the basic auth header to the request.
    85  func (s *BasicSigner) Sign(req *http.Request) error {
    86  	if s.Username != "" && s.Password != "" {
    87  		req.SetBasicAuth(s.Username, s.Password)
    88  	}
    89  	return nil
    90  }
    91  
    92  // Sign adds the API key header to the request.
    93  func (s *APIKeySigner) Sign(req *http.Request) error {
    94  	if s.KeyName == "" {
    95  		s.KeyName = "Authorization"
    96  	}
    97  	if s.Format == "" {
    98  		s.Format = "Bearer %s"
    99  	}
   100  	name := s.KeyName
   101  	format := s.Format
   102  	val := fmt.Sprintf(format, s.KeyValue)
   103  	if s.SignQuery && val != "" {
   104  		query := req.URL.Query()
   105  		query.Set(name, val)
   106  		req.URL.RawQuery = query.Encode()
   107  	} else {
   108  		req.Header.Set(name, val)
   109  	}
   110  	return nil
   111  }
   112  
   113  // Sign adds the JWT auth header.
   114  func (s *JWTSigner) Sign(req *http.Request) error {
   115  	return signFromSource(s.TokenSource, req)
   116  }
   117  
   118  // Sign refreshes the access token if needed and adds the OAuth header.
   119  func (s *OAuth2Signer) Sign(req *http.Request) error {
   120  	return signFromSource(s.TokenSource, req)
   121  }
   122  
   123  // signFromSource generates a token using the given source and uses it to sign the request.
   124  func signFromSource(source TokenSource, req *http.Request) error {
   125  	token, err := source.Token()
   126  	if err != nil {
   127  		return err
   128  	}
   129  	if !token.Valid() {
   130  		return fmt.Errorf("token expired or invalid")
   131  	}
   132  	token.SetAuthHeader(req)
   133  	return nil
   134  }
   135  
   136  // Token returns the static token.
   137  func (s *StaticTokenSource) Token() (Token, error) {
   138  	return s.StaticToken, nil
   139  }
   140  
   141  // SetAuthHeader sets the Authorization header to r.
   142  func (t *StaticToken) SetAuthHeader(r *http.Request) {
   143  	typ := t.Type
   144  	if typ == "" {
   145  		typ = "Bearer"
   146  	}
   147  	r.Header.Set("Authorization", typ+" "+t.Value)
   148  }
   149  
   150  // Valid reports whether Token can be used to properly sign requests.
   151  func (t *StaticToken) Valid() bool { return true }