forked from tangled.org/core
Monorepo for Tangled

appview/oauth: return to original page after login-block

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 <me@oppi.li>

authored by oppi.li and committed by Tangled e503066a e807c571

Changed files
+26 -6
appview
cache
session
middleware
oauth
pages
templates
user
+1
appview/cache/session/store.go
··· 31 31 PkceVerifier string 32 32 DpopAuthserverNonce string 33 33 DpopPrivateJwk string 34 + ReturnUrl string 34 35 } 35 36 36 37 type SessionStore struct {
+10 -2
appview/middleware/middleware.go
··· 5 5 "fmt" 6 6 "log" 7 7 "net/http" 8 + "net/url" 8 9 "slices" 9 10 "strconv" 10 11 "strings" ··· 46 47 func AuthMiddleware(a *oauth.OAuth) middlewareFunc { 47 48 return func(next http.Handler) http.Handler { 48 49 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 50 + returnURL := "/" 51 + if u, err := url.Parse(r.Header.Get("Referer")); err == nil { 52 + returnURL = u.RequestURI() 53 + } 54 + 55 + loginURL := fmt.Sprintf("/login?return_url=%s", url.QueryEscape(returnURL)) 56 + 49 57 redirectFunc := func(w http.ResponseWriter, r *http.Request) { 50 - http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) 58 + http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) 51 59 } 52 60 if r.Header.Get("HX-Request") == "true" { 53 61 redirectFunc = func(w http.ResponseWriter, _ *http.Request) { 54 - w.Header().Set("HX-Redirect", "/login") 62 + w.Header().Set("HX-Redirect", loginURL) 55 63 w.WriteHeader(http.StatusOK) 56 64 } 57 65 }
+11 -2
appview/oauth/handler/handler.go
··· 109 109 func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) { 110 110 switch r.Method { 111 111 case http.MethodGet: 112 - o.pages.Login(w, pages.LoginParams{}) 112 + returnURL := r.URL.Query().Get("return_url") 113 + o.pages.Login(w, pages.LoginParams{ 114 + ReturnUrl: returnURL, 115 + }) 113 116 case http.MethodPost: 114 117 handle := r.FormValue("handle") 115 118 ··· 194 197 DpopAuthserverNonce: parResp.DpopAuthserverNonce, 195 198 DpopPrivateJwk: string(dpopKeyJson), 196 199 State: parResp.State, 200 + ReturnUrl: r.FormValue("return_url"), 197 201 }) 198 202 if err != nil { 199 203 log.Println("failed to save oauth request:", err) ··· 311 315 } 312 316 } 313 317 314 - http.Redirect(w, r, "/", http.StatusFound) 318 + returnUrl := oauthRequest.ReturnUrl 319 + if returnUrl == "" { 320 + returnUrl = "/" 321 + } 322 + 323 + http.Redirect(w, r, returnUrl, http.StatusFound) 315 324 } 316 325 317 326 func (o *OAuthHandler) logout(w http.ResponseWriter, r *http.Request) {
+2 -2
appview/oauth/oauth.go
··· 103 103 if err != nil { 104 104 return nil, false, fmt.Errorf("error parsing expiry time: %w", err) 105 105 } 106 - if expiry.Sub(time.Now()) <= 5*time.Minute { 106 + if time.Until(expiry) <= 5*time.Minute { 107 107 privateJwk, err := helpers.ParseJWKFromBytes([]byte(session.DpopPrivateJwk)) 108 108 if err != nil { 109 109 return nil, false, err ··· 315 315 redirectURIs := makeRedirectURIs(clientURI) 316 316 317 317 if o.config.Core.Dev { 318 - clientURI = fmt.Sprintf("http://127.0.0.1:3000") 318 + clientURI = "http://127.0.0.1:3000" 319 319 redirectURIs = makeRedirectURIs(clientURI) 320 320 321 321 query := url.Values{}
+1
appview/pages/pages.go
··· 261 261 } 262 262 263 263 type LoginParams struct { 264 + ReturnUrl string 264 265 } 265 266 266 267 func (p *Pages) Login(w io.Writer, params LoginParams) error {
+1
appview/pages/templates/user/login.html
··· 41 41 your Tangled (<code>.tngl.sh</code>) or <a href="https://bsky.app">Bluesky</a> (<code>.bsky.social</code>) account. 42 42 </span> 43 43 </div> 44 + <input type="hidden" name="return_url" value="{{ .ReturnUrl }}"> 44 45 45 46 <button 46 47 class="btn w-full my-2 mt-6 text-base "