oficina / home Public

Clone
git clone https://amadan.net/oficina/home

Plain git — no account needed to clone.

Download

Download this file

1package home
2
3import (
4 "net/http"
5 "net/url"
6 "time"
7)
8
9const returnCookie = "__Host-oficina-return"
10const returnTTL = 10 * time.Minute
11
12func credentialReturn(value string) string {
13 switch value {
14 case "/passkey/enrol", "/passkey/codes", "/authorize/resume":
15 return value
16 }
17 return "/"
18}
19
20func writeReturn(w http.ResponseWriter, value string) {
21 maxAge := int(returnTTL.Seconds())
22 if value == "/" {
23 value = ""
24 maxAge = -1
25 }
26 http.SetCookie(w, &http.Cookie{Name: returnCookie, Value: value, Path: "/", MaxAge: maxAge, Secure: true, HttpOnly: true, SameSite: http.SameSiteLaxMode})
27}
28
29func readReturn(r *http.Request) string {
30 value := ""
31 count := 0
32 for _, c := range r.Cookies() {
33 if c.Name == returnCookie {
34 value = c.Value
35 count++
36 }
37 }
38 if count != 1 {
39 return "/"
40 }
41 return credentialReturn(value)
42}
43
44func rememberReturn(w http.ResponseWriter, r *http.Request) {
45 q, err := url.ParseQuery(r.URL.RawQuery)
46 if err != nil {
47 writeReturn(w, "/")
48 return
49 }
50 values, present := q["return_to"]
51 if !present && q.Get("force") == "1" && readReturn(r) != "/" {
52 return
53 }
54 target := "/"
55 if len(values) == 1 {
56 target = credentialReturn(values[0])
57 }
58 writeReturn(w, target)
59}
60
61// Gate reads FormValue. Give it only validated navigation intent, so neither
62// the callback query nor the magic-link POST can override the cookie.
63func requestWithReturn(r *http.Request, target string) *http.Request {
64 clone := r.Clone(r.Context())
65 clone.Form = url.Values{"return_to": {target}}
66 clone.PostForm = url.Values{"return_to": {target}}
67 return clone
68}
69