summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoramWilander <jwawilander@gmail.com>2015-08-13 12:03:47 -0400
committerJoramWilander <jwawilander@gmail.com>2015-08-14 12:37:08 -0400
commite27db2ed63fd3c9c686c049a9b9049a907985ecc (patch)
tree701fcc97846e658e34c5d7ffada5b1d51a4920a9
parentb9aef9f2a6b90663cb7ba4ff9e42560c145b631d (diff)
downloadchat-e27db2ed63fd3c9c686c049a9b9049a907985ecc.tar.gz
chat-e27db2ed63fd3c9c686c049a9b9049a907985ecc.tar.bz2
chat-e27db2ed63fd3c9c686c049a9b9049a907985ecc.zip
initial server implementation for using google as a single-sign-on oauth service
-rw-r--r--api/user.go6
-rw-r--r--config/config.json10
-rw-r--r--model/gitlab.go57
-rw-r--r--model/google.go54
-rw-r--r--model/user.go68
-rw-r--r--utils/config.go1
-rw-r--r--web/web.go9
7 files changed, 146 insertions, 59 deletions
diff --git a/api/user.go b/api/user.go
index a42f81cf1..79f2201da 100644
--- a/api/user.go
+++ b/api/user.go
@@ -1314,9 +1314,15 @@ func GetAuthorizationCode(c *Context, w http.ResponseWriter, r *http.Request, te
clientId := utils.Cfg.SSOSettings[service].Id
endpoint := utils.Cfg.SSOSettings[service].AuthEndpoint
+ scope := utils.Cfg.SSOSettings[service].Scope
state := model.HashPassword(clientId)
authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri+"?team="+teamName) + "&state=" + url.QueryEscape(state)
+
+ if len(scope) > 0 {
+ authUrl += "&scope=" + utils.UrlEncode(scope)
+ }
+
http.Redirect(w, r, authUrl, http.StatusFound)
}
diff --git a/config/config.json b/config/config.json
index c446b517c..8405b9076 100644
--- a/config/config.json
+++ b/config/config.json
@@ -29,9 +29,19 @@
"Allow": false,
"Secret" : "",
"Id": "",
+ "Scope": "",
"AuthEndpoint": "",
"TokenEndpoint": "",
"UserApiEndpoint": ""
+ },
+ "google": {
+ "Allow": true,
+ "Secret": "hWN1kiPeyihN6nHr36j0oDqx",
+ "Id": "974585606220-ek5q66olpagb069pkg9ok0d7h8djeov6.apps.googleusercontent.com",
+ "Scope": "email profile",
+ "AuthEndpoint": "https://accounts.google.com/o/oauth2/auth",
+ "TokenEndpoint": "https://www.googleapis.com/oauth2/v3/token",
+ "UserApiEndpoint": "https://www.googleapis.com/plus/v1/people/me"
}
},
"SqlSettings": {
diff --git a/model/gitlab.go b/model/gitlab.go
new file mode 100644
index 000000000..9adcac189
--- /dev/null
+++ b/model/gitlab.go
@@ -0,0 +1,57 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+ "strconv"
+ "strings"
+)
+
+const (
+ USER_AUTH_SERVICE_GITLAB = "gitlab"
+)
+
+type GitLabUser struct {
+ Id int64 `json:"id"`
+ Username string `json:"username"`
+ Email string `json:"email"`
+ Name string `json:"name"`
+}
+
+func UserFromGitLabUser(glu *GitLabUser) *User {
+ user := &User{}
+ user.Username = glu.Username
+ splitName := strings.Split(glu.Name, " ")
+ if len(splitName) == 2 {
+ user.FirstName = splitName[0]
+ user.LastName = splitName[1]
+ } else if len(splitName) >= 2 {
+ user.FirstName = splitName[0]
+ user.LastName = strings.Join(splitName[1:], " ")
+ } else {
+ user.FirstName = glu.Name
+ }
+ user.Email = glu.Email
+ user.AuthData = strconv.FormatInt(glu.Id, 10)
+ user.AuthService = USER_AUTH_SERVICE_GITLAB
+
+ return user
+}
+
+func GitLabUserFromJson(data io.Reader) *GitLabUser {
+ decoder := json.NewDecoder(data)
+ var glu GitLabUser
+ err := decoder.Decode(&glu)
+ if err == nil {
+ return &glu
+ } else {
+ return nil
+ }
+}
+
+func (glu *GitLabUser) GetAuthData() string {
+ return strconv.FormatInt(glu.Id, 10)
+}
diff --git a/model/google.go b/model/google.go
new file mode 100644
index 000000000..bdb500704
--- /dev/null
+++ b/model/google.go
@@ -0,0 +1,54 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+)
+
+const (
+ USER_AUTH_SERVICE_GOOGLE = "google"
+)
+
+type GoogleUser struct {
+ Id string `json:"id"`
+ Nickname string `json:"nickname"`
+ Emails []map[string]string `json:"emails"`
+ Names map[string]string `json:"name"`
+}
+
+func UserFromGoogleUser(gu *GoogleUser) *User {
+ user := &User{}
+ user.Username = gu.Nickname
+ user.FirstName = gu.Names["givenName"]
+ user.LastName = gu.Names["familyName"]
+ user.Nickname = gu.Nickname
+
+ for _, e := range gu.Emails {
+ if e["type"] == "account" {
+ user.Email = e["value"]
+ }
+ }
+
+ user.AuthData = gu.Id
+ user.AuthService = USER_AUTH_SERVICE_GOOGLE
+
+ return user
+}
+
+func GoogleUserFromJson(data io.Reader) *GoogleUser {
+ decoder := json.NewDecoder(data)
+ var gu GoogleUser
+ err := decoder.Decode(&gu)
+ if err == nil {
+ return &gu
+ } else {
+ return nil
+ }
+}
+
+func (gu *GoogleUser) GetAuthData() string {
+ return gu.Id
+}
diff --git a/model/user.go b/model/user.go
index ed5161538..ebefa4762 100644
--- a/model/user.go
+++ b/model/user.go
@@ -8,24 +8,22 @@ import (
"encoding/json"
"io"
"regexp"
- "strconv"
"strings"
)
const (
- ROLE_ADMIN = "admin"
- ROLE_SYSTEM_ADMIN = "system_admin"
- ROLE_SYSTEM_SUPPORT = "system_support"
- USER_AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutes
- USER_OFFLINE_TIMEOUT = 1 * 60 * 1000 // 1 minute
- USER_OFFLINE = "offline"
- USER_AWAY = "away"
- USER_ONLINE = "online"
- USER_NOTIFY_ALL = "all"
- USER_NOTIFY_MENTION = "mention"
- USER_NOTIFY_NONE = "none"
- BOT_USERNAME = "valet"
- USER_AUTH_SERVICE_GITLAB = "gitlab"
+ ROLE_ADMIN = "admin"
+ ROLE_SYSTEM_ADMIN = "system_admin"
+ ROLE_SYSTEM_SUPPORT = "system_support"
+ USER_AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutes
+ USER_OFFLINE_TIMEOUT = 1 * 60 * 1000 // 1 minute
+ USER_OFFLINE = "offline"
+ USER_AWAY = "away"
+ USER_ONLINE = "online"
+ USER_NOTIFY_ALL = "all"
+ USER_NOTIFY_MENTION = "mention"
+ USER_NOTIFY_NONE = "none"
+ BOT_USERNAME = "valet"
)
type User struct {
@@ -54,13 +52,6 @@ type User struct {
FailedAttempts int `json:"failed_attempts"`
}
-type GitLabUser struct {
- Id int64 `json:"id"`
- Username string `json:"username"`
- Email string `json:"email"`
- Name string `json:"name"`
-}
-
// IsValid validates the user and returns an error if it isn't configured
// correctly.
func (u *User) IsValid() *AppError {
@@ -355,38 +346,3 @@ func IsUsernameValid(username string) bool {
return true
}
-
-func UserFromGitLabUser(glu *GitLabUser) *User {
- user := &User{}
- user.Username = glu.Username
- splitName := strings.Split(glu.Name, " ")
- if len(splitName) == 2 {
- user.FirstName = splitName[0]
- user.LastName = splitName[1]
- } else if len(splitName) >= 2 {
- user.FirstName = splitName[0]
- user.LastName = strings.Join(splitName[1:], " ")
- } else {
- user.FirstName = glu.Name
- }
- user.Email = glu.Email
- user.AuthData = strconv.FormatInt(glu.Id, 10)
- user.AuthService = USER_AUTH_SERVICE_GITLAB
-
- return user
-}
-
-func GitLabUserFromJson(data io.Reader) *GitLabUser {
- decoder := json.NewDecoder(data)
- var glu GitLabUser
- err := decoder.Decode(&glu)
- if err == nil {
- return &glu
- } else {
- return nil
- }
-}
-
-func (glu *GitLabUser) GetAuthData() string {
- return strconv.FormatInt(glu.Id, 10)
-}
diff --git a/utils/config.go b/utils/config.go
index 8d9dd11e0..a3944f670 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -37,6 +37,7 @@ type SSOSetting struct {
Allow bool
Secret string
Id string
+ Scope string
AuthEndpoint string
TokenEndpoint string
UserApiEndpoint string
diff --git a/web/web.go b/web/web.go
index 8b329c149..1acddb914 100644
--- a/web/web.go
+++ b/web/web.go
@@ -53,13 +53,13 @@ func InitWeb() {
mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/", api.AppHandler(login)).Methods("GET")
mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/login", api.AppHandler(login)).Methods("GET")
- // Bug in gorilla.mux pervents us from using regex here.
+ // Bug in gorilla.mux prevents us from using regex here.
mainrouter.Handle("/{team}/login/{service}", api.AppHandler(loginWithOAuth)).Methods("GET")
mainrouter.Handle("/login/{service:[A-Za-z]+}/complete", api.AppHandlerIndependent(loginCompleteOAuth)).Methods("GET")
mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/logout", api.AppHandler(logout)).Methods("GET")
mainrouter.Handle("/{team:[A-Za-z0-9-]+(__)?[A-Za-z0-9-]+}/reset_password", api.AppHandler(resetPassword)).Methods("GET")
- // Bug in gorilla.mux pervents us from using regex here.
+ // Bug in gorilla.mux prevents us from using regex here.
mainrouter.Handle("/{team}/channels/{channelname}", api.UserRequired(getChannel)).Methods("GET")
// Anything added here must have an _ in it so it does not conflict with team names
@@ -67,7 +67,7 @@ func InitWeb() {
mainrouter.Handle("/signup_user_complete/", api.AppHandlerIndependent(signupUserComplete)).Methods("GET")
mainrouter.Handle("/signup_team_confirm/", api.AppHandlerIndependent(signupTeamConfirm)).Methods("GET")
- // Bug in gorilla.mux pervents us from using regex here.
+ // Bug in gorilla.mux prevents us from using regex here.
mainrouter.Handle("/{team}/signup/{service}", api.AppHandler(signupWithOAuth)).Methods("GET")
mainrouter.Handle("/signup/{service:[A-Za-z]+}/complete", api.AppHandlerIndependent(signupCompleteOAuth)).Methods("GET")
@@ -532,6 +532,9 @@ func signupCompleteOAuth(c *api.Context, w http.ResponseWriter, r *http.Request)
if service == model.USER_AUTH_SERVICE_GITLAB {
glu := model.GitLabUserFromJson(body)
user = model.UserFromGitLabUser(glu)
+ } else if service == model.USER_AUTH_SERVICE_GOOGLE {
+ gu := model.GoogleUserFromJson(body)
+ user = model.UserFromGoogleUser(gu)
}
if user == nil {