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
This commit is contained in:
parent
228ffcfbc9
commit
5b9a03a261
|
@ -11,6 +11,7 @@ http:
|
||||||
sso:
|
sso:
|
||||||
enable: false
|
enable: false
|
||||||
ssoAddr: "http://10.1.2.3:8071"
|
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"
|
redirectURL: "http://10.1.2.3:8072/api/rdb/auth/callback"
|
||||||
clientId: ""
|
clientId: ""
|
||||||
clientSecret: ""
|
clientSecret: ""
|
||||||
|
@ -21,6 +22,7 @@ sso:
|
||||||
phone: "phone"
|
phone: "phone"
|
||||||
im: ""
|
im: ""
|
||||||
coverAttributes: false
|
coverAttributes: false
|
||||||
|
stateExpiresIn: 300
|
||||||
|
|
||||||
tokens:
|
tokens:
|
||||||
- rdb-builtin-token
|
- rdb-builtin-token
|
||||||
|
|
|
@ -33,6 +33,7 @@ type ssoSection struct {
|
||||||
ClientId string `yaml:"clientId"`
|
ClientId string `yaml:"clientId"`
|
||||||
ClientSecret string `yaml:"clientSecret"`
|
ClientSecret string `yaml:"clientSecret"`
|
||||||
ApiKey string `yaml:"apiKey"`
|
ApiKey string `yaml:"apiKey"`
|
||||||
|
StateExpiresIn int `yaml:"stateExpiresIn"`
|
||||||
CoverAttributes bool `yaml:"coverAttributes"`
|
CoverAttributes bool `yaml:"coverAttributes"`
|
||||||
Attributes struct {
|
Attributes struct {
|
||||||
Dispname string `yaml:"dispname"`
|
Dispname string `yaml:"dispname"`
|
||||||
|
|
|
@ -21,6 +21,9 @@ func Config(r *gin.Engine) {
|
||||||
notLogin.GET("/auth/authorize", authAuthorize)
|
notLogin.GET("/auth/authorize", authAuthorize)
|
||||||
notLogin.GET("/auth/callback", authCallback)
|
notLogin.GET("/auth/callback", authCallback)
|
||||||
notLogin.GET("/auth/settings", authSettings)
|
notLogin.GET("/auth/settings", authSettings)
|
||||||
|
|
||||||
|
notLogin.GET("/auth/v2/authorize", authAuthorizeV2)
|
||||||
|
notLogin.GET("/auth/v2/callback", authCallbackV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
hbs := r.Group("/api/hbs")
|
hbs := r.Group("/api/hbs")
|
||||||
|
|
|
@ -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) {
|
func authCallback(c *gin.Context) {
|
||||||
code := queryStr(c, "code", "")
|
code := queryStr(c, "code", "")
|
||||||
state := queryStr(c, "state", "")
|
state := queryStr(c, "state", "")
|
||||||
|
@ -127,6 +149,29 @@ func authCallback(c *gin.Context) {
|
||||||
c.Redirect(302, redirect)
|
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) {
|
func authSettings(c *gin.Context) {
|
||||||
renderData(c, struct {
|
renderData(c, struct {
|
||||||
Sso bool `json:"sso"`
|
Sso bool `json:"sso"`
|
||||||
|
|
|
@ -24,6 +24,7 @@ type ssoClient struct {
|
||||||
config oauth2.Config
|
config oauth2.Config
|
||||||
apiKey string
|
apiKey string
|
||||||
cache *cache.LRUExpireCache
|
cache *cache.LRUExpireCache
|
||||||
|
stateExpiresIn time.Duration
|
||||||
ssoAddr string
|
ssoAddr string
|
||||||
callbackAddr string
|
callbackAddr string
|
||||||
coverAttributes bool
|
coverAttributes bool
|
||||||
|
@ -73,12 +74,18 @@ func InitSSO() {
|
||||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||||
}
|
}
|
||||||
cli.apiKey = cf.ApiKey
|
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
|
// Authorize return the sso authorize location with state
|
||||||
func Authorize(redirect string) string {
|
func Authorize(redirect string) string {
|
||||||
state := uuid.New().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)
|
return cli.config.AuthCodeURL(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue