From 009dc2509ab493a470feb2cd5ccbff3b1ca2cae8 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Sun, 19 Oct 2025 20:46:22 +0900 Subject: [PATCH] appview/oauth: handle failed login with error code Change-Id: zmowtwoprttltmwlzxzmxutuwllrqtyw Close: #271 Signed-off-by: Seongmin Lee --- appview/oauth/handler.go | 15 +++++++++++++-- appview/pages/pages.go | 3 ++- appview/pages/templates/user/login.html | 21 +++++++++++++++++++-- appview/state/login.go | 2 ++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/appview/oauth/handler.go b/appview/oauth/handler.go index 1ea04ab9..10c77b60 100644 --- a/appview/oauth/handler.go +++ b/appview/oauth/handler.go @@ -4,11 +4,13 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "net/http" "slices" "time" + "github.com/bluesky-social/indigo/atproto/auth/oauth" "github.com/go-chi/chi/v5" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/posthog/posthog-go" @@ -58,15 +60,24 @@ func (o *OAuth) jwks(w http.ResponseWriter, r *http.Request) { func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) { ctx := r.Context() + l := o.Logger.With("query", r.URL.Query()) sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query()) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + var callbackErr *oauth.AuthRequestCallbackError + if errors.As(err, &callbackErr) { + l.Debug("callback error", "err", callbackErr) + http.Redirect(w, r, fmt.Sprintf("/login?error=%s", callbackErr.ErrorCode), http.StatusFound) + return + } + l.Error("failed to process callback", "err", err) + http.Redirect(w, r, "/login?error=oauth", http.StatusFound) return } if err := o.SaveSession(w, r, sessData); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + l.Error("failed to save session", "data", sessData, "err", err) + http.Redirect(w, r, "/login?error=session", http.StatusFound) return } diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 296d797d..7e9d2038 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -220,7 +220,8 @@ func (p *Pages) Favicon(w io.Writer) error { } type LoginParams struct { - ReturnUrl string + ReturnUrl string + ErrorCode string } func (p *Pages) Login(w io.Writer, params LoginParams) error { diff --git a/appview/pages/templates/user/login.html b/appview/pages/templates/user/login.html index 2b9347b4..7727a9a4 100644 --- a/appview/pages/templates/user/login.html +++ b/appview/pages/templates/user/login.html @@ -13,7 +13,7 @@ login · tangled -
+

{{ template "fragments/logotype" }}

@@ -21,7 +21,7 @@ tightly-knit social coding.
login
+ {{ if .ErrorCode }} +
+ {{ i "circle-alert" "w-4 h-4" }} +
+
Login error
+

+ {{ if eq .ErrorCode "access_denied" }} + You have not authorized the app. Please try again + {{ else if eq .ErrorCode "session" }} + Server failed to create user session. Please try again + {{ else }} + Internal Server error. Please try again +

+ {{ end }} +
+
+ {{ end }}

Don't have an account? Create an account on Tangled now!

diff --git a/appview/state/login.go b/appview/state/login.go index a476cfb3..89797cb7 100644 --- a/appview/state/login.go +++ b/appview/state/login.go @@ -14,8 +14,10 @@ func (s *State) Login(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: returnURL := r.URL.Query().Get("return_url") + errorCode := r.URL.Query().Get("error") s.pages.Login(w, pages.LoginParams{ ReturnUrl: returnURL, + ErrorCode: errorCode, }) case http.MethodPost: handle := r.FormValue("handle") -- 2.43.0