From 5b9a03a2619ed0c0a3b7120acda1e42868e82cf2 Mon Sep 17 00:00:00 2001 From: yubo Date: Fri, 23 Oct 2020 15:22:06 +0800 Subject: [PATCH] add OAuth2.0 callback/authorize V2 for UI (#353) * support openID2.0 * generate UUID if it's not set * change OAuth2 callback method to API style --- etc/rdb.yml | 2 ++ src/modules/rdb/config/yaml.go | 1 + src/modules/rdb/http/router.go | 3 ++ src/modules/rdb/http/router_auth.go | 45 +++++++++++++++++++++++++++++ src/modules/rdb/ssoc/sso.go | 9 +++++- 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/etc/rdb.yml b/etc/rdb.yml index 6b0bb2dd..afa15202 100644 --- a/etc/rdb.yml +++ b/etc/rdb.yml @@ -11,6 +11,7 @@ http: sso: enable: false ssoAddr: "http://10.1.2.3:8071" + # TODO: redirectURL: "http://10.1.2.3:8072/auth-callback" redirectURL: "http://10.1.2.3:8072/api/rdb/auth/callback" clientId: "" clientSecret: "" @@ -21,6 +22,7 @@ sso: phone: "phone" im: "" coverAttributes: false + stateExpiresIn: 300 tokens: - rdb-builtin-token diff --git a/src/modules/rdb/config/yaml.go b/src/modules/rdb/config/yaml.go index 730196c2..64cbbbdb 100644 --- a/src/modules/rdb/config/yaml.go +++ b/src/modules/rdb/config/yaml.go @@ -33,6 +33,7 @@ type ssoSection struct { ClientId string `yaml:"clientId"` ClientSecret string `yaml:"clientSecret"` ApiKey string `yaml:"apiKey"` + StateExpiresIn int `yaml:"stateExpiresIn"` CoverAttributes bool `yaml:"coverAttributes"` Attributes struct { Dispname string `yaml:"dispname"` diff --git a/src/modules/rdb/http/router.go b/src/modules/rdb/http/router.go index fa14fab9..8dd79217 100644 --- a/src/modules/rdb/http/router.go +++ b/src/modules/rdb/http/router.go @@ -21,6 +21,9 @@ func Config(r *gin.Engine) { notLogin.GET("/auth/authorize", authAuthorize) notLogin.GET("/auth/callback", authCallback) notLogin.GET("/auth/settings", authSettings) + + notLogin.GET("/auth/v2/authorize", authAuthorizeV2) + notLogin.GET("/auth/v2/callback", authCallbackV2) } hbs := r.Group("/api/hbs") diff --git a/src/modules/rdb/http/router_auth.go b/src/modules/rdb/http/router_auth.go index 8b3d542d..57480088 100644 --- a/src/modules/rdb/http/router_auth.go +++ b/src/modules/rdb/http/router_auth.go @@ -110,6 +110,28 @@ func authAuthorize(c *gin.Context) { } +type authRedirect struct { + Redirect string `json:"redirect"` +} + +func authAuthorizeV2(c *gin.Context) { + redirect := queryStr(c, "redirect", "/") + ret := &authRedirect{Redirect: redirect} + + username := cookieUsername(c) + if username != "" { // alread login + renderData(c, ret, nil) + return + } + + if config.Config.SSO.Enable { + ret.Redirect = ssoc.Authorize(redirect) + } else { + ret.Redirect = "/login" + } + renderData(c, ret, nil) +} + func authCallback(c *gin.Context) { code := queryStr(c, "code", "") state := queryStr(c, "state", "") @@ -127,6 +149,29 @@ func authCallback(c *gin.Context) { c.Redirect(302, redirect) } +func authCallbackV2(c *gin.Context) { + code := queryStr(c, "code", "") + state := queryStr(c, "state", "") + redirect := queryStr(c, "redirect", "") + + ret := &authRedirect{Redirect: redirect} + if code == "" && redirect != "" { + renderData(c, ret, nil) + return + } + + var user *models.User + var err error + ret.Redirect, user, err = ssoc.Callback(code, state) + if err != nil { + renderData(c, ret, err) + return + } + + writeCookieUser(c, user.UUID) + renderData(c, ret, nil) +} + func authSettings(c *gin.Context) { renderData(c, struct { Sso bool `json:"sso"` diff --git a/src/modules/rdb/ssoc/sso.go b/src/modules/rdb/ssoc/sso.go index 36cefd03..c51a4ee0 100644 --- a/src/modules/rdb/ssoc/sso.go +++ b/src/modules/rdb/ssoc/sso.go @@ -24,6 +24,7 @@ type ssoClient struct { config oauth2.Config apiKey string cache *cache.LRUExpireCache + stateExpiresIn time.Duration ssoAddr string callbackAddr string coverAttributes bool @@ -73,12 +74,18 @@ func InitSSO() { Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } cli.apiKey = cf.ApiKey + + if cf.StateExpiresIn == 0 { + cli.stateExpiresIn = time.Second * 60 + } else { + cli.stateExpiresIn = time.Second * time.Duration(cf.StateExpiresIn) + } } // Authorize return the sso authorize location with state func Authorize(redirect string) string { state := uuid.New().String() - cli.cache.Add(state, redirect, time.Second*60) + cli.cache.Add(state, redirect, cli.stateExpiresIn) return cli.config.AuthCodeURL(state) }