Add SSO login support
- Add [sso] config section with redirect_uri - Create mcdsl/sso client when SSO is configured - Add /login (landing page), /sso/redirect, /sso/callback routes - Add /logout route - Update login template with SSO landing page variant - Bump mcdsl to v1.6.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
mcdsso "git.wntrmute.dev/mc/mcdsl/sso"
|
||||
"git.wntrmute.dev/mc/mcdsl/web"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,14 @@ func (ws *WebServer) registerRoutes(r chi.Router) {
|
||||
r.Get("/", ws.handleRoot)
|
||||
r.HandleFunc("/init", ws.handleInit)
|
||||
r.HandleFunc("/unseal", ws.handleUnseal)
|
||||
r.HandleFunc("/login", ws.handleLogin)
|
||||
if ws.ssoClient != nil {
|
||||
r.Get("/login", ws.handleSSOLogin)
|
||||
r.Get("/sso/redirect", ws.handleSSORedirect)
|
||||
r.Get("/sso/callback", ws.handleSSOCallback)
|
||||
} else {
|
||||
r.HandleFunc("/login", ws.handleLogin)
|
||||
}
|
||||
r.Get("/logout", ws.handleLogout)
|
||||
r.Get("/dashboard", ws.requireAuth(ws.handleDashboard))
|
||||
r.Post("/dashboard/mount-ca", ws.requireAuth(ws.handleDashboardMountCA))
|
||||
r.Post("/dashboard/mount-engine", ws.requireAuth(ws.handleDashboardMountEngine))
|
||||
@@ -236,6 +244,43 @@ func (ws *WebServer) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// handleSSOLogin renders a landing page with a "Sign in with MCIAS" button.
|
||||
func (ws *WebServer) handleSSOLogin(w http.ResponseWriter, r *http.Request) {
|
||||
state, _ := ws.vault.Status(r.Context())
|
||||
if state != "unsealed" {
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
ws.renderTemplate(w, "login.html", map[string]interface{}{"SSO": true})
|
||||
}
|
||||
|
||||
// handleSSORedirect initiates the SSO redirect to MCIAS.
|
||||
func (ws *WebServer) handleSSORedirect(w http.ResponseWriter, r *http.Request) {
|
||||
if err := mcdsso.RedirectToLogin(w, r, ws.ssoClient, "metacrypt"); err != nil {
|
||||
ws.logger.Error("sso: redirect to login", "error", err)
|
||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// handleSSOCallback exchanges the authorization code for a JWT and sets the session.
|
||||
func (ws *WebServer) handleSSOCallback(w http.ResponseWriter, r *http.Request) {
|
||||
token, returnTo, err := mcdsso.HandleCallback(w, r, ws.ssoClient, "metacrypt")
|
||||
if err != nil {
|
||||
ws.logger.Error("sso: callback", "error", err)
|
||||
http.Error(w, "Login failed. Please try again.", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
web.SetSessionCookie(w, "metacrypt_token", token)
|
||||
http.Redirect(w, r, returnTo, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handleLogout clears the session and redirects to login.
|
||||
func (ws *WebServer) handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||
web.ClearSessionCookie(w, "metacrypt_token")
|
||||
http.Redirect(w, r, "/login", http.StatusFound)
|
||||
}
|
||||
|
||||
func (ws *WebServer) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
||||
info := tokenInfoFromContext(r.Context())
|
||||
token := extractCookie(r)
|
||||
|
||||
Reference in New Issue
Block a user