From 9c8c9ff6d10b35de8d2d7eae0fc2646ad9bbe94a Mon Sep 17 00:00:00 2001
From: Denys Konovalov <kontakt@denyskon.de>
Date: Tue, 21 May 2024 18:23:49 +0200
Subject: [PATCH] use existing oauth grant for public client (#31015)

Do not try to create a new authorization grant when one exists already,
thus preventing a DB-related authorization issue.

Fix https://github.com/go-gitea/gitea/pull/30790#issuecomment-2118812426

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
---
 routers/web/auth/oauth.go | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 84fa473044..b337b6b156 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -556,15 +556,30 @@ func GrantApplicationOAuth(ctx *context.Context) {
 		ctx.ServerError("GetOAuth2ApplicationByClientID", err)
 		return
 	}
-	grant, err := app.CreateGrant(ctx, ctx.Doer.ID, form.Scope)
+	grant, err := app.GetGrantByUserID(ctx, ctx.Doer.ID)
 	if err != nil {
+		handleServerError(ctx, form.State, form.RedirectURI)
+		return
+	}
+	if grant == nil {
+		grant, err = app.CreateGrant(ctx, ctx.Doer.ID, form.Scope)
+		if err != nil {
+			handleAuthorizeError(ctx, AuthorizeError{
+				State:            form.State,
+				ErrorDescription: "cannot create grant for user",
+				ErrorCode:        ErrorCodeServerError,
+			}, form.RedirectURI)
+			return
+		}
+	} else if grant.Scope != form.Scope {
 		handleAuthorizeError(ctx, AuthorizeError{
 			State:            form.State,
-			ErrorDescription: "cannot create grant for user",
+			ErrorDescription: "a grant exists with different scope",
 			ErrorCode:        ErrorCodeServerError,
 		}, form.RedirectURI)
 		return
 	}
+
 	if len(form.Nonce) > 0 {
 		err := grant.SetNonce(ctx, form.Nonce)
 		if err != nil {