Show SSO landing page instead of immediate redirect

The login page now shows the service name and a "Sign in with MCIAS"
button instead of immediately redirecting to MCIAS. This lets the user
know what service they are logging into before the redirect.

- GET /login renders the landing page with SSO button
- GET /sso/redirect initiates the actual SSO redirect
- Non-SSO login form still works when SSO is not configured

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 16:40:25 -07:00
parent 908aaed168
commit 8eeab91cbd
4 changed files with 19 additions and 4 deletions

View File

@@ -133,8 +133,17 @@ func (s *Server) handleLoginSubmit(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", http.StatusSeeOther)
}
// handleSSOLogin redirects the user to MCIAS for SSO login.
// handleSSOLogin renders a landing page with a "Sign in" button that
// initiates the SSO redirect to MCIAS.
func (s *Server) handleSSOLogin(w http.ResponseWriter, r *http.Request) {
s.templates.render(w, "login", map[string]any{
"SSO": true,
"Session": false,
})
}
// handleSSORedirect initiates the SSO redirect to MCIAS.
func (s *Server) handleSSORedirect(w http.ResponseWriter, r *http.Request) {
if err := mcdsso.RedirectToLogin(w, r, s.ssoClient, "mcr"); err != nil {
log.Printf("sso: redirect to login: %v", err)
http.Error(w, "internal error", http.StatusInternalServerError)

View File

@@ -95,6 +95,7 @@ func (s *Server) buildRouter() chi.Router {
// Public routes (no session required).
if s.ssoClient != nil {
r.Get("/login", s.handleSSOLogin)
r.Get("/sso/redirect", s.handleSSORedirect)
r.Get("/sso/callback", s.handleSSOCallback)
} else {
r.Get("/login", s.handleLoginPage)

View File

@@ -245,8 +245,8 @@ func TestLoginPageRenders(t *testing.T) {
}
body := rec.Body.String()
if !strings.Contains(body, "MCR Login") {
t.Error("login page does not contain 'MCR Login'")
if !strings.Contains(body, "Metacircular Container Registry") {
t.Error("login page does not contain 'Metacircular Container Registry'")
}
if !strings.Contains(body, "_csrf") {
t.Error("login page does not contain CSRF token field")

View File

@@ -2,10 +2,14 @@
{{define "content"}}
<div class="login-container">
<h1>MCR Login</h1>
<h1>Metacircular Container Registry</h1>
{{if .Error}}
<div class="error">{{.Error}}</div>
{{end}}
{{if .SSO}}
<p>Sign in to manage container images, policies, and audit logs.</p>
<a href="/sso/redirect" class="btn">Sign in with MCIAS</a>
{{else}}
<form method="POST" action="/login">
<input type="hidden" name="_csrf" value="{{.CSRFToken}}">
<div class="form-group">
@@ -18,5 +22,6 @@
</div>
<button type="submit">Sign In</button>
</form>
{{end}}
</div>
{{end}}