10 type Credentials struct {
14 func NewCredentials() *Credentials {
15 return &Credentials{Tokens: []string{}}
18 func NewCredentialsFromHTTPRequest(r *http.Request) *Credentials {
20 c.LoadTokensFromHTTPRequest(r)
24 // EncodeTokenCookie accepts a token and returns a byte slice suitable
25 // for use as a cookie value, such that it will be decoded correctly
26 // by LoadTokensFromHTTPRequest.
27 var EncodeTokenCookie func([]byte) string = base64.URLEncoding.EncodeToString
29 // DecodeTokenCookie accepts a cookie value and returns the encoded
31 var DecodeTokenCookie func(string) ([]byte, error) = base64.URLEncoding.DecodeString
33 // LoadTokensFromHttpRequest loads all tokens it can find in the
34 // headers and query string of an http query.
35 func (a *Credentials) LoadTokensFromHTTPRequest(r *http.Request) {
36 // Load plain token from "Authorization: OAuth2 ..." header
37 // (typically used by smart API clients)
38 if toks := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(toks) == 2 && toks[0] == "OAuth2" {
39 a.Tokens = append(a.Tokens, toks[1])
42 // Load base64-encoded token from "Authorization: Basic ..."
43 // header (typically used by git via credential helper)
44 if _, password, ok := BasicAuth(r); ok {
45 a.Tokens = append(a.Tokens, password)
48 // Load tokens from query string. It's generally not a good
49 // idea to pass tokens around this way, but passing a narrowly
50 // scoped token is a reasonable way to implement "secret link
51 // to an object" in a generic way.
53 // ParseQuery always returns a non-nil map which might have
54 // valid parameters, even when a decoding error causes it to
55 // return a non-nil err. We ignore err; hopefully the caller
56 // will also need to parse the query string for
57 // application-specific purposes and will therefore
58 // find/report decoding errors in a suitable way.
59 qvalues, _ := url.ParseQuery(r.URL.RawQuery)
60 if val, ok := qvalues["api_token"]; ok {
61 a.Tokens = append(a.Tokens, val...)
64 a.loadTokenFromCookie(r)
66 // TODO: Load token from Rails session cookie (if Rails site
70 func (a *Credentials) loadTokenFromCookie(r *http.Request) {
71 cookie, err := r.Cookie("arvados_api_token")
72 if err != nil || len(cookie.Value) == 0 {
75 token, err := DecodeTokenCookie(cookie.Value)
79 a.Tokens = append(a.Tokens, string(token))
82 // TODO: LoadTokensFromHttpRequestBody(). We can't assume in
83 // LoadTokensFromHttpRequest() that [or how] we should read and parse
84 // the request body. This has to be requested explicitly by the