package identityprovider import ( "testing" "vpn-platform/backend/internal/model" "vpn-platform/backend/internal/service" "vpn-platform/backend/internal/store" ) func TestProfileNamesRequireMatchingIssuerAppAndSubject(t *testing.T) { previous := store.DB t.Cleanup(func() { if store.DB != nil { if db, err := store.DB.DB(); err == nil { _ = db.Close() } } store.DB = previous }) if err := store.Init(t.TempDir()); err != nil { t.Fatal(err) } idp := model.IdentityProvider{ID: 1, Enabled: true, AppID: "cli_current"} if err := store.DB.Create(&idp).Error; err != nil { t.Fatal(err) } issuer := "https://vpn.example.com/id" subject := "tenant:ou_123" if err := saveProfile(issuer, idp, accessData{Subject: subject, Name: "First name"}); err != nil { t.Fatal(err) } if err := saveProfile(issuer, idp, accessData{Subject: subject, Name: "Updated name"}); err != nil { t.Fatal(err) } tunnel := &model.Tunnel{Protocol: "openvpn", Config: service.ConfigJSON(map[string]interface{}{ "auth_mode": "oidc", "oidc_provider": "builtin", "oidc_issuer": issuer, })} if names := ProfileNames(tunnel, []string{subject, "tenant:ou_other"}); len(names) != 1 || names[subject] != "Updated name" { t.Fatalf("profile did not follow stable subject: %v", names) } other := *tunnel other.Config = service.ConfigJSON(map[string]interface{}{ "auth_mode": "oidc", "oidc_provider": "builtin", "oidc_issuer": "https://other.example.com/id", }) if names := ProfileNames(&other, []string{subject}); len(names) != 0 { t.Fatalf("profile leaked across issuer: %v", names) } if err := store.DB.Model(&idp).Update("app_id", "cli_other").Error; err != nil { t.Fatal(err) } if names := ProfileNames(tunnel, []string{subject}); len(names) != 0 { t.Fatalf("profile leaked across app: %v", names) } }