mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
198 lines
6.2 KiB
Go
198 lines
6.2 KiB
Go
package traefikoidc
|
|
|
|
import (
|
|
"testing"
|
|
"text/template"
|
|
)
|
|
|
|
func TestTemplatedHeaderValidation(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
header TemplatedHeader
|
|
expectedError string
|
|
}{
|
|
{
|
|
name: "Empty Name",
|
|
header: TemplatedHeader{Name: "", Value: "{{.Claims.email}}"},
|
|
expectedError: "header name cannot be empty",
|
|
},
|
|
{
|
|
name: "Empty Value",
|
|
header: TemplatedHeader{Name: "X-Email", Value: ""},
|
|
expectedError: "header value template cannot be empty",
|
|
},
|
|
{
|
|
name: "Not a Template",
|
|
header: TemplatedHeader{Name: "X-Email", Value: "static-value"},
|
|
expectedError: "header value 'static-value' does not appear to be a valid template (missing {{ }})",
|
|
},
|
|
{
|
|
name: "Lowercase claims",
|
|
header: TemplatedHeader{Name: "X-Email", Value: "{{.claims.email}}"},
|
|
expectedError: "header template '{{.claims.email}}' appears to use lowercase 'claims' - use '{{.Claims...' instead (case sensitive)",
|
|
},
|
|
{
|
|
name: "Lowercase accessToken",
|
|
header: TemplatedHeader{Name: "X-Token", Value: "Bearer {{.accessToken}}"},
|
|
expectedError: "header template 'Bearer {{.accessToken}}' appears to use lowercase 'accessToken' - use '{{.AccessToken...' instead (case sensitive)",
|
|
},
|
|
{
|
|
name: "Lowercase idToken",
|
|
header: TemplatedHeader{Name: "X-Token", Value: "Bearer {{.idToken}}"},
|
|
expectedError: "header template 'Bearer {{.idToken}}' appears to use lowercase 'idToken' - use '{{.IdToken...' instead (case sensitive)",
|
|
},
|
|
{
|
|
name: "Lowercase refreshToken",
|
|
header: TemplatedHeader{Name: "X-Refresh", Value: "Bearer {{.refreshToken}}"},
|
|
expectedError: "header template 'Bearer {{.refreshToken}}' appears to use lowercase 'refreshToken' - use '{{.RefreshToken...' instead (case sensitive)",
|
|
},
|
|
{
|
|
name: "Valid Template",
|
|
header: TemplatedHeader{Name: "X-Email", Value: "{{.Claims.email}}"},
|
|
expectedError: "",
|
|
},
|
|
{
|
|
name: "Valid Bearer Token Template",
|
|
header: TemplatedHeader{Name: "Authorization", Value: "Bearer {{.AccessToken}}"},
|
|
expectedError: "",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
config := &Config{
|
|
ProviderURL: "https://provider.com",
|
|
CallbackURL: "/callback",
|
|
ClientID: "client-id",
|
|
ClientSecret: "client-secret",
|
|
SessionEncryptionKey: "this-is-a-long-enough-encryption-key",
|
|
RateLimit: 10, // Adding minimum required rate limit
|
|
Headers: []TemplatedHeader{tc.header},
|
|
}
|
|
|
|
err := config.Validate()
|
|
if tc.expectedError == "" {
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
} else {
|
|
if err == nil {
|
|
t.Errorf("Expected error: %s, got nil", tc.expectedError)
|
|
} else if err.Error() != tc.expectedError {
|
|
t.Errorf("Expected error: %s, got: %s", tc.expectedError, err.Error())
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTemplateParsingInNew(t *testing.T) {
|
|
// Test successful parsing of templates during middleware creation
|
|
tests := []struct {
|
|
name string
|
|
headers []TemplatedHeader
|
|
expectedTemplates int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Single Valid Template",
|
|
headers: []TemplatedHeader{
|
|
{Name: "X-Email", Value: "{{.Claims.email}}"},
|
|
},
|
|
expectedTemplates: 1,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Multiple Valid Templates",
|
|
headers: []TemplatedHeader{
|
|
{Name: "X-Email", Value: "{{.Claims.email}}"},
|
|
{Name: "X-User-ID", Value: "{{.Claims.sub}}"},
|
|
{Name: "Authorization", Value: "Bearer {{.AccessToken}}"},
|
|
},
|
|
expectedTemplates: 3,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Invalid Template",
|
|
headers: []TemplatedHeader{
|
|
{Name: "X-Email", Value: "{{.Claims.email"}, // Missing closing braces
|
|
},
|
|
expectedTemplates: 0,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Mix of Valid and Invalid Templates",
|
|
headers: []TemplatedHeader{
|
|
{Name: "X-Email", Value: "{{.Claims.email}}"},
|
|
{Name: "X-Invalid", Value: "{{if .Claims.admin}}Admin{{end"}, // Invalid template
|
|
},
|
|
expectedTemplates: 1, // Only the valid template should be parsed
|
|
expectError: true, // We expect an error for the invalid template, but we'll handle it
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
// For testing template parsing, we'll directly try to parse the templates instead of using New()
|
|
// This avoids the provider discovery that would fail in tests
|
|
headerTemplates := make(map[string]*template.Template)
|
|
|
|
// Special handling for the mixed valid/invalid templates case
|
|
if tc.name == "Mix of Valid and Invalid Templates" {
|
|
// Process templates one at a time so we can still have valid templates
|
|
for _, header := range tc.headers {
|
|
tmpl, err := template.New(header.Name).Parse(header.Value)
|
|
if err != nil {
|
|
// We expect an error for the invalid template
|
|
if !tc.expectError {
|
|
t.Errorf("Unexpected error parsing template %s: %v", header.Name, err)
|
|
}
|
|
// Skip this template but continue processing others
|
|
continue
|
|
}
|
|
headerTemplates[header.Name] = tmpl
|
|
}
|
|
} else {
|
|
// Normal handling for other test cases
|
|
var parseErr error
|
|
for _, header := range tc.headers {
|
|
tmpl, err := template.New(header.Name).Parse(header.Value)
|
|
if err != nil {
|
|
parseErr = err
|
|
break
|
|
}
|
|
headerTemplates[header.Name] = tmpl
|
|
}
|
|
|
|
if tc.expectError {
|
|
if parseErr == nil {
|
|
t.Error("Expected error parsing templates but got nil")
|
|
}
|
|
return
|
|
}
|
|
|
|
if parseErr != nil {
|
|
t.Fatalf("Unexpected error: %v", parseErr)
|
|
}
|
|
}
|
|
|
|
// Check the number of parsed templates
|
|
if len(headerTemplates) != tc.expectedTemplates {
|
|
t.Errorf("Expected %d parsed templates, got %d", tc.expectedTemplates, len(headerTemplates))
|
|
}
|
|
|
|
// Check each template was parsed
|
|
for _, header := range tc.headers {
|
|
// Skip the known invalid templates
|
|
if header.Value == "{{.Claims.email" || header.Value == "{{if .Claims.admin}}Admin{{end" {
|
|
continue
|
|
}
|
|
|
|
if _, ok := headerTemplates[header.Name]; !ok {
|
|
t.Errorf("Template for header %s was not parsed", header.Name)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|