diff --git a/cmd/lavender/conf.go b/cmd/lavender/conf.go
index 9637149..c9b465f 100644
--- a/cmd/lavender/conf.go
+++ b/cmd/lavender/conf.go
@@ -8,6 +8,7 @@ import (
type startUpConfig struct {
Listen string `json:"listen"`
BaseUrl string `json:"base_url"`
+ ServiceName string `json:"service_name"`
Issuer string `json:"issuer"`
SsoServices []loginServiceManager.SsoConfig `json:"sso_services"`
AllowedClients []utils.JsonUrl `json:"allowed_clients"`
diff --git a/cmd/lavender/serve.go b/cmd/lavender/serve.go
index 30ca916..4f94ca7 100644
--- a/cmd/lavender/serve.go
+++ b/cmd/lavender/serve.go
@@ -77,7 +77,7 @@ func normalLoad(startUp startUpConfig, wd string) {
log.Fatal("[Lavender] Failed to create SSO service manager: ", err)
}
- srv := server.NewHttpServer(startUp.Listen, startUp.BaseUrl, startUp.AllowedClients, manager, mSign)
+ srv := server.NewHttpServer(startUp.Listen, startUp.BaseUrl, startUp.ServiceName, startUp.AllowedClients, manager, mSign)
log.Printf("[Lavender] Starting HTTP server on '%s'\n", srv.Addr)
go utils.RunBackgroundHttp("HTTP", srv)
diff --git a/issuer/sso.go b/issuer/sso.go
index 2533784..f208e4f 100644
--- a/issuer/sso.go
+++ b/issuer/sso.go
@@ -46,6 +46,7 @@ func (s SsoConfig) FetchConfig() (*WellKnownOIDC, error) {
if err != nil {
return nil, err
}
+ c.Config = s
c.OAuth2Config = oauth2.Config{
ClientID: c.Config.Client.ID,
ClientSecret: c.Config.Client.Secret,
diff --git a/server/flow-callback.go.html b/server/flow-callback.go.html
index 7c72a9d..267f6c3 100644
--- a/server/flow-callback.go.html
+++ b/server/flow-callback.go.html
@@ -2,20 +2,17 @@
{{.ServiceName}}
+
-
-Loading...
+Loading...
diff --git a/server/flow-popup.go.html b/server/flow-popup.go.html
index f809094..86c67ca 100644
--- a/server/flow-popup.go.html
+++ b/server/flow-popup.go.html
@@ -8,11 +8,11 @@
{{.ServiceName}}
-
diff --git a/server/flow.go b/server/flow.go
index ca7302e..c40f6b1 100644
--- a/server/flow.go
+++ b/server/flow.go
@@ -1,10 +1,13 @@
package server
import (
+ "context"
_ "embed"
"encoding/json"
+ "fmt"
"github.com/google/uuid"
"github.com/julienschmidt/httprouter"
+ "golang.org/x/oauth2"
"html/template"
"log"
"net/http"
@@ -28,6 +31,7 @@ func init() {
log.Fatal("flow.go: Failed to parse flow popup HTML:", err)
}
flowPopupTemplate = pageParse
+
pageParse, err = template.New("pages").Parse(flowCallbackHtml)
if err != nil {
log.Fatal("flow.go: Failed to parse flow callback HTML:", err)
@@ -37,7 +41,7 @@ func init() {
func (h *HttpServer) flowPopup(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
err := flowPopupTemplate.Execute(rw, map[string]any{
- "ServiceName": flowPopupTemplate,
+ "ServiceName": h.serviceName,
"Origin": req.URL.Query().Get("origin"),
})
if err != nil {
@@ -46,7 +50,8 @@ func (h *HttpServer) flowPopup(rw http.ResponseWriter, req *http.Request, _ http
}
func (h *HttpServer) flowPopupPost(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
- login := h.manager.FindServiceFromLogin(req.PostFormValue("username"))
+ loginName := req.PostFormValue("loginname")
+ login := h.manager.FindServiceFromLogin(loginName)
if login == nil {
http.Error(rw, "No login service defined for this username", http.StatusBadRequest)
return
@@ -68,7 +73,7 @@ func (h *HttpServer) flowPopupPost(rw http.ResponseWriter, req *http.Request, _
// generate oauth2 config and redirect to authorize URL
oa2conf := login.OAuth2Config
oa2conf.RedirectURL = h.baseUrl + "/callback"
- nextUrl := oa2conf.AuthCodeURL(state)
+ nextUrl := oa2conf.AuthCodeURL(state, oauth2.SetAuthURLParam("login_name", loginName))
http.Redirect(rw, req, nextUrl, http.StatusFound)
}
@@ -92,14 +97,18 @@ func (h *HttpServer) flowCallback(rw http.ResponseWriter, req *http.Request, _ h
return
}
- exchange, err := v.sso.OAuth2Config.Exchange(req.Context(), q.Get("code"))
+ oa2conf := v.sso.OAuth2Config
+ oa2conf.RedirectURL = h.baseUrl + "/callback"
+ exchange, err := oa2conf.Exchange(context.Background(), q.Get("code"))
if err != nil {
+ fmt.Println("Failed exchange:", err)
http.Error(rw, "Failed to exchange code", http.StatusInternalServerError)
return
}
client := v.sso.OAuth2Config.Client(req.Context(), exchange)
v2, err := client.Get(v.sso.UserInfoEndpoint)
if err != nil {
+ fmt.Println("Failed to get userinfo:", err)
http.Error(rw, "Failed to get userinfo", http.StatusInternalServerError)
return
}
@@ -110,11 +119,15 @@ func (h *HttpServer) flowCallback(rw http.ResponseWriter, req *http.Request, _ h
}
var v3 any
if json.NewDecoder(v2.Body).Decode(&v3) != nil {
+ fmt.Println("Failed to decode userinfo:", err)
http.Error(rw, "Failed to decode userinfo JSON", http.StatusInternalServerError)
return
}
+ // TODO: generate signed mjwt object
+
_ = flowCallbackTemplate.Execute(rw, map[string]any{
+ "ServiceName": h.serviceName,
"TargetOrigin": v.targetOrigin,
"TargetMessage": v3,
})
diff --git a/server/server.go b/server/server.go
index fc6b16b..f0447ad 100644
--- a/server/server.go
+++ b/server/server.go
@@ -12,12 +12,13 @@ import (
)
type HttpServer struct {
- r *httprouter.Router
- baseUrl string
- manager *issuer.Manager
- signer mjwt.Signer
- flowState *cache.Cache[string, flowStateData]
- services map[string]struct{}
+ r *httprouter.Router
+ baseUrl string
+ serviceName string
+ manager *issuer.Manager
+ signer mjwt.Signer
+ flowState *cache.Cache[string, flowStateData]
+ services map[string]struct{}
}
type flowStateData struct {
@@ -25,7 +26,7 @@ type flowStateData struct {
targetOrigin string
}
-func NewHttpServer(listen, baseUrl string, clients []utils.JsonUrl, manager *issuer.Manager, signer mjwt.Signer) *http.Server {
+func NewHttpServer(listen, baseUrl, serviceName string, clients []utils.JsonUrl, manager *issuer.Manager, signer mjwt.Signer) *http.Server {
r := httprouter.New()
// remove last slash from baseUrl
@@ -38,15 +39,17 @@ func NewHttpServer(listen, baseUrl string, clients []utils.JsonUrl, manager *iss
services := make(map[string]struct{})
for _, i := range clients {
- services[i.Host] = struct{}{}
+ services[i.String()] = struct{}{}
}
hs := &HttpServer{
- r: r,
- baseUrl: baseUrl,
- manager: manager,
- signer: signer,
- services: services,
+ r: r,
+ baseUrl: baseUrl,
+ serviceName: serviceName,
+ manager: manager,
+ signer: signer,
+ flowState: cache.New[string, flowStateData](),
+ services: services,
}
r.GET("/", func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
diff --git a/test-client/index.html b/test-client/index.html
new file mode 100644
index 0000000..a6ec13a
--- /dev/null
+++ b/test-client/index.html
@@ -0,0 +1,75 @@
+
+
+
+ Test Client
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test-client/run.sh b/test-client/run.sh
new file mode 100755
index 0000000..60aacf8
--- /dev/null
+++ b/test-client/run.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+python3 -m http.server 2020