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:
yubo 2020-10-23 15:22:06 +08:00 committed by GitHub
parent 228ffcfbc9
commit 5b9a03a261
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 1 deletions

View File

@ -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

View File

@ -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"`

View File

@ -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")

View File

@ -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"`

View File

@ -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)
}