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 /modules | |
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 'modules')
-rw-r--r-- | modules/auth/auth_form.go | 62 | ||||
-rw-r--r-- | modules/auth/oauth2/oauth2.go | 133 |
2 files changed, 159 insertions, 36 deletions
diff --git a/modules/auth/auth_form.go b/modules/auth/auth_form.go index 338be53457..8dc039835f 100644 --- a/modules/auth/auth_form.go +++ b/modules/auth/auth_form.go @@ -11,34 +11,40 @@ import ( // AuthenticationForm form for authentication type AuthenticationForm struct { - ID int64 - Type int `binding:"Range(2,6)"` - Name string `binding:"Required;MaxSize(30)"` - Host string - Port int - BindDN string - BindPassword string - UserBase string - UserDN string - AttributeUsername string - AttributeName string - AttributeSurname string - AttributeMail string - AttributesInBind bool - Filter string - AdminFilter string - IsActive bool - SMTPAuth string - SMTPHost string - SMTPPort int - AllowedDomains string - SecurityProtocol int `binding:"Range(0,2)"` - TLS bool - SkipVerify bool - PAMServiceName string - Oauth2Provider string - Oauth2Key string - Oauth2Secret string + ID int64 + Type int `binding:"Range(2,6)"` + Name string `binding:"Required;MaxSize(30)"` + Host string + Port int + BindDN string + BindPassword string + UserBase string + UserDN string + AttributeUsername string + AttributeName string + AttributeSurname string + AttributeMail string + AttributesInBind bool + Filter string + AdminFilter string + IsActive bool + SMTPAuth string + SMTPHost string + SMTPPort int + AllowedDomains string + SecurityProtocol int `binding:"Range(0,2)"` + TLS bool + SkipVerify bool + PAMServiceName string + Oauth2Provider string + Oauth2Key string + Oauth2Secret string + OpenIDConnectAutoDiscoveryURL string + Oauth2UseCustomURL bool + Oauth2TokenURL string + Oauth2AuthURL string + Oauth2ProfileURL string + Oauth2EmailURL string } // Validate validates fields 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 "" } |