func saltedTokenProvider(local backend, remoteID string) rpc.TokenProvider {
return func(ctx context.Context) ([]string, error) {
var tokens []string
- incoming, ok := ctx.Value(auth.ContextKeyCredentials).(*auth.Credentials)
+ incoming, ok := auth.FromContext(ctx)
if !ok {
return nil, errors.New("no token provided")
}
case auth.ErrSalted:
tokens = append(tokens, token)
case auth.ErrObsoleteToken:
- ctx := context.WithValue(ctx, auth.ContextKeyCredentials, &auth.Credentials{Tokens: []string{token}})
+ ctx := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{token}})
aca, err := local.APIClientAuthorizationCurrent(ctx, arvados.GetOptions{})
if errStatus(err) == http.StatusUnauthorized {
// pass through unmodified
}
func provideIncomingToken(ctx context.Context) ([]string, error) {
- incoming, ok := ctx.Value(auth.ContextKeyCredentials).(*auth.Credentials)
+ incoming, ok := auth.FromContext(ctx)
if !ok {
return nil, errors.New("no token provided")
}
}
}
}
- ctx := req.Context()
- ctx = context.WithValue(ctx, auth.ContextKeyCredentials, creds)
+ ctx := auth.NewContext(req.Context(), creds)
ctx = arvados.ContextWithRequestID(ctx, req.Header.Get("X-Request-Id"))
logger.WithFields(logrus.Fields{
"apiEndpoint": endpoint,
"git.curoverse.com/arvados.git/sdk/go/arvados"
)
-type contextKey string
-
-const ContextKeyCredentials contextKey = "credentials"
-
type TokenProvider func(context.Context) ([]string, error)
type Conn struct {
if err != nil {
return err
} else if len(tokens) > 0 {
- ctx = context.WithValue(ctx, "Authorization", "Bearer "+tokens[0])
+ ctx = arvados.ContextWithAuthorization(ctx, "Bearer "+tokens[0])
} else {
// Use a non-empty auth string to ensure we override
// any default token set on aClient -- and to avoid
// having the remote prompt us to send a token by
// responding 401.
- ctx = context.WithValue(ctx, "Authorization", "Bearer -")
+ ctx = arvados.ContextWithAuthorization(ctx, "Bearer -")
}
// Encode opts to JSON and decode from there to a
// Do adds Authorization and X-Request-Id headers and then calls
// (*http.Client)Do().
func (c *Client) Do(req *http.Request) (*http.Response, error) {
- if auth, _ := req.Context().Value("Authorization").(string); auth != "" {
+ if auth, _ := req.Context().Value(contextKeyAuthorization{}).(string); auth != "" {
req.Header.Add("Authorization", auth)
} else if c.AuthToken != "" {
req.Header.Add("Authorization", "OAuth2 "+c.AuthToken)
}
if req.Header.Get("X-Request-Id") == "" {
- reqid, _ := req.Context().Value(contextKeyRequestID).(string)
+ reqid, _ := req.Context().Value(contextKeyRequestID{}).(string)
if reqid == "" {
- reqid, _ = c.context().Value(contextKeyRequestID).(string)
+ reqid, _ = c.context().Value(contextKeyRequestID{}).(string)
}
if reqid == "" {
reqid = reqIDGen.Next()
"context"
)
-type contextKey string
-
-var contextKeyRequestID contextKey = "X-Request-Id"
+type contextKeyRequestID struct{}
+type contextKeyAuthorization struct{}
func ContextWithRequestID(ctx context.Context, reqid string) context.Context {
- return context.WithValue(ctx, contextKeyRequestID, reqid)
+ return context.WithValue(ctx, contextKeyRequestID{}, reqid)
+}
+
+// ContextWithAuthorization returns a child context that (when used
+// with (*Client)RequestAndDecodeContext) sends the given
+// Authorization header value instead of the Client's default
+// AuthToken.
+func ContextWithAuthorization(ctx context.Context, value string) context.Context {
+ return context.WithValue(ctx, contextKeyAuthorization{}, value)
}
package auth
import (
+ "context"
"encoding/base64"
"net/http"
"net/url"
return &Credentials{Tokens: []string{}}
}
+func NewContext(ctx context.Context, c *Credentials) context.Context {
+ return context.WithValue(ctx, contextKeyCredentials{}, c)
+}
+
+func FromContext(ctx context.Context) (*Credentials, bool) {
+ c, ok := ctx.Value(contextKeyCredentials{}).(*Credentials)
+ return c, ok
+}
+
func CredentialsFromRequest(r *http.Request) *Credentials {
- if c, ok := r.Context().Value(ContextKeyCredentials).(*Credentials); ok {
+ if c, ok := FromContext(r.Context()); ok {
// preloaded by middleware
return c
}
"net/http"
)
-type contextKey string
-
-var ContextKeyCredentials contextKey = "credentials"
+type contextKeyCredentials struct{}
// LoadToken wraps the next handler, adding credentials to the request
// context so subsequent handlers can access them efficiently via
// CredentialsFromRequest.
func LoadToken(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if _, ok := r.Context().Value(ContextKeyCredentials).(*Credentials); !ok {
- r = r.WithContext(context.WithValue(r.Context(), ContextKeyCredentials, CredentialsFromRequest(r)))
+ if _, ok := r.Context().Value(contextKeyCredentials{}).(*Credentials); !ok {
+ r = r.WithContext(context.WithValue(r.Context(), contextKeyCredentials{}, CredentialsFromRequest(r)))
}
next.ServeHTTP(w, r)
})