diff --git a/cmd/dashboard/controller/guest_page.go b/cmd/dashboard/controller/guest_page.go index e3351e9..3d6ab66 100644 --- a/cmd/dashboard/controller/guest_page.go +++ b/cmd/dashboard/controller/guest_page.go @@ -49,6 +49,9 @@ func (gp *guestPage) login(c *gin.Context) { } else if singleton.Conf.Oauth2.Type == model.ConfigTypeGitea { LoginType = "Gitea" RegistrationLink = fmt.Sprintf("%s/user/sign_up", singleton.Conf.Oauth2.Endpoint) + } else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare { + LoginType = "Cloudflare" + RegistrationLink = "https://dash.cloudflare.com/sign-up/teams" } c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/login", mygin.CommonEnvironment(c, gin.H{ "Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}), diff --git a/cmd/dashboard/controller/oauth2.go b/cmd/dashboard/controller/oauth2.go index 99e064f..75e5341 100644 --- a/cmd/dashboard/controller/oauth2.go +++ b/cmd/dashboard/controller/oauth2.go @@ -2,8 +2,10 @@ package controller import ( "context" + "encoding/json" "errors" "fmt" + "github.com/naiba/nezha/pkg/oidc/cloudflare" "net/http" "net/url" "strings" @@ -74,6 +76,17 @@ func (oa *oauth2controller) getCommonOauth2Config(c *gin.Context) *oauth2.Config }, RedirectURL: oa.getRedirectURL(c), } + } else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare { + return &oauth2.Config{ + ClientID: singleton.Conf.Oauth2.ClientID, + ClientSecret: singleton.Conf.Oauth2.ClientSecret, + Scopes: []string{"openid", "email", "profile", "groups"}, + Endpoint: oauth2.Endpoint{ + AuthURL: fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/authorization", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID), + TokenURL: fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/token", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID), + }, + RedirectURL: oa.getRedirectURL(c), + } } else { return &oauth2.Config{ ClientID: singleton.Conf.Oauth2.ClientID, @@ -155,6 +168,17 @@ func (oa *oauth2controller) callback(c *gin.Context) { if err == nil { user = model.NewUserFromGitea(u) } + } else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare { + client := oauth2Config.Client(context.Background(), otk) + resp, err := client.Get(fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/userinfo", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID)) + if err == nil { + defer resp.Body.Close() + var cloudflareUserInfo *cloudflare.UserInfo + if err := json.NewDecoder(resp.Body).Decode(&cloudflareUserInfo); err == nil { + user = cloudflareUserInfo.MapToNezhaUser() + } + } + } else { var client *GitHubAPI.Client oc := oauth2Config.Client(ctx, otk) diff --git a/model/config.go b/model/config.go index 90d65f5..9730c54 100644 --- a/model/config.go +++ b/model/config.go @@ -32,11 +32,12 @@ var DashboardThemes = map[string]string{ } const ( - ConfigTypeGitHub = "github" - ConfigTypeGitee = "gitee" - ConfigTypeGitlab = "gitlab" - ConfigTypeJihulab = "jihulab" - ConfigTypeGitea = "gitea" + ConfigTypeGitHub = "github" + ConfigTypeGitee = "gitee" + ConfigTypeGitlab = "gitlab" + ConfigTypeJihulab = "jihulab" + ConfigTypeGitea = "gitea" + ConfigTypeCloudflare = "cloudflare" ) const ( diff --git a/pkg/oidc/cloudflare/cloudflare.go b/pkg/oidc/cloudflare/cloudflare.go new file mode 100644 index 0000000..f7de13f --- /dev/null +++ b/pkg/oidc/cloudflare/cloudflare.go @@ -0,0 +1,22 @@ +package cloudflare + +import ( + "github.com/naiba/nezha/model" + "github.com/naiba/nezha/service/singleton" +) + +type UserInfo struct { + Sub string `json:"sub"` + Email string `json:"email"` + Name string `json:"name"` + Groups []string `json:"groups"` +} + +func (u UserInfo) MapToNezhaUser() model.User { + var user model.User + singleton.DB.Where("login = ?", u.Sub).First(&user) + user.Login = u.Sub + user.Email = u.Email + user.Name = u.Name + return user +}