diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 9aa31c1c02..f646615968 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -847,7 +847,17 @@ func SignInOAuthCallback(ctx *context.Context) {
 	}
 
 	if u == nil {
-		if !setting.Service.AllowOnlyInternalRegistration && setting.OAuth2Client.EnableAutoRegistration {
+		if ctx.Doer != nil {
+			// attach user to already logged in user
+			err = externalaccount.LinkAccountToUser(ctx.Doer, gothUser)
+			if err != nil {
+				ctx.ServerError("UserLinkAccount", err)
+				return
+			}
+
+			ctx.Redirect(setting.AppSubURL + "/user/settings/security")
+			return
+		} else if !setting.Service.AllowOnlyInternalRegistration && setting.OAuth2Client.EnableAutoRegistration {
 			// create new user with details from oauth2 provider
 			var missingFields []string
 			if gothUser.UserID == "" {
diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go
index a87012c480..747bf64a17 100644
--- a/routers/web/user/setting/security/security.go
+++ b/routers/web/user/setting/security/security.go
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/services/auth/source/oauth2"
 )
 
 const (
@@ -109,6 +110,14 @@ func loadSecurityData(ctx *context.Context) {
 	}
 	ctx.Data["AccountLinks"] = sources
 
+	orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers()
+	if err != nil {
+		ctx.ServerError("GetActiveOAuth2Providers", err)
+		return
+	}
+	ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
+	ctx.Data["OAuth2Providers"] = oauth2Providers
+
 	openid, err := user_model.GetUserOpenIDs(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetUserOpenIDs", err)
diff --git a/routers/web/web.go b/routers/web/web.go
index 97ea1e9035..1e550286f9 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -344,10 +344,6 @@ func RegisterRoutes(m *web.Route) {
 		}, openIDSignInEnabled)
 		m.Get("/sign_up", auth.SignUp)
 		m.Post("/sign_up", bindIgnErr(forms.RegisterForm{}), auth.SignUpPost)
-		m.Group("/oauth2", func() {
-			m.Get("/{provider}", auth.SignInOAuth)
-			m.Get("/{provider}/callback", auth.SignInOAuthCallback)
-		})
 		m.Get("/link_account", linkAccountEnabled, auth.LinkAccount)
 		m.Post("/link_account_signin", linkAccountEnabled, bindIgnErr(forms.SignInForm{}), auth.LinkAccountPostSignIn)
 		m.Post("/link_account_signup", linkAccountEnabled, bindIgnErr(forms.RegisterForm{}), auth.LinkAccountPostRegister)
@@ -452,6 +448,10 @@ func RegisterRoutes(m *web.Route) {
 		m.Get("/task/{task}", reqSignIn, user.TaskStatus)
 		m.Get("/stopwatches", reqSignIn, user.GetStopwatches)
 		m.Get("/search", ignExploreSignIn, user.Search)
+		m.Group("/oauth2", func() {
+			m.Get("/{provider}", auth.SignInOAuth)
+			m.Get("/{provider}/callback", auth.SignInOAuthCallback)
+		})
 	})
 	// ***** END: User *****
 
diff --git a/templates/user/settings/security/accountlinks.tmpl b/templates/user/settings/security/accountlinks.tmpl
index 7a9935d031..cdbd8ad1de 100644
--- a/templates/user/settings/security/accountlinks.tmpl
+++ b/templates/user/settings/security/accountlinks.tmpl
@@ -1,5 +1,23 @@
 <h4 class="ui top attached header">
 	{{.i18n.Tr "settings.manage_account_links"}}
+	{{if .OrderedOAuth2Names}}
+		<div class="ui right">
+			<div class="ui dropdown">
+				<div class="ui primary tiny button">Link Account</div>
+				<div class="menu">
+					{{range $key := .OrderedOAuth2Names}}
+						{{$provider := index $.OAuth2Providers $key}}
+						<a class="item" href="{{AppSubUrl}}/user/oauth2/{{$key}}">
+							<img
+								alt="{{$provider.DisplayName}}"
+								src="{{AppSubUrl}}{{$provider.Image}}"
+								width="20" height="20">{{$provider.DisplayName}}
+						</a>
+					{{end}}
+				</div>
+			</div>
+		</div>
+	{{end}}
 </h4>
 <div class="ui attached segment">
 	<div class="ui key list">