Skip to content

Commit

Permalink
gitlab: use /oauth/userinfo and respect GITLAB_URL
Browse files Browse the repository at this point in the history
  • Loading branch information
gartnera authored and Alex Gartner committed Dec 9, 2019
1 parent 72f342f commit 545611a
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 237 deletions.
155 changes: 70 additions & 85 deletions oauth2/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,102 +5,87 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"

"github.com/tarent/loginsrv/model"
)

var gitlabAPI = "https://gitlab.com/api/v4"
const defaultGitlabURL = "https://gitlab.com"

func init() {
RegisterProvider(providerGitlab)
gitlabURL, ok := os.LookupEnv("GITLAB_URL")
if !ok {
gitlabURL = defaultGitlabURL
}
provider := MakeGitlabProvider(gitlabURL)
RegisterProvider(provider)
}

// GitlabUser is used for parsing the gitlab response
type GitlabUser struct {
Username string `json:"username,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
// GitlabUserInfo is used for parsing the gitlab response
type GitlabUserInfo struct {
model.UserInfo
Sub string `json:"nickname"`
}

type GitlabGroup struct {
FullPath string `json:"full_path,omitempty"`
func (i GitlabUserInfo) toUserInfo() model.UserInfo {
res := model.UserInfo{
Sub: i.Sub,
Picture: i.Picture,
Name: i.Name,
Email: i.Email,
Origin: "gitlab",
Expiry: i.Expiry,
Refreshes: i.Refreshes,
Groups: i.Groups,
}

email := i.Email
emailComponents := strings.Split(email, "@")
if len(emailComponents) == 2 {
res.Domain = emailComponents[1]
}
return res
}

var providerGitlab = Provider{
Name: "gitlab",
AuthURL: "https://gitlab.com/oauth/authorize",
TokenURL: "https://gitlab.com/oauth/token",
GetUserInfo: func(token TokenInfo) (model.UserInfo, string, error) {
gu := GitlabUser{}
url := fmt.Sprintf("%v/user?access_token=%v", gitlabAPI, token.AccessToken)

var respUser *http.Response
respUser, err := http.Get(url)
if err != nil {
return model.UserInfo{}, "", err
}
defer respUser.Body.Close()

if !strings.Contains(respUser.Header.Get("Content-Type"), "application/json") {
return model.UserInfo{}, "", fmt.Errorf("wrong content-type on gitlab get user info: %v", respUser.Header.Get("Content-Type"))
}

if respUser.StatusCode != 200 {
return model.UserInfo{}, "", fmt.Errorf("got http status %v on gitlab get user info", respUser.StatusCode)
}

b, err := ioutil.ReadAll(respUser.Body)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error reading gitlab get user info: %v", err)
}

err = json.Unmarshal(b, &gu)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error parsing gitlab get user info: %v", err)
}

gg := []*GitlabGroup{}
url = fmt.Sprintf("%v/groups?access_token=%v", gitlabAPI, token.AccessToken)

var respGroup *http.Response
respGroup, err = http.Get(url)
if err != nil {
return model.UserInfo{}, "", err
}
defer respGroup.Body.Close()

if !strings.Contains(respGroup.Header.Get("Content-Type"), "application/json") {
return model.UserInfo{}, "", fmt.Errorf("wrong content-type on gitlab get groups info: %v", respGroup.Header.Get("Content-Type"))
}

if respGroup.StatusCode != 200 {
return model.UserInfo{}, "", fmt.Errorf("got http status %v on gitlab get groups info", respGroup.StatusCode)
}

g, err := ioutil.ReadAll(respGroup.Body)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error reading gitlab get groups info: %v", err)
}

err = json.Unmarshal(g, &gg)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error parsing gitlab get groups info: %v", err)
}

groups := make([]string, len(gg))
for i := 0; i < len(gg); i++ {
groups[i] = gg[i].FullPath
}

return model.UserInfo{
Sub: gu.Username,
Picture: gu.AvatarURL,
Name: gu.Name,
Email: gu.Email,
Groups: groups,
Origin: "gitlab",
}, `{"user":` + string(b) + `,"groups":` + string(g) + `}`, nil
},
// MakeGitlabProvider make's a gitlab provider with the given url
func MakeGitlabProvider(gitlabURL string) Provider {
return Provider{
Name: "gitlab",
AuthURL: gitlabURL + "/oauth/authorize",
TokenURL: gitlabURL + "/oauth/token",
DefaultScopes: "email openid",
GetUserInfo: func(token TokenInfo) (model.UserInfo, string, error) {
url := fmt.Sprintf("%s/oauth/userinfo?access_token=%v", gitlabURL, token.AccessToken)

var info GitlabUserInfo

var respUser *http.Response
respUser, err := http.Get(url)
if err != nil {
return model.UserInfo{}, "", err
}
defer respUser.Body.Close()

if !strings.Contains(respUser.Header.Get("Content-Type"), "application/json") {
return model.UserInfo{}, "", fmt.Errorf("wrong content-type on gitlab get user info: %v", respUser.Header.Get("Content-Type"))
}

if respUser.StatusCode != 200 {
return model.UserInfo{}, "", fmt.Errorf("got http status %v on gitlab get user info", respUser.StatusCode)
}

b, err := ioutil.ReadAll(respUser.Body)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error reading gitlab get user info: %v", err)
}

err = json.Unmarshal(b, &info)
if err != nil {
return model.UserInfo{}, "", fmt.Errorf("error parsing gitlab get user info: %v", err)
}

return info.toUserInfo(), "", nil
},
}
}
Loading

0 comments on commit 545611a

Please sign in to comment.