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