gopkg.in/raphael/goa.v1@v1.4.2/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 }