From 7898d2ed8a7d9e2a4c5bc7e5113cb32770cbab78 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Thu, 14 Aug 2025 23:32:38 +0100 Subject: [PATCH] appview/oauth: return to original page after login-block Change-Id: pkqzkqmxotyzyupwlqupusnuvxxwlluu when attempting to do an authorized request while logged-out, the auth middleware boots the user to the login page. this page now keeps track of the 'Referer' in the oauth request. once the oauth callback is complete, the user is sent back to the page they came from. Signed-off-by: oppiliappan --- appview/cache/session/store.go | 1 + appview/middleware/middleware.go | 12 ++++++++++-- appview/oauth/handler/handler.go | 13 +++++++++++-- appview/oauth/oauth.go | 4 ++-- appview/pages/pages.go | 1 + appview/pages/templates/user/login.html | 1 + 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/appview/cache/session/store.go b/appview/cache/session/store.go index cd8e6cef..b9e0c3ea 100644 --- a/appview/cache/session/store.go +++ b/appview/cache/session/store.go @@ -31,6 +31,7 @@ type OAuthRequest struct { PkceVerifier string DpopAuthserverNonce string DpopPrivateJwk string + ReturnUrl string } type SessionStore struct { diff --git a/appview/middleware/middleware.go b/appview/middleware/middleware.go index b5532e3a..d69d01a4 100644 --- a/appview/middleware/middleware.go +++ b/appview/middleware/middleware.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "net/url" "slices" "strconv" "strings" @@ -46,12 +47,19 @@ type middlewareFunc func(http.Handler) http.Handler func AuthMiddleware(a *oauth.OAuth) middlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + returnURL := "/" + if u, err := url.Parse(r.Header.Get("Referer")); err == nil { + returnURL = u.RequestURI() + } + + loginURL := fmt.Sprintf("/login?return_url=%s", url.QueryEscape(returnURL)) + redirectFunc := func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) + http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) } if r.Header.Get("HX-Request") == "true" { redirectFunc = func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("HX-Redirect", "/login") + w.Header().Set("HX-Redirect", loginURL) w.WriteHeader(http.StatusOK) } } diff --git a/appview/oauth/handler/handler.go b/appview/oauth/handler/handler.go index c4a6c419..18393f27 100644 --- a/appview/oauth/handler/handler.go +++ b/appview/oauth/handler/handler.go @@ -109,7 +109,10 @@ func (o *OAuthHandler) jwks(w http.ResponseWriter, r *http.Request) { func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - o.pages.Login(w, pages.LoginParams{}) + returnURL := r.URL.Query().Get("return_url") + o.pages.Login(w, pages.LoginParams{ + ReturnUrl: returnURL, + }) case http.MethodPost: handle := r.FormValue("handle") @@ -194,6 +197,7 @@ func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) { DpopAuthserverNonce: parResp.DpopAuthserverNonce, DpopPrivateJwk: string(dpopKeyJson), State: parResp.State, + ReturnUrl: r.FormValue("return_url"), }) if err != nil { log.Println("failed to save oauth request:", err) @@ -311,7 +315,12 @@ func (o *OAuthHandler) callback(w http.ResponseWriter, r *http.Request) { } } - http.Redirect(w, r, "/", http.StatusFound) + returnUrl := oauthRequest.ReturnUrl + if returnUrl == "" { + returnUrl = "/" + } + + http.Redirect(w, r, returnUrl, http.StatusFound) } func (o *OAuthHandler) logout(w http.ResponseWriter, r *http.Request) { diff --git a/appview/oauth/oauth.go b/appview/oauth/oauth.go index 5a233f3c..47859952 100644 --- a/appview/oauth/oauth.go +++ b/appview/oauth/oauth.go @@ -103,7 +103,7 @@ func (o *OAuth) GetSession(r *http.Request) (*sessioncache.OAuthSession, bool, e if err != nil { return nil, false, fmt.Errorf("error parsing expiry time: %w", err) } - if expiry.Sub(time.Now()) <= 5*time.Minute { + if time.Until(expiry) <= 5*time.Minute { privateJwk, err := helpers.ParseJWKFromBytes([]byte(session.DpopPrivateJwk)) if err != nil { return nil, false, err @@ -315,7 +315,7 @@ func (o *OAuth) ClientMetadata() ClientMetadata { redirectURIs := makeRedirectURIs(clientURI) if o.config.Core.Dev { - clientURI = fmt.Sprintf("http://127.0.0.1:3000") + clientURI = "http://127.0.0.1:3000" redirectURIs = makeRedirectURIs(clientURI) query := url.Values{} diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 953748e4..d5bb68bb 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -261,6 +261,7 @@ func (p *Pages) executeRepo(name string, w io.Writer, params any) error { } type LoginParams struct { + ReturnUrl 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 bd55539b..414e2733 100644 --- a/appview/pages/templates/user/login.html +++ b/appview/pages/templates/user/login.html @@ -41,6 +41,7 @@ your Tangled (.tngl.sh) or Bluesky (.bsky.social) account. +