oidc: render HTML error pages for browser-facing failures
Add httpUserError() alongside httpError() for browser-facing error paths. It renders a styled HTML page using the AuthError template instead of returning plain text. Technical error details stay in server logs; the HTML page shows actionable messages derived from the HTTP status code: 401/403 → "You are not authorized. Please contact your administrator." 410 → "Your session has expired. Please try again." 400-499 → "The request could not be processed. Please try again." 500+ → "Something went wrong. Please try again later." Convert all httpError calls in oidc.go (OIDC callback, SSH check, registration confirm) to httpUserError. Machine-facing endpoints (noise, verify, key, health, debug) are unchanged. Fixes juanfont/headscale#3182
This commit is contained in:
parent
c15caff48c
commit
78990491da
5 changed files with 257 additions and 48 deletions
|
|
@ -7,6 +7,71 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAuthErrorTemplate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
result templates.AuthErrorResult
|
||||
}{
|
||||
{
|
||||
name: "bad_request",
|
||||
result: templates.AuthErrorResult{
|
||||
Title: "Headscale - Error",
|
||||
Heading: "Bad Request",
|
||||
Message: "The request could not be processed. Please try again.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "forbidden",
|
||||
result: templates.AuthErrorResult{
|
||||
Title: "Headscale - Error",
|
||||
Heading: "Forbidden",
|
||||
Message: "You are not authorized. Please contact your administrator.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "gone_expired",
|
||||
result: templates.AuthErrorResult{
|
||||
Title: "Headscale - Error",
|
||||
Heading: "Gone",
|
||||
Message: "Your session has expired. Please try again.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "internal_server_error",
|
||||
result: templates.AuthErrorResult{
|
||||
Title: "Headscale - Error",
|
||||
Heading: "Internal Server Error",
|
||||
Message: "Something went wrong. Please try again later.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
html := templates.AuthError(tt.result).Render()
|
||||
|
||||
// Verify the HTML contains expected structural elements
|
||||
assert.Contains(t, html, "<!DOCTYPE html>")
|
||||
assert.Contains(t, html, "<title>"+tt.result.Title+"</title>")
|
||||
assert.Contains(t, html, tt.result.Heading)
|
||||
assert.Contains(t, html, tt.result.Message)
|
||||
|
||||
// Verify Material for MkDocs design system CSS is present
|
||||
assert.Contains(t, html, "Material for MkDocs")
|
||||
assert.Contains(t, html, "Roboto")
|
||||
assert.Contains(t, html, ".md-typeset")
|
||||
|
||||
// Verify SVG elements are present
|
||||
assert.Contains(t, html, "<svg")
|
||||
assert.Contains(t, html, "class=\"headscale-logo\"")
|
||||
assert.Contains(t, html, "id=\"error-icon\"")
|
||||
|
||||
// Verify no success checkbox icon
|
||||
assert.NotContains(t, html, "id=\"checkbox\"")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthSuccessTemplate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue