mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 07:23:05 +00:00 
			
		
		
		
	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
This commit is contained in:
		
				
					committed by
					
						 Lunny Xiao
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							2368bbb672
						
					
				
				
					commit
					950f2e2074
				
			
							
								
								
									
										163
									
								
								vendor/github.com/mrjones/oauth/provider.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/mrjones/oauth/provider.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user