challenge/resource-load: use proper redirect URL to current issued challenge, add static/dynamic cache bust

This commit is contained in:
WeebDataHoarder
2025-05-13 23:43:31 +02:00
parent 3abdc2ee5b
commit 163fce6cfc
6 changed files with 25 additions and 15 deletions

View File

@@ -8,7 +8,9 @@ import (
"git.gammaspectra.live/git/go-away/utils" "git.gammaspectra.live/git/go-away/utils"
"net/http" "net/http"
"net/url" "net/url"
"strconv"
"strings" "strings"
"time"
) )
var ErrInvalidToken = errors.New("invalid token") var ErrInvalidToken = errors.New("invalid token")
@@ -47,6 +49,7 @@ const (
QueryArgRequestId = QueryArgPrefix + "_id" QueryArgRequestId = QueryArgPrefix + "_id"
QueryArgChallenge = QueryArgPrefix + "_challenge" QueryArgChallenge = QueryArgPrefix + "_challenge"
QueryArgToken = QueryArgPrefix + "_token" QueryArgToken = QueryArgPrefix + "_token"
QueryArgBust = QueryArgPrefix + "_bust"
) )
const MakeChallengeUrlSuffix = "/make-challenge" const MakeChallengeUrlSuffix = "/make-challenge"
@@ -96,6 +99,7 @@ func VerifyUrl(r *http.Request, reg *Registration, token string) (*url.URL, erro
values.Set(QueryArgRedirect, redirectUrl.String()) values.Set(QueryArgRedirect, redirectUrl.String())
values.Set(QueryArgToken, token) values.Set(QueryArgToken, token)
values.Set(QueryArgChallenge, reg.Name) values.Set(QueryArgChallenge, reg.Name)
values.Set(QueryArgBust, strconv.FormatInt(time.Now().UTC().UnixMilli(), 10))
uri.RawQuery = values.Encode() uri.RawQuery = values.Encode()
return uri, nil return uri, nil

View File

@@ -23,9 +23,13 @@ func FillRegistrationHeader(state challenge.StateInterface, reg *challenge.Regis
return challenge.VerifyResultFail return challenge.VerifyResultFail
} }
redirectUri, err := challenge.RedirectUrl(r, reg)
if err != nil {
return challenge.VerifyResultFail
}
// self redirect! // self redirect!
//TODO: adjust deadline //TODO: adjust deadline
w.Header().Set("Refresh", "2; url="+r.URL.String()) w.Header().Set("Refresh", "2; url="+redirectUri.String())
state.ChallengePage(w, r, state.Settings().ChallengeResponseCode, reg, map[string]any{ state.ChallengePage(w, r, state.Settings().ChallengeResponseCode, reg, map[string]any{
"LinkTags": []map[string]string{ "LinkTags": []map[string]string{

View File

@@ -23,6 +23,7 @@ func ServeChallengeScript(w http.ResponseWriter, r *http.Request, reg *Registrat
//TODO: log //TODO: log
panic(err) panic(err)
} }
data.ResponseHeaders(w) data.ResponseHeaders(w)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@@ -30,7 +31,7 @@ func ServeChallengeScript(w http.ResponseWriter, r *http.Request, reg *Registrat
"Id": data.Id.String(), "Id": data.Id.String(),
"Path": reg.Path, "Path": reg.Path,
"Parameters": paramData, "Parameters": paramData,
"Random": utils.CacheBust(), "Random": utils.StaticCacheBust(),
"Challenge": reg.Name, "Challenge": reg.Name,
"ChallengeScript": script, "ChallengeScript": script,
"Strings": data.State.Strings(), "Strings": data.State.Strings(),

View File

@@ -97,7 +97,7 @@ func FillJavaScriptRegistration(state challenge.StateInterface, reg *challenge.R
reg.IssueChallenge = func(w http.ResponseWriter, r *http.Request, key challenge.Key, expiry time.Time) challenge.VerifyResult { reg.IssueChallenge = func(w http.ResponseWriter, r *http.Request, key challenge.Key, expiry time.Time) challenge.VerifyResult {
state.ChallengePage(w, r, state.Settings().ChallengeResponseCode, reg, map[string]any{ state.ChallengePage(w, r, state.Settings().ChallengeResponseCode, reg, map[string]any{
"EndTags": []template.HTML{ "EndTags": []template.HTML{
template.HTML(fmt.Sprintf("<script async type=\"module\" src=\"%s?cacheBust=%s\"></script>", reg.Path+"/script.mjs", utils.CacheBust())), template.HTML(fmt.Sprintf("<script async type=\"module\" src=\"%s?cacheBust=%s\"></script>", reg.Path+"/script.mjs", utils.StaticCacheBust())),
}, },
}) })
return challenge.VerifyResultNone return challenge.VerifyResultNone
@@ -164,6 +164,8 @@ func FillJavaScriptRegistration(state challenge.StateInterface, reg *challenge.R
w.Header()[k] = v w.Header()[k] = v
} }
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out.Data))) w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out.Data)))
data.ResponseHeaders(w)
w.WriteHeader(out.Code) w.WriteHeader(out.Code)
_, _ = w.Write(out.Data) _, _ = w.Write(out.Data)
return nil return nil

View File

@@ -78,7 +78,7 @@ func (state *State) ChallengePage(w http.ResponseWriter, r *http.Request, status
data := challenge.RequestDataFromContext(r.Context()) data := challenge.RequestDataFromContext(r.Context())
input := make(map[string]any) input := make(map[string]any)
input["Id"] = data.Id.String() input["Id"] = data.Id.String()
input["Random"] = utils.CacheBust() input["Random"] = utils.StaticCacheBust()
input["Path"] = state.UrlPath() input["Path"] = state.UrlPath()
input["Links"] = state.opt.Links input["Links"] = state.opt.Links
@@ -121,7 +121,7 @@ func (state *State) ErrorPage(w http.ResponseWriter, r *http.Request, status int
input := map[string]any{ input := map[string]any{
"Id": data.Id.String(), "Id": data.Id.String(),
"Random": utils.CacheBust(), "Random": utils.StaticCacheBust(),
"Error": err.Error(), "Error": err.Error(),
"Path": state.UrlPath(), "Path": state.UrlPath(),
"Theme": "", "Theme": "",

View File

@@ -167,15 +167,14 @@ func GetRemoteAddress(ctx context.Context) *netip.AddrPort {
return &ip return &ip
} }
func CacheBust() string { func RandomCacheBust(n int) string {
return cacheBust buf := make([]byte, n)
}
var cacheBust string
func init() {
buf := make([]byte, 16)
_, _ = rand.Read(buf) _, _ = rand.Read(buf)
cacheBust = base64.RawURLEncoding.EncodeToString(buf) return base64.RawURLEncoding.EncodeToString(buf)
}
var staticCacheBust = RandomCacheBust(16)
func StaticCacheBust() string {
return staticCacheBust
} }