Refactor OpenIDConnect to support SSH/FullName sync (#34978)
* Fix #26585 * Fix #28327 * Fix #34932
This commit is contained in:
@@ -5,7 +5,6 @@ package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -21,8 +20,6 @@ import (
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/externalaccount"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
|
||||
"github.com/markbates/goth"
|
||||
)
|
||||
|
||||
var tplLinkAccount templates.TplName = "user/auth/link_account"
|
||||
@@ -52,28 +49,28 @@ func LinkAccount(ctx *context.Context) {
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
|
||||
|
||||
gothUser, ok := ctx.Session.Get("linkAccountGothUser").(goth.User)
|
||||
linkAccountData := oauth2GetLinkAccountData(ctx)
|
||||
|
||||
// If you'd like to quickly debug the "link account" page layout, just uncomment the blow line
|
||||
// Don't worry, when the below line exists, the lint won't pass: ineffectual assignment to gothUser (ineffassign)
|
||||
// gothUser, ok = goth.User{Email: "invalid-email", Name: "."}, true // intentionally use invalid data to avoid pass the registration check
|
||||
// linkAccountData = &LinkAccountData{authSource, gothUser} // intentionally use invalid data to avoid pass the registration check
|
||||
|
||||
if !ok {
|
||||
if linkAccountData == nil {
|
||||
// no account in session, so just redirect to the login page, then the user could restart the process
|
||||
ctx.Redirect(setting.AppSubURL + "/user/login")
|
||||
return
|
||||
}
|
||||
|
||||
if missingFields, ok := gothUser.RawData["__giteaAutoRegMissingFields"].([]string); ok {
|
||||
ctx.Data["AutoRegistrationFailedPrompt"] = ctx.Tr("auth.oauth_callback_unable_auto_reg", gothUser.Provider, strings.Join(missingFields, ","))
|
||||
if missingFields, ok := linkAccountData.GothUser.RawData["__giteaAutoRegMissingFields"].([]string); ok {
|
||||
ctx.Data["AutoRegistrationFailedPrompt"] = ctx.Tr("auth.oauth_callback_unable_auto_reg", linkAccountData.GothUser.Provider, strings.Join(missingFields, ","))
|
||||
}
|
||||
|
||||
uname, err := extractUserNameFromOAuth2(&gothUser)
|
||||
uname, err := extractUserNameFromOAuth2(&linkAccountData.GothUser)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
return
|
||||
}
|
||||
email := gothUser.Email
|
||||
email := linkAccountData.GothUser.Email
|
||||
ctx.Data["user_name"] = uname
|
||||
ctx.Data["email"] = email
|
||||
|
||||
@@ -152,8 +149,8 @@ func LinkAccountPostSignIn(ctx *context.Context) {
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
|
||||
|
||||
gothUser := ctx.Session.Get("linkAccountGothUser")
|
||||
if gothUser == nil {
|
||||
linkAccountData := oauth2GetLinkAccountData(ctx)
|
||||
if linkAccountData == nil {
|
||||
ctx.ServerError("UserSignIn", errors.New("not in LinkAccount session"))
|
||||
return
|
||||
}
|
||||
@@ -169,11 +166,14 @@ func LinkAccountPostSignIn(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
linkAccount(ctx, u, gothUser.(goth.User), signInForm.Remember)
|
||||
oauth2LinkAccount(ctx, u, linkAccountData, signInForm.Remember)
|
||||
}
|
||||
|
||||
func linkAccount(ctx *context.Context, u *user_model.User, gothUser goth.User, remember bool) {
|
||||
updateAvatarIfNeed(ctx, gothUser.AvatarURL, u)
|
||||
func oauth2LinkAccount(ctx *context.Context, u *user_model.User, linkAccountData *LinkAccountData, remember bool) {
|
||||
oauth2SignInSync(ctx, &linkAccountData.AuthSource, u, linkAccountData.GothUser)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
// If this user is enrolled in 2FA, we can't sign the user in just yet.
|
||||
// Instead, redirect them to the 2FA authentication page.
|
||||
@@ -185,7 +185,7 @@ func linkAccount(ctx *context.Context, u *user_model.User, gothUser goth.User, r
|
||||
return
|
||||
}
|
||||
|
||||
err = externalaccount.LinkAccountToUser(ctx, u, gothUser)
|
||||
err = externalaccount.LinkAccountToUser(ctx, linkAccountData.AuthSource.ID, u, linkAccountData.GothUser)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserLinkAccount", err)
|
||||
return
|
||||
@@ -243,17 +243,11 @@ func LinkAccountPostRegister(ctx *context.Context) {
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/link_account_signin"
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/link_account_signup"
|
||||
|
||||
gothUserInterface := ctx.Session.Get("linkAccountGothUser")
|
||||
if gothUserInterface == nil {
|
||||
linkAccountData := oauth2GetLinkAccountData(ctx)
|
||||
if linkAccountData == nil {
|
||||
ctx.ServerError("UserSignUp", errors.New("not in LinkAccount session"))
|
||||
return
|
||||
}
|
||||
gothUser, ok := gothUserInterface.(goth.User)
|
||||
if !ok {
|
||||
ctx.ServerError("UserSignUp", fmt.Errorf("session linkAccountGothUser type is %t but not goth.User", gothUserInterface))
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(http.StatusOK, tplLinkAccount)
|
||||
return
|
||||
@@ -296,31 +290,33 @@ func LinkAccountPostRegister(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
authSource, err := auth.GetActiveOAuth2SourceByName(ctx, gothUser.Provider)
|
||||
if err != nil {
|
||||
ctx.ServerError("CreateUser", err)
|
||||
return
|
||||
}
|
||||
|
||||
u := &user_model.User{
|
||||
Name: form.UserName,
|
||||
Email: form.Email,
|
||||
Passwd: form.Password,
|
||||
LoginType: auth.OAuth2,
|
||||
LoginSource: authSource.ID,
|
||||
LoginName: gothUser.UserID,
|
||||
LoginSource: linkAccountData.AuthSource.ID,
|
||||
LoginName: linkAccountData.GothUser.UserID,
|
||||
}
|
||||
|
||||
if !createAndHandleCreatedUser(ctx, tplLinkAccount, form, u, nil, &gothUser, false) {
|
||||
if !createAndHandleCreatedUser(ctx, tplLinkAccount, form, u, nil, linkAccountData) {
|
||||
// error already handled
|
||||
return
|
||||
}
|
||||
|
||||
source := authSource.Cfg.(*oauth2.Source)
|
||||
if err := syncGroupsToTeams(ctx, source, &gothUser, u); err != nil {
|
||||
source := linkAccountData.AuthSource.Cfg.(*oauth2.Source)
|
||||
if err := syncGroupsToTeams(ctx, source, &linkAccountData.GothUser, u); err != nil {
|
||||
ctx.ServerError("SyncGroupsToTeams", err)
|
||||
return
|
||||
}
|
||||
|
||||
handleSignIn(ctx, u, false)
|
||||
}
|
||||
|
||||
func linkAccountFromContext(ctx *context.Context, user *user_model.User) error {
|
||||
linkAccountData := oauth2GetLinkAccountData(ctx)
|
||||
if linkAccountData == nil {
|
||||
return errors.New("not in LinkAccount session")
|
||||
}
|
||||
return externalaccount.LinkAccountToUser(ctx, linkAccountData.AuthSource.ID, user, linkAccountData.GothUser)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user