diff options
author | Willem van Dreumel <willemvd@users.noreply.github.com> | 2017-05-01 15:26:53 +0200 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2017-05-01 21:26:53 +0800 |
commit | 950f2e207413551b868252a1bced6ce9263d16d4 (patch) | |
tree | b01a330af11c7f8b9e2d1461685d9afb2ae9e485 /vendor/github.com/mrjones/oauth/provider.go | |
parent | 2368bbb6727ea5497743c0fdade723b49693cb4c (diff) | |
download | gitea-950f2e207413551b868252a1bced6ce9263d16d4.tar.gz gitea-950f2e207413551b868252a1bced6ce9263d16d4.zip |
Additional OAuth2 providers (#1010)
* add google+
* sort signin oauth2 providers based on the name so order is always the same
* update auth tip for google+
* add gitlab provider
* add bitbucket provider (and some go fmt)
* add twitter provider
* add facebook provider
* add dropbox provider
* add openid connect provider incl. new format of tips section in "Add New Source"
* lower the amount of disk storage for each session to prevent issues while building cross platform (and disk overflow)
* imports according to goimport and code style
* make it possible to set custom urls to gitlab and github provider (only these could have a different host)
* split up oauth2 into multiple files
* small typo in comment
* fix indention
* fix indentation
* fix new line before external import
* fix layout of signin part
* update "broken" dependency
Diffstat (limited to 'vendor/github.com/mrjones/oauth/provider.go')
-rw-r--r-- | vendor/github.com/mrjones/oauth/provider.go | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/vendor/github.com/mrjones/oauth/provider.go b/vendor/github.com/mrjones/oauth/provider.go new file mode 100644 index 0000000000..3a37e38a1b --- /dev/null +++ b/vendor/github.com/mrjones/oauth/provider.go @@ -0,0 +1,163 @@ +package oauth + +import ( + "bytes" + "fmt" + "math" + "net/http" + "net/url" + "strconv" + "strings" +) + +// +// OAuth1 2-legged provider +// Contributed by https://github.com/jacobpgallagher +// + +// Provide an buffer reader which implements the Close() interface +type oauthBufferReader struct { + *bytes.Buffer +} + +// So that it implements the io.ReadCloser interface +func (m oauthBufferReader) Close() error { return nil } + +type ConsumerGetter func(key string, header map[string]string) (*Consumer, error) + +// Provider provides methods for a 2-legged Oauth1 provider +type Provider struct { + ConsumerGetter ConsumerGetter + + // For mocking + clock clock +} + +// NewProvider takes a function to get the consumer secret from a datastore. +// Returns a Provider +func NewProvider(secretGetter ConsumerGetter) *Provider { + provider := &Provider{ + secretGetter, + &defaultClock{}, + } + return provider +} + +// Combine a URL and Request to make the URL absolute +func makeURLAbs(url *url.URL, request *http.Request) { + if !url.IsAbs() { + url.Host = request.Host + if request.TLS != nil || request.Header.Get("X-Forwarded-Proto") == "https" { + url.Scheme = "https" + } else { + url.Scheme = "http" + } + } +} + +// IsAuthorized takes an *http.Request and returns a pointer to a string containing the consumer key, +// or nil if not authorized +func (provider *Provider) IsAuthorized(request *http.Request) (*string, error) { + var err error + var userParams map[string]string + + // start with the body/query params + userParams, err = parseBody(request) + if err != nil { + return nil, err + } + + // if the oauth params are in the Authorization header, grab them, and + // let them override what's in userParams + authHeader := request.Header.Get(HTTP_AUTH_HEADER) + if len(authHeader) > 6 && strings.EqualFold(OAUTH_HEADER, authHeader[0:6]) { + authHeader = authHeader[6:] + params := strings.Split(authHeader, ",") + for _, param := range params { + vals := strings.SplitN(param, "=", 2) + k := strings.Trim(vals[0], " ") + v := strings.Trim(strings.Trim(vals[1], "\""), " ") + if strings.HasPrefix(k, "oauth") { + userParams[k], err = url.QueryUnescape(v) + if err != nil { + return nil, err + } + } + } + } + + // pop the request's signature, it's not included in our signature + // calculation + oauthSignature, ok := userParams[SIGNATURE_PARAM] + if !ok { + return nil, fmt.Errorf("no oauth signature") + } + delete(userParams, SIGNATURE_PARAM) + + // get the oauth consumer key + consumerKey, ok := userParams[CONSUMER_KEY_PARAM] + if !ok || consumerKey == "" { + return nil, fmt.Errorf("no consumer key") + } + + // use it to create a consumer object + consumer, err := provider.ConsumerGetter(consumerKey, userParams) + if err != nil { + return nil, err + } + + // Make sure timestamp is no more than 10 digits + timestamp := userParams[TIMESTAMP_PARAM] + if len(timestamp) > 10 { + timestamp = timestamp[0:10] + } + + // Check the timestamp + if !consumer.serviceProvider.IgnoreTimestamp { + oauthTimeNumber, err := strconv.Atoi(timestamp) + if err != nil { + return nil, err + } + + if math.Abs(float64(int64(oauthTimeNumber)-provider.clock.Seconds())) > 5*60 { + return nil, fmt.Errorf("too much clock skew") + } + } + + // Include the query string params in the base string + if consumer.serviceProvider.SignQueryParams { + for k, v := range request.URL.Query() { + userParams[k] = strings.Join(v, "") + } + } + + // if our consumer supports bodyhash, check it + if consumer.serviceProvider.BodyHash { + bodyHash, err := calculateBodyHash(request, consumer.signer) + if err != nil { + return nil, err + } + + sentHash, ok := userParams[BODY_HASH_PARAM] + + if bodyHash == "" && ok { + return nil, fmt.Errorf("body_hash must not be set") + } else if sentHash != bodyHash { + return nil, fmt.Errorf("body_hash mismatch") + } + } + + allParams := NewOrderedParams() + for key, value := range userParams { + allParams.Add(key, value) + } + + makeURLAbs(request.URL, request) + baseString := consumer.requestString(request.Method, canonicalizeUrl(request.URL), allParams) + err = consumer.signer.Verify(baseString, oauthSignature) + if err != nil { + return nil, err + } + + return &consumerKey, nil +} |