mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-20 14:01:40 +01:00
Persist the new token in DB after login
This commit make sure the token is persist to DB after every time after a user logs in via OIDC provider, to make sure the secret is usable for the OIDC providers that don't provide refresh token. It also updates the authorize URL for google to make sure the refresh token will be returned. Also some misc refinement included, including add comment to the OIDC onboarded user, preset the username in onboard dialog. Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
parent
66087aac82
commit
473fed5689
@ -148,8 +148,8 @@ func AuthCodeURL(state string) (string, error) {
|
||||
log.Errorf("Failed to get OAuth configuration, error: %v", err)
|
||||
return "", err
|
||||
}
|
||||
if strings.HasPrefix(conf.Endpoint.AuthURL, googleEndpoint) {
|
||||
return conf.AuthCodeURL(state, oauth2.AccessTypeOffline), nil
|
||||
if strings.HasPrefix(conf.Endpoint.AuthURL, googleEndpoint) { // make sure the refresh token will be returned
|
||||
return conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("prompt", "consent")), nil
|
||||
}
|
||||
return conf.AuthCodeURL(state), nil
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ func (dm *defaultManager) VerifyToken(ctx context.Context, user *models.OIDCUser
|
||||
if err != nil {
|
||||
return verifyError(err)
|
||||
}
|
||||
log.Debugf("Token string for verify: %s", tokenStr)
|
||||
_, err = VerifyToken(ctx, token.IDToken)
|
||||
if err == nil {
|
||||
return nil
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
const tokenKey = "oidc_token"
|
||||
const stateKey = "oidc_state"
|
||||
const userInfoKey = "oidc_user_info"
|
||||
const oidcUserComment = "Onboarded via OIDC provider"
|
||||
|
||||
// OIDCController handles requests for OIDC login, callback and user onboard
|
||||
type OIDCController struct {
|
||||
@ -67,6 +68,7 @@ func (oc *OIDCController) RedirectLogin() {
|
||||
return
|
||||
}
|
||||
oc.SetSession(stateKey, state)
|
||||
log.Debugf("State dumped to session: %s", state)
|
||||
// Force to use the func 'Redirect' of beego.Controller
|
||||
oc.Controller.Redirect(url, http.StatusFound)
|
||||
}
|
||||
@ -75,6 +77,8 @@ func (oc *OIDCController) RedirectLogin() {
|
||||
// kick off onboard if needed.
|
||||
func (oc *OIDCController) Callback() {
|
||||
if oc.Ctx.Request.URL.Query().Get("state") != oc.GetSession(stateKey) {
|
||||
log.Errorf("State mismatch, in session: %s, in url: %s", oc.GetSession(stateKey),
|
||||
oc.Ctx.Request.URL.Query().Get("state"))
|
||||
oc.SendBadRequestError(errors.New("State mismatch"))
|
||||
return
|
||||
}
|
||||
@ -106,21 +110,34 @@ func (oc *OIDCController) Callback() {
|
||||
oc.SendInternalServerError(err)
|
||||
return
|
||||
}
|
||||
|
||||
tokenBytes, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
oc.SendInternalServerError(err)
|
||||
return
|
||||
}
|
||||
log.Debugf("Exchanged token string: %s", string(tokenBytes))
|
||||
oc.SetSession(tokenKey, tokenBytes)
|
||||
|
||||
if u == nil {
|
||||
oc.SetSession(userInfoKey, string(ouDataStr))
|
||||
oc.Controller.Redirect("/oidc-onboard", http.StatusFound)
|
||||
oc.Controller.Redirect(fmt.Sprintf("/oidc-onboard?username=%s", strings.Replace(d.Username, " ", "_", -1)),
|
||||
http.StatusFound)
|
||||
} else {
|
||||
oidcUser, err := dao.GetOIDCUserByUserID(u.UserID)
|
||||
if err != nil {
|
||||
oc.SendInternalServerError(err)
|
||||
return
|
||||
}
|
||||
_, t, err := secretAndToken(tokenBytes)
|
||||
oidcUser.Token = t
|
||||
if err := dao.UpdateOIDCUser(oidcUser); err != nil {
|
||||
oc.SendInternalServerError(err)
|
||||
return
|
||||
}
|
||||
oc.SetSession(userKey, *u)
|
||||
oc.Controller.Redirect("/", http.StatusFound)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Onboard handles the request to onboard an user authenticated via OIDC provider
|
||||
@ -170,18 +187,19 @@ func (oc *OIDCController) Onboard() {
|
||||
|
||||
email := d.Email
|
||||
if email == "" {
|
||||
email = utils.GenerateRandomString() + "@harbor.com"
|
||||
email = utils.GenerateRandomString() + "@placeholder.com"
|
||||
}
|
||||
user := models.User{
|
||||
Username: username,
|
||||
Email: email,
|
||||
OIDCUserMeta: &oidcUser,
|
||||
Comment: oidcUserComment,
|
||||
}
|
||||
|
||||
err = dao.OnBoardOIDCUser(&user)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), dao.ErrDupUser.Error()) {
|
||||
oc.RenderError(http.StatusConflict, "Duplicate username")
|
||||
oc.RenderError(http.StatusConflict, "Conflict in username, the user with same username has been onboarded.")
|
||||
return
|
||||
}
|
||||
oc.SendInternalServerError(err)
|
||||
|
Loading…
Reference in New Issue
Block a user