Save login name to cookie, correct public key path, fix test client

This commit is contained in:
Melon 2023-11-08 11:38:31 +00:00
parent 6941d64b7f
commit 56f594ab3c
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
5 changed files with 76 additions and 7 deletions

View File

@ -11,9 +11,9 @@ import (
"flag" "flag"
"github.com/1f349/lavender/server" "github.com/1f349/lavender/server"
"github.com/1f349/lavender/server/pages" "github.com/1f349/lavender/server/pages"
"github.com/1f349/mjwt"
"github.com/1f349/violet/utils" "github.com/1f349/violet/utils"
exit_reload "github.com/MrMelon54/exit-reload" exit_reload "github.com/MrMelon54/exit-reload"
"github.com/1f349/mjwt"
"github.com/google/subcommands" "github.com/google/subcommands"
"log" "log"
"os" "os"
@ -75,7 +75,7 @@ func normalLoad(startUp server.Conf, wd string) {
if err != nil { if err != nil {
log.Fatal("[Lavender] Failed to load or create MJWT signer:", err) log.Fatal("[Lavender] Failed to load or create MJWT signer:", err)
} }
saveMjwtPubKey(mSign) saveMjwtPubKey(mSign, wd)
if err := pages.LoadPages(wd); err != nil { if err := pages.LoadPages(wd); err != nil {
log.Fatal("[Lavender] Failed to load page templates:", err) log.Fatal("[Lavender] Failed to load page templates:", err)
@ -91,14 +91,14 @@ func normalLoad(startUp server.Conf, wd string) {
}) })
} }
func saveMjwtPubKey(mSign mjwt.Signer) { func saveMjwtPubKey(mSign mjwt.Signer, wd string) {
pubKey := x509.MarshalPKCS1PublicKey(mSign.PublicKey()) pubKey := x509.MarshalPKCS1PublicKey(mSign.PublicKey())
b := new(bytes.Buffer) b := new(bytes.Buffer)
err := pem.Encode(b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pubKey}) err := pem.Encode(b, &pem.Block{Type: "RSA PUBLIC KEY", Bytes: pubKey})
if err != nil { if err != nil {
log.Fatal("[Lavender] Failed to encode MJWT public key:", err) log.Fatal("[Lavender] Failed to encode MJWT public key:", err)
} }
err = os.WriteFile("lavender.public.key", b.Bytes(), 0600) err = os.WriteFile(filepath.Join(wd, "lavender.public.key"), b.Bytes(), 0600)
if err != nil && !errors.Is(err, os.ErrExist) { if err != nil && !errors.Is(err, os.ErrExist) {
log.Fatal("[Lavender] Failed to save MJWT public key:", err) log.Fatal("[Lavender] Failed to save MJWT public key:", err)
} }

View File

@ -15,6 +15,7 @@ import (
"golang.org/x/oauth2" "golang.org/x/oauth2"
"net/http" "net/http"
"net/mail" "net/mail"
"net/url"
"strings" "strings"
"time" "time"
) )
@ -33,6 +34,15 @@ var testOa2UserInfo = func(oidc *issuer.WellKnownOIDC, ctx context.Context, exch
} }
func (h *HttpServer) flowPopup(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) { func (h *HttpServer) flowPopup(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
cookie, err := req.Cookie("lavender-login-name")
if err == nil && cookie.Valid() == nil {
pages.RenderPageTemplate(rw, "flow-popup-memory", map[string]any{
"ServiceName": h.conf.ServiceName,
"Origin": req.URL.Query().Get("origin"),
"LoginName": cookie.Value,
})
return
}
pages.RenderPageTemplate(rw, "flow-popup", map[string]any{ pages.RenderPageTemplate(rw, "flow-popup", map[string]any{
"ServiceName": h.conf.ServiceName, "ServiceName": h.conf.ServiceName,
"Origin": req.URL.Query().Get("origin"), "Origin": req.URL.Query().Get("origin"),
@ -40,6 +50,23 @@ func (h *HttpServer) flowPopup(rw http.ResponseWriter, req *http.Request, _ http
} }
func (h *HttpServer) flowPopupPost(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) { func (h *HttpServer) flowPopupPost(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
if req.PostFormValue("not-you") == "1" {
http.SetCookie(rw, &http.Cookie{
Name: "lavender-login-name",
Value: "",
Path: "/",
MaxAge: -1,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
http.Redirect(rw, req, (&url.URL{
Path: "/popup",
RawQuery: url.Values{
"origin": []string{req.PostFormValue("origin")},
}.Encode(),
}).String(), http.StatusFound)
return
}
loginName := req.PostFormValue("loginname") loginName := req.PostFormValue("loginname")
login := h.manager.FindServiceFromLogin(loginName) login := h.manager.FindServiceFromLogin(loginName)
if login == nil { if login == nil {
@ -50,6 +77,18 @@ func (h *HttpServer) flowPopupPost(rw http.ResponseWriter, req *http.Request, _
n := strings.IndexByte(loginName, '@') n := strings.IndexByte(loginName, '@')
loginUn := loginName[:n] loginUn := loginName[:n]
now := time.Now()
future := now.AddDate(1, 0, 0)
http.SetCookie(rw, &http.Cookie{
Name: "lavender-login-name",
Value: loginName,
Path: "/",
Expires: future,
MaxAge: int(future.Sub(now).Seconds()),
Secure: true,
SameSite: http.SameSiteStrictMode,
})
targetOrigin := req.PostFormValue("origin") targetOrigin := req.PostFormValue("origin")
allowedService, found := h.services[targetOrigin] allowedService, found := h.services[targetOrigin]
if !found { if !found {

View File

@ -13,6 +13,9 @@
}; };
window.addEventListener("load", function () { window.addEventListener("load", function () {
window.opener.postMessage(loginData, loginData.target); window.opener.postMessage(loginData, loginData.target);
setTimeout(function () {
window.close();
}, 500);
}); });
</script> </script>
</head> </head>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{.ServiceName}}</title>
</head>
<body>
<header>
<h1>{{.ServiceName}}</h1>
</header>
<main>
<div>Log in as: <span>{{.LoginName}}</span></div>
<div>
<form method="POST" action="/popup">
<input type="hidden" name="origin" value="{{.Origin}}"/>
<button type="submit" name="not-you" value="1">Not You?</button>
</form>
</div>
<div>
<form method="POST" action="/popup">
<input type="hidden" name="origin" value="{{.Origin}}"/>
<input type="hidden" name="loginname" value="{{.LoginName}}"/>
<button type="submit">Continue</button>
</form>
</div>
</main>
</body>
</html>

View File

@ -10,9 +10,9 @@
if (isObject(event.data)) { if (isObject(event.data)) {
document.getElementById("someTextArea").textContent = JSON.stringify(event.data, null, 2); document.getElementById("someTextArea").textContent = JSON.stringify(event.data, null, 2);
let perms = document.getElementById("somePerms"); let perms = document.getElementById("somePerms");
perms.childNodes.forEach(function (x) { while (perms.childNodes.length > 0) {
x.clear(); perms.childNodes.item(0).remove();
}); }
let jwt = parseJwt(event.data.tokens.access); let jwt = parseJwt(event.data.tokens.access);
if (jwt.per != null) { if (jwt.per != null) {
jwt.per.forEach(function (x) { jwt.per.forEach(function (x) {