Bladeren bron

Updated OAuth2

- added gitlab support
- minor code fixing
AY 4 jaren geleden
bovenliggende
commit
ef74431513
4 gewijzigde bestanden met toevoegingen van 151 en 7 verwijderingen
  1. 88 0
      mod/auth/oauth2/gitlab.go
  2. 24 5
      mod/auth/oauth2/oauth2.go
  3. 6 0
      mod/auth/oauth2/serviceSelector.go
  4. 33 2
      web/SystemAO/advance/oauth.html

+ 88 - 0
mod/auth/oauth2/gitlab.go

@@ -0,0 +1,88 @@
+package oauth2
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+
+	"golang.org/x/oauth2"
+)
+
+type GitlabField struct {
+	ID                             int           `json:"id"`
+	Name                           string        `json:"name"`
+	Username                       string        `json:"username"`
+	State                          string        `json:"state"`
+	AvatarURL                      string        `json:"avatar_url"`
+	WebURL                         string        `json:"web_url"`
+	CreatedAt                      time.Time     `json:"created_at"`
+	Bio                            string        `json:"bio"`
+	BioHTML                        string        `json:"bio_html"`
+	Location                       interface{}   `json:"location"`
+	PublicEmail                    string        `json:"public_email"`
+	Skype                          string        `json:"skype"`
+	Linkedin                       string        `json:"linkedin"`
+	Twitter                        string        `json:"twitter"`
+	WebsiteURL                     string        `json:"website_url"`
+	Organization                   interface{}   `json:"organization"`
+	JobTitle                       string        `json:"job_title"`
+	Pronouns                       interface{}   `json:"pronouns"`
+	Bot                            bool          `json:"bot"`
+	WorkInformation                interface{}   `json:"work_information"`
+	Followers                      int           `json:"followers"`
+	Following                      int           `json:"following"`
+	LastSignInAt                   time.Time     `json:"last_sign_in_at"`
+	ConfirmedAt                    time.Time     `json:"confirmed_at"`
+	LastActivityOn                 string        `json:"last_activity_on"`
+	Email                          string        `json:"email"`
+	ThemeID                        int           `json:"theme_id"`
+	ColorSchemeID                  int           `json:"color_scheme_id"`
+	ProjectsLimit                  int           `json:"projects_limit"`
+	CurrentSignInAt                time.Time     `json:"current_sign_in_at"`
+	Identities                     []interface{} `json:"identities"`
+	CanCreateGroup                 bool          `json:"can_create_group"`
+	CanCreateProject               bool          `json:"can_create_project"`
+	TwoFactorEnabled               bool          `json:"two_factor_enabled"`
+	External                       bool          `json:"external"`
+	PrivateProfile                 bool          `json:"private_profile"`
+	CommitEmail                    string        `json:"commit_email"`
+	SharedRunnersMinutesLimit      interface{}   `json:"shared_runners_minutes_limit"`
+	ExtraSharedRunnersMinutesLimit interface{}   `json:"extra_shared_runners_minutes_limit"`
+	IsAdmin                        bool          `json:"is_admin"`
+	Note                           interface{}   `json:"note"`
+	UsingLicenseSeat               bool          `json:"using_license_seat"`
+}
+
+func gitlabScope() []string {
+	return []string{"read_user api read_api"}
+}
+
+func gitlabEndpoint(server string) oauth2.Endpoint {
+	Endpoint := oauth2.Endpoint{
+		AuthURL:  server + "/oauth/authorize",
+		TokenURL: server + "/oauth/token",
+	}
+	return Endpoint
+}
+
+func gitlabUserInfo(accessToken string, server string) (string, error) {
+	response, err := http.Get(server + "/api/v4/user?access_token=" + accessToken)
+	if err != nil {
+		return "", err
+	}
+	defer response.Body.Close()
+	contents, err := ioutil.ReadAll(response.Body)
+	if err != nil {
+		return "", err
+	}
+	var data GitlabField
+	json.Unmarshal([]byte(contents), &data)
+
+	serverURL, err := url.Parse(server)
+	if err != nil {
+		return "", err
+	}
+	return data.Username + "@" + serverURL.Hostname(), err
+}

+ 24 - 5
mod/auth/oauth2/oauth2.go

@@ -27,6 +27,7 @@ type Config struct {
 	Enabled      bool   `json:"enabled"`
 	IDP          string `json:"idp"`
 	RedirectURL  string `json:"redirect_url"`
+	ServerURL    string `json:"server_url"`
 	ClientID     string `json:"client_id"`
 	ClientSecret string `json:"client_secret"`
 }
@@ -178,12 +179,14 @@ func (oh *OauthHandler) ReadConfig(w http.ResponseWriter, r *http.Request) {
 
 	idp := oh.readSingleConfig("idp")
 	redirecturl := oh.readSingleConfig("redirecturl")
+	serverurl := oh.readSingleConfig("serverurl")
 	clientid := oh.readSingleConfig("clientid")
 	clientsecret := oh.readSingleConfig("clientsecret")
 
 	config, err := json.Marshal(Config{
 		Enabled:      enabled,
 		IDP:          idp,
+		ServerURL:    serverurl,
 		RedirectURL:  redirecturl,
 		ClientID:     clientid,
 		ClientSecret: clientsecret,
@@ -201,7 +204,7 @@ func (oh *OauthHandler) ReadConfig(w http.ResponseWriter, r *http.Request) {
 func (oh *OauthHandler) WriteConfig(w http.ResponseWriter, r *http.Request) {
 	enabled, err := mv(r, "enabled", true)
 	if err != nil {
-		sendErrorResponse(w, "enabled field can't be empty'")
+		sendErrorResponse(w, "enabled field can't be empty")
 		return
 	}
 
@@ -215,34 +218,50 @@ func (oh *OauthHandler) WriteConfig(w http.ResponseWriter, r *http.Request) {
 	idp, err := mv(r, "idp", true)
 	if err != nil {
 		if showError {
-			sendErrorResponse(w, "idp field can't be empty'")
+			sendErrorResponse(w, "idp field can't be empty")
 			return
 		}
 	}
 	redirecturl, err := mv(r, "redirecturl", true)
 	if err != nil {
 		if showError {
-			sendErrorResponse(w, "redirecturl field can't be empty'")
+			sendErrorResponse(w, "redirecturl field can't be empty")
 			return
 		}
 	}
+	serverurl, err := mv(r, "serverurl", true)
+	if err != nil {
+		if showError {
+			if idp != "Gitlab" {
+				serverurl = ""
+			} else {
+				sendErrorResponse(w, "serverurl field can't be empty")
+				return
+			}
+		}
+	}
+	if idp != "Gitlab" {
+		serverurl = ""
+	}
+
 	clientid, err := mv(r, "clientid", true)
 	if err != nil {
 		if showError {
-			sendErrorResponse(w, "clientid field can't be empty'")
+			sendErrorResponse(w, "clientid field can't be empty")
 			return
 		}
 	}
 	clientsecret, err := mv(r, "clientsecret", true)
 	if err != nil {
 		if showError {
-			sendErrorResponse(w, "clientsecret field can't be empty'")
+			sendErrorResponse(w, "clientsecret field can't be empty")
 			return
 		}
 	}
 
 	oh.coredb.Write("oauth", "idp", idp)
 	oh.coredb.Write("oauth", "redirecturl", redirecturl)
+	oh.coredb.Write("oauth", "serverurl", serverurl)
 	oh.coredb.Write("oauth", "clientid", clientid)
 	oh.coredb.Write("oauth", "clientsecret", clientsecret)
 

+ 6 - 0
mod/auth/oauth2/serviceSelector.go

@@ -16,6 +16,8 @@ func getScope(coredb *db.Database) []string {
 		return githubScope()
 	} else if idp == "Microsoft" {
 		return microsoftScope()
+	} else if idp == "Gitlab" {
+		return gitlabScope()
 	}
 	return []string{}
 }
@@ -29,6 +31,8 @@ func getEndpoint(coredb *db.Database) oauth2.Endpoint {
 		return githubEndpoint()
 	} else if idp == "Microsoft" {
 		return microsoftEndpoint()
+	} else if idp == "Gitlab" {
+		return gitlabEndpoint(readSingleConfig("serverurl", coredb))
 	}
 	return oauth2.Endpoint{}
 }
@@ -42,6 +46,8 @@ func getUserInfo(accessToken string, coredb *db.Database) (string, error) {
 		return githubUserInfo(accessToken)
 	} else if idp == "Microsoft" {
 		return microsoftUserInfo(accessToken)
+	} else if idp == "Gitlab" {
+		return gitlabUserInfo(accessToken, readSingleConfig("serverurl", coredb))
 	}
 	return "", errors.New("Unauthorized")
 }

+ 33 - 2
web/SystemAO/advance/oauth.html

@@ -91,11 +91,17 @@
                 </div>
             </div>
             <div class="field">
-                <label>Redirect URL (you have to provide https://YOUR_DOMAIN/system/auth/oauth/authorize at the 3rd auth rely)</label>
+                <label>Redirect URL (you have to provide <span id="redirectspan">https://YOUR_DOMAIN/system/auth/oauth/authorize</span> at the 3rd auth rely)</label>
                 <div class="ui fluid input">
                     <input type="text" id="redirecturl" placeholder="https://YOUR_DOMAIN/">
                 </div>
             </div>
+            <div class="field" id="server" style="display: none;">
+                <label>Server URL</label>
+                <div class="ui fluid input">
+                    <input type="text" id="serverurl" placeholder="http://YOUR_DOMAIN/">
+                </div>
+            </div>
             <div class="field">
                 <label>Client ID</label>
                 <div class="ui fluid input">
@@ -119,6 +125,23 @@
         $(document).ready(function() {
             loadIdpList();
             read();
+            initPlaceholder();
+        });
+
+        $("#idp").change(function() {
+            if ($("#idp").val() == "Gitlab") {
+                $("#server").removeAttr("style");
+            } else {
+                $("#server").attr("style", "display:none;");
+            }
+        });
+
+        $("#redirecturl").on('input propertychange', function() {
+            if ($("#redirecturl").val() == "") {
+                $("#redirectspan").text(window.location.origin + "/system/auth/oauth/authorize");
+            } else {
+                $("#redirectspan").text($("#redirecturl").val() + "/system/auth/oauth/authorize");
+            }
         });
 
         function read() {
@@ -127,6 +150,7 @@
                     $("#enable").parent().checkbox("check")
                 }
                 $("#idp").parent().dropdown("set selected", data.idp);
+                $("#serverurl").val(data.server_url);
                 $("#redirecturl").val(data.redirect_url);
                 $("#clientid").val(data.client_id);
                 $("#clientsecret").val(data.client_secret);
@@ -140,6 +164,7 @@
                     redirecturl: $("#redirecturl").val(),
                     clientid: $("#clientid").val(),
                     clientsecret: $("#clientsecret").val(),
+                    serverurl: $("#serverurl").val()
                 })
                 .done(function(data) {
                     if (data.error != undefined) {
@@ -153,7 +178,7 @@
 
         function loadIdpList() {
             $("#idplist").html("");
-            var data = ["Google", "Microsoft", "Github"];
+            var data = ["Google", "Microsoft", "Github", "Gitlab"];
             if (data.error !== undefined) {
                 alert(data.error);
             } else {
@@ -164,6 +189,12 @@
             }
             $("#idplist").parent().dropdown();
         }
+
+        function initPlaceholder() {
+            $("#redirectspan").text(window.location.origin + "/system/auth/oauth/authorize");
+            $("#redirecturl").attr("placeholder", window.location.origin);
+            $("#serverurl").attr("placeholder", "https://gitlab.com");
+        }
     </script>
 </body>