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. +