service: accept forwarded groups from oauth2-proxy

This commit is contained in:
Brad Stein 2026-03-31 18:03:14 -03:00
parent db2c7ae023
commit a103a654f7
2 changed files with 51 additions and 7 deletions

View File

@ -160,22 +160,20 @@ func (a *App) withUIAuth(next http.HandlerFunc) http.HandlerFunc {
}
func (a *App) authorize(r *http.Request) (userContext, bool) {
user := strings.TrimSpace(r.Header.Get("X-Auth-Request-User"))
if user == "" {
user = strings.TrimSpace(r.Header.Get("X-Forwarded-User"))
}
user := firstNonEmptyHeader(r, "X-Auth-Request-User", "X-Forwarded-User", "X-Auth-Request-Email", "X-Forwarded-Email")
if user == "" {
return userContext{}, false
}
groups := splitHeaderList(r.Header.Get("X-Auth-Request-Groups"))
groups := splitHeaderList(firstNonEmptyHeader(r, "X-Auth-Request-Groups", "X-Forwarded-Groups"))
normalizedUser := normalizeUserValue(user)
for _, allowedUser := range a.settings.AllowedUsers {
if allowedUser == user {
if normalizeUserValue(allowedUser) == normalizedUser {
return userContext{Name: user, Groups: groups}, true
}
}
for _, group := range groups {
for _, allowed := range a.settings.AllowedGroups {
if group == allowed {
if normalizeGroupValue(group) == normalizeGroupValue(allowed) {
return userContext{Name: user, Groups: groups}, true
}
}
@ -183,6 +181,15 @@ func (a *App) authorize(r *http.Request) (userContext, bool) {
return userContext{Name: user, Groups: groups}, false
}
func firstNonEmptyHeader(r *http.Request, keys ...string) string {
for _, key := range keys {
if value := strings.TrimSpace(r.Header.Get(key)); value != "" {
return value
}
}
return ""
}
func splitHeaderList(raw string) []string {
if strings.TrimSpace(raw) == "" {
return nil
@ -198,6 +205,15 @@ func splitHeaderList(raw string) []string {
return out
}
func normalizeUserValue(raw string) string {
return strings.ToLower(strings.TrimSpace(raw))
}
func normalizeGroupValue(raw string) string {
value := strings.ToLower(strings.TrimSpace(raw))
return strings.TrimPrefix(value, "/")
}
func requestValue(r *http.Request, key string) string {
if err := r.ParseForm(); err == nil {
if value := strings.TrimSpace(r.Form.Get(key)); value != "" {

View File

@ -36,6 +36,34 @@ func TestUIAuthGuardsState(t *testing.T) {
}
}
func TestUIAuthAcceptsForwardedSlashGroups(t *testing.T) {
app := newTestApp(t)
handler := app.Handler()
req := httptest.NewRequest(http.MethodGet, "/api/state", nil)
req.Header.Set("X-Forwarded-User", "brad")
req.Header.Set("X-Forwarded-Groups", "/admin,/ops")
resp := httptest.NewRecorder()
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusOK {
t.Fatalf("expected ok, got %d: %s", resp.Code, resp.Body.String())
}
}
func TestUIAuthAcceptsForwardedEmailForAllowedUser(t *testing.T) {
app := newTestApp(t)
app.settings.AllowedUsers = []string{"brad.stein@gmail.com"}
handler := app.Handler()
req := httptest.NewRequest(http.MethodGet, "/api/state", nil)
req.Header.Set("X-Forwarded-Email", "Brad.Stein@gmail.com")
resp := httptest.NewRecorder()
handler.ServeHTTP(resp, req)
if resp.Code != http.StatusOK {
t.Fatalf("expected ok, got %d: %s", resp.Code, resp.Body.String())
}
}
func TestInternalSnapshotAndWatch(t *testing.T) {
app := newTestApp(t)
handler := app.Handler()