362 lines
10 KiB
Go
362 lines
10 KiB
Go
package auth
|
|
|
|
import (
|
|
"bytes"
|
|
"log/slog"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestInitializeAuthConfig(t *testing.T) {
|
|
// Setup test environment variables
|
|
testEnv := map[string]string{
|
|
"AWS_REGION": "us-east-2",
|
|
"COGNITO_USER_POOL_ID": "us-east-2_testpool",
|
|
"COGNITO_CLIENT_ID": "test-client-id",
|
|
"COGNITO_CLIENT_SECRET": "test-client-secret",
|
|
"COGNITO_DOMAIN": "test-domain.auth.us-east-2.amazoncognito.com",
|
|
"COGNITO_LOGIN_PATH": "/custom-login",
|
|
"COGNITO_CALLBACK_PATH": "/custom-callback",
|
|
"COGNITO_HOME_PATH": "/custom-home",
|
|
"COGNITO_LOGOUT_PATH": "/custom-logout",
|
|
"DEBUG": "true",
|
|
}
|
|
|
|
// Set environment variables
|
|
for k, v := range testEnv {
|
|
os.Setenv(k, v)
|
|
}
|
|
defer func() {
|
|
// Cleanup environment variables after test
|
|
for k := range testEnv {
|
|
os.Unsetenv(k)
|
|
}
|
|
}()
|
|
|
|
// Create test logger
|
|
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
|
Level: slog.LevelDebug,
|
|
})
|
|
testLogger := slog.New(logHandler)
|
|
|
|
// Test base URL
|
|
baseURL := "https://example.com"
|
|
|
|
// Create config instance
|
|
cfg := &CognitoConfig{}
|
|
err := cfg.InitializeAuthConfig(baseURL, testLogger)
|
|
|
|
// Test initialization success
|
|
if err != nil {
|
|
t.Errorf("InitializeAuthConfig failed: %v", err)
|
|
}
|
|
|
|
// Test all fields
|
|
tests := []struct {
|
|
name string
|
|
got string
|
|
expected string
|
|
}{
|
|
{"AuthRegion", cfg.AuthRegion, "us-east-2"},
|
|
{"AuthUserPoolID", cfg.AuthUserPoolID, "us-east-2_testpool"},
|
|
{"AuthClientID", cfg.AuthClientID, "test-client-id"},
|
|
{"AuthClientSecret", cfg.AuthClientSecret, "test-client-secret"},
|
|
{"AuthDomain", cfg.AuthDomain, "test-domain.auth.us-east-2.amazoncognito.com"},
|
|
{"AuthLoginPath", cfg.AuthLoginPath, "/custom-login"},
|
|
{"AuthCallbackPath", cfg.AuthCallbackPath, "/custom-callback"},
|
|
{"AuthHomePath", cfg.AuthHomePath, "/custom-home"},
|
|
{"AuthLogoutPath", cfg.AuthLogoutPath, "/custom-logout"},
|
|
{"AuthRedirectURI", cfg.AuthRedirectURI, "https://example.com/custom-callback"},
|
|
{"AuthTokenURL", cfg.AuthTokenURL, "test-domain.auth.us-east-2.amazoncognito.com/oauth2/token"},
|
|
{"AuthURL", cfg.AuthURL, "test-domain.auth.us-east-2.amazoncognito.com/oauth2/authorize"},
|
|
{"AuthJwksURL", cfg.AuthJwksURL, "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_testpool/.well-known/jwks.json"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.got != tt.expected {
|
|
t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test logger
|
|
if cfg.AuthLogger == nil {
|
|
t.Error("AuthLogger is nil")
|
|
}
|
|
|
|
// Test route permissions map initialization
|
|
if cfg.AuthRoutePermissions == nil {
|
|
t.Error("AuthRoutePermissions map was not initialized")
|
|
}
|
|
}
|
|
|
|
func TestInitializeAuthConfigWithDefaults(t *testing.T) {
|
|
// Clear any existing environment variables
|
|
envVars := []string{
|
|
"AWS_REGION",
|
|
"COGNITO_LOGIN_PATH",
|
|
"COGNITO_CALLBACK_PATH",
|
|
"COGNITO_HOME_PATH",
|
|
"COGNITO_LOGOUT_PATH",
|
|
}
|
|
for _, env := range envVars {
|
|
os.Unsetenv(env)
|
|
}
|
|
|
|
// Set required variables
|
|
os.Setenv("COGNITO_USER_POOL_ID", "us-east-2_testpool")
|
|
os.Setenv("COGNITO_CLIENT_ID", "test-client-id")
|
|
os.Setenv("COGNITO_CLIENT_SECRET", "test-client-secret")
|
|
os.Setenv("COGNITO_DOMAIN", "test-domain.auth.us-east-2.amazoncognito.com")
|
|
|
|
defer func() {
|
|
for _, env := range append(envVars, "COGNITO_USER_POOL_ID", "COGNITO_CLIENT_ID", "COGNITO_CLIENT_SECRET", "COGNITO_DOMAIN") {
|
|
os.Unsetenv(env)
|
|
}
|
|
}()
|
|
|
|
cfg := &CognitoConfig{}
|
|
err := cfg.InitializeAuthConfig("https://example.com", nil)
|
|
|
|
if err != nil {
|
|
t.Errorf("InitializeAuthConfig failed: %v", err)
|
|
}
|
|
|
|
// Test default values
|
|
defaults := []struct {
|
|
name string
|
|
got string
|
|
expected string
|
|
}{
|
|
{"AuthRegion", cfg.AuthRegion, "us-east-2"},
|
|
{"AuthLoginPath", cfg.AuthLoginPath, "/login"},
|
|
{"AuthCallbackPath", cfg.AuthCallbackPath, "/login-callback"},
|
|
{"AuthHomePath", cfg.AuthHomePath, "/home"},
|
|
{"AuthLogoutPath", cfg.AuthLogoutPath, "/logout"},
|
|
}
|
|
|
|
for _, tt := range defaults {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.got != tt.expected {
|
|
t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGettersAndSetters(t *testing.T) {
|
|
// Create a test instance
|
|
cfg := &CognitoConfig{}
|
|
|
|
// Test logger
|
|
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
|
Level: slog.LevelDebug,
|
|
})
|
|
testLogger := slog.New(logHandler)
|
|
|
|
// Test route permissions
|
|
testPermissions := map[string][]string{
|
|
"/api/test": {"read", "write"},
|
|
"/api/admin": {"admin"},
|
|
}
|
|
|
|
// Test cases for all getter/setter pairs
|
|
testCases := []struct {
|
|
name string
|
|
setter func()
|
|
getter func() interface{}
|
|
expected interface{}
|
|
}{
|
|
{
|
|
name: "AuthRegion",
|
|
setter: func() { cfg.SetAuthRegion("us-west-2") },
|
|
getter: func() interface{} { return cfg.GetAuthRegion() },
|
|
expected: "us-west-2",
|
|
},
|
|
{
|
|
name: "AuthUserPoolID",
|
|
setter: func() { cfg.SetAuthUserPoolID("us-west-2_testpool") },
|
|
getter: func() interface{} { return cfg.GetAuthUserPoolID() },
|
|
expected: "us-west-2_testpool",
|
|
},
|
|
{
|
|
name: "AuthClientSecret",
|
|
setter: func() { cfg.SetAuthClientSecret("test-secret") },
|
|
getter: func() interface{} { return cfg.GetAuthClientSecret() },
|
|
expected: "test-secret",
|
|
},
|
|
{
|
|
name: "AuthDomain",
|
|
setter: func() { cfg.SetAuthDomain("test-domain.com") },
|
|
getter: func() interface{} { return cfg.GetAuthDomain() },
|
|
expected: "test-domain.com",
|
|
},
|
|
{
|
|
name: "AuthClientID",
|
|
setter: func() { cfg.SetAuthClientID("test-client-id") },
|
|
getter: func() interface{} { return cfg.GetAuthClientID() },
|
|
expected: "test-client-id",
|
|
},
|
|
{
|
|
name: "AuthRedirectURI",
|
|
setter: func() { cfg.SetAuthRedirectURI("https://example.com/callback") },
|
|
getter: func() interface{} { return cfg.GetAuthRedirectURI() },
|
|
expected: "https://example.com/callback",
|
|
},
|
|
{
|
|
name: "AuthTokenURL",
|
|
setter: func() { cfg.SetAuthTokenURL("https://example.com/token") },
|
|
getter: func() interface{} { return cfg.GetAuthTokenURL() },
|
|
expected: "https://example.com/token",
|
|
},
|
|
{
|
|
name: "AuthJwksURL",
|
|
setter: func() { cfg.SetAuthJwksURL("https://example.com/jwks.json") },
|
|
getter: func() interface{} { return cfg.GetAuthJwksURL() },
|
|
expected: "https://example.com/jwks.json",
|
|
},
|
|
{
|
|
name: "AuthURL",
|
|
setter: func() { cfg.SetAuthURL("https://example.com/auth") },
|
|
getter: func() interface{} { return cfg.GetAuthURL() },
|
|
expected: "https://example.com/auth",
|
|
},
|
|
{
|
|
name: "AuthLoginPath",
|
|
setter: func() { cfg.SetAuthLoginPath("/custom-login") },
|
|
getter: func() interface{} { return cfg.GetAuthLoginPath() },
|
|
expected: "/custom-login",
|
|
},
|
|
{
|
|
name: "AuthCallbackPath",
|
|
setter: func() { cfg.SetAuthCallbackPath("/custom-callback") },
|
|
getter: func() interface{} { return cfg.GetAuthCallbackPath() },
|
|
expected: "/custom-callback",
|
|
},
|
|
{
|
|
name: "AuthHomePath",
|
|
setter: func() { cfg.SetAuthHomePath("/custom-home") },
|
|
getter: func() interface{} { return cfg.GetAuthHomePath() },
|
|
expected: "/custom-home",
|
|
},
|
|
{
|
|
name: "AuthLogoutPath",
|
|
setter: func() { cfg.SetAuthLogoutPath("/custom-logout") },
|
|
getter: func() interface{} { return cfg.GetAuthLogoutPath() },
|
|
expected: "/custom-logout",
|
|
},
|
|
{
|
|
name: "AuthLogger",
|
|
setter: func() { cfg.SetAuthLogger(testLogger) },
|
|
getter: func() interface{} { return cfg.GetAuthLogger() },
|
|
expected: testLogger,
|
|
},
|
|
{
|
|
name: "AuthRoutePermissions",
|
|
setter: func() { cfg.SetAuthRoutePermissions(testPermissions) },
|
|
getter: func() interface{} { return cfg.GetAuthRoutePermissions() },
|
|
expected: testPermissions,
|
|
},
|
|
}
|
|
|
|
// Run all test cases
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
// Execute setter
|
|
tc.setter()
|
|
|
|
// Get value and compare with expected
|
|
got := tc.getter()
|
|
|
|
// Handle different types of comparisons
|
|
switch expected := tc.expected.(type) {
|
|
case map[string][]string:
|
|
gotMap, ok := got.(map[string][]string)
|
|
if !ok {
|
|
t.Errorf("failed to convert to map[string][]string: got type %T", got)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(gotMap, expected) {
|
|
t.Errorf("got %v, want %v", gotMap, expected)
|
|
}
|
|
case *slog.Logger:
|
|
gotLogger, ok := got.(*slog.Logger)
|
|
if !ok {
|
|
t.Errorf("failed to convert to *slog.Logger: got type %T", got)
|
|
return
|
|
}
|
|
if gotLogger != expected {
|
|
t.Errorf("got %v, want %v", gotLogger, expected)
|
|
}
|
|
default:
|
|
if got != tc.expected {
|
|
t.Errorf("got %v, want %v", got, tc.expected)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPrettyPrintDebugOnly(t *testing.T) {
|
|
// Test with DEBUG=true
|
|
os.Setenv("DEBUG", "true")
|
|
defer os.Unsetenv("DEBUG")
|
|
|
|
cfg := &CognitoConfig{
|
|
AuthClientID: "test-client-id",
|
|
AuthClientSecret: "test-secret",
|
|
AuthRedirectURI: "https://example.com/callback",
|
|
AuthRoutePermissions: map[string][]string{
|
|
"/test": {"read"},
|
|
},
|
|
}
|
|
|
|
// Create a buffer to capture log output
|
|
var buf bytes.Buffer
|
|
|
|
// Create a logger that writes to our buffer
|
|
logHandler := slog.NewTextHandler(&buf, &slog.HandlerOptions{
|
|
Level: slog.LevelDebug,
|
|
})
|
|
testLogger := slog.New(logHandler)
|
|
|
|
// Set the logger in the config
|
|
cfg.SetAuthLogger(testLogger)
|
|
|
|
// Call the method
|
|
cfg.PrettyPrintDebugOnly()
|
|
|
|
// Get the output
|
|
output := buf.String()
|
|
|
|
// Verify output contains expected values - adjust these to match actual format
|
|
expectedStrings := []string{
|
|
"level=DEBUG",
|
|
"msg=\"CognitoConfig details\"",
|
|
"AuthClientID=test-client-id",
|
|
"AuthClientSecret=test-secret",
|
|
"AuthRedirectURI=https://example.com/callback",
|
|
}
|
|
|
|
for _, expected := range expectedStrings {
|
|
if !strings.Contains(output, expected) {
|
|
t.Errorf("Expected output to contain %q", expected)
|
|
}
|
|
}
|
|
|
|
// Verify route permissions are included
|
|
if !strings.Contains(output, "/test") || !strings.Contains(output, "read") {
|
|
t.Errorf("Expected output to contain route permissions for /test")
|
|
}
|
|
|
|
// Test with DEBUG=false
|
|
os.Setenv("DEBUG", "false")
|
|
buf.Reset()
|
|
|
|
cfg.PrettyPrintDebugOnly()
|
|
|
|
}
|