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

merged
opened by oppi.li targeting master from push-pkqzkqmxotyz

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

Changed files
+26 -6
appview
cache
session
middleware
oauth
pages
templates
user
+1
appview/cache/session/store.go
···
PkceVerifier string
DpopAuthserverNonce string
DpopPrivateJwk string
+
ReturnUrl string
}
type SessionStore struct {
+10 -2
appview/middleware/middleware.go
···
"fmt"
"log"
"net/http"
+
"net/url"
"slices"
"strconv"
"strings"
···
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)
}
}
+11 -2
appview/oauth/handler/handler.go
···
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")
···
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)
···
}
}
-
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) {
+2 -2
appview/oauth/oauth.go
···
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
···
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{}
+1
appview/pages/pages.go
···
}
type LoginParams struct {
+
ReturnUrl string
}
func (p *Pages) Login(w io.Writer, params LoginParams) error {
+1
appview/pages/templates/user/login.html
···
your Tangled (<code>.tngl.sh</code>) or <a href="https://bsky.app">Bluesky</a> (<code>.bsky.social</code>) account.
</span>
</div>
+
<input type="hidden" name="return_url" value="{{ .ReturnUrl }}">
<button
class="btn w-full my-2 mt-6 text-base "