diff options
Diffstat (limited to 'modules/auth/oauth2/oauth2.go')
-rw-r--r-- | modules/auth/oauth2/oauth2.go | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/modules/auth/oauth2/oauth2.go b/modules/auth/oauth2/oauth2.go index ca4cde73b6..4584c48db7 100644 --- a/modules/auth/oauth2/oauth2.go +++ b/modules/auth/oauth2/oauth2.go @@ -5,6 +5,7 @@ package oauth2 import ( + "math" "net/http" "os" "path/filepath" @@ -15,7 +16,14 @@ import ( "github.com/gorilla/sessions" "github.com/markbates/goth" "github.com/markbates/goth/gothic" + "github.com/markbates/goth/providers/bitbucket" + "github.com/markbates/goth/providers/dropbox" + "github.com/markbates/goth/providers/facebook" "github.com/markbates/goth/providers/github" + "github.com/markbates/goth/providers/gitlab" + "github.com/markbates/goth/providers/gplus" + "github.com/markbates/goth/providers/openidConnect" + "github.com/markbates/goth/providers/twitter" "github.com/satori/go.uuid" ) @@ -24,6 +32,14 @@ var ( providerHeaderKey = "gitea-oauth2-provider" ) +// CustomURLMapping describes the urls values to use when customizing OAuth2 provider URLs +type CustomURLMapping struct { + AuthURL string + TokenURL string + ProfileURL string + EmailURL string +} + // Init initialize the setup of the OAuth2 library func Init() { sessionDir := filepath.Join(setting.AppDataPath, "sessions", "oauth2") @@ -31,7 +47,15 @@ func Init() { log.Fatal(4, "Fail to create dir %s: %v", sessionDir, err) } - gothic.Store = sessions.NewFilesystemStore(sessionDir, []byte(sessionUsersStoreKey)) + store := sessions.NewFilesystemStore(sessionDir, []byte(sessionUsersStoreKey)) + // according to the Goth lib: + // set the maxLength of the cookies stored on the disk to a larger number to prevent issues with: + // securecookie: the value is too long + // when using OpenID Connect , since this can contain a large amount of extra information in the id_token + + // Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk + store.MaxLength(math.MaxInt16) + gothic.Store = store gothic.SetState = func(req *http.Request) string { return uuid.NewV4().String() @@ -74,12 +98,14 @@ func ProviderCallback(provider string, request *http.Request, response http.Resp } // RegisterProvider register a OAuth2 provider in goth lib -func RegisterProvider(providerName, providerType, clientID, clientSecret string) { - provider := createProvider(providerName, providerType, clientID, clientSecret) +func RegisterProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) error { + provider, err := createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL, customURLMapping) - if provider != nil { + if err == nil && provider != nil { goth.UseProviders(provider) } + + return err } // RemoveProvider removes the given OAuth2 provider from the goth lib @@ -88,20 +114,111 @@ func RemoveProvider(providerName string) { } // used to create different types of goth providers -func createProvider(providerName, providerType, clientID, clientSecret string) goth.Provider { +func createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) (goth.Provider, error) { callbackURL := setting.AppURL + "user/oauth2/" + providerName + "/callback" var provider goth.Provider + var err error switch providerType { + case "bitbucket": + provider = bitbucket.New(clientID, clientSecret, callbackURL, "account") + case "dropbox": + provider = dropbox.New(clientID, clientSecret, callbackURL) + case "facebook": + provider = facebook.New(clientID, clientSecret, callbackURL, "email") case "github": - provider = github.New(clientID, clientSecret, callbackURL, "user:email") + authURL := github.AuthURL + tokenURL := github.TokenURL + profileURL := github.ProfileURL + emailURL := github.EmailURL + if customURLMapping != nil { + if len(customURLMapping.AuthURL) > 0 { + authURL = customURLMapping.AuthURL + } + if len(customURLMapping.TokenURL) > 0 { + tokenURL = customURLMapping.TokenURL + } + if len(customURLMapping.ProfileURL) > 0 { + profileURL = customURLMapping.ProfileURL + } + if len(customURLMapping.EmailURL) > 0 { + emailURL = customURLMapping.EmailURL + } + } + provider = github.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL, emailURL) + case "gitlab": + authURL := gitlab.AuthURL + tokenURL := gitlab.TokenURL + profileURL := gitlab.ProfileURL + if customURLMapping != nil { + if len(customURLMapping.AuthURL) > 0 { + authURL = customURLMapping.AuthURL + } + if len(customURLMapping.TokenURL) > 0 { + tokenURL = customURLMapping.TokenURL + } + if len(customURLMapping.ProfileURL) > 0 { + profileURL = customURLMapping.ProfileURL + } + } + provider = gitlab.NewCustomisedURL(clientID, clientSecret, callbackURL, authURL, tokenURL, profileURL) + case "gplus": + provider = gplus.New(clientID, clientSecret, callbackURL, "email") + case "openidConnect": + if provider, err = openidConnect.New(clientID, clientSecret, callbackURL, openIDConnectAutoDiscoveryURL); err != nil { + log.Warn("Failed to create OpenID Connect Provider with name '%s' with url '%s': %v", providerName, openIDConnectAutoDiscoveryURL, err) + } + case "twitter": + provider = twitter.NewAuthenticate(clientID, clientSecret, callbackURL) } // always set the name if provider is created so we can support multiple setups of 1 provider - if provider != nil { + if err == nil && provider != nil { provider.SetName(providerName) } - return provider + return provider, err +} + +// GetDefaultTokenURL return the default token url for the given provider +func GetDefaultTokenURL(provider string) string { + switch provider { + case "github": + return github.TokenURL + case "gitlab": + return gitlab.TokenURL + } + return "" +} + +// GetDefaultAuthURL return the default authorize url for the given provider +func GetDefaultAuthURL(provider string) string { + switch provider { + case "github": + return github.AuthURL + case "gitlab": + return gitlab.AuthURL + } + return "" +} + +// GetDefaultProfileURL return the default profile url for the given provider +func GetDefaultProfileURL(provider string) string { + switch provider { + case "github": + return github.ProfileURL + case "gitlab": + return gitlab.ProfileURL + } + return "" +} + +// GetDefaultEmailURL return the default email url for the given provider +func GetDefaultEmailURL(provider string) string { + switch provider { + case "github": + return github.EmailURL + } + return "" } |