From f323690049b7ac11b40c4f7441c176ce7257422c Mon Sep 17 00:00:00 2001 From: Ryan Richard Date: Thu, 23 May 2024 13:35:31 -0700 Subject: [PATCH] refactor upstream refresh test helpers to be more specific to IDP type --- .../active_directory_upstream_watcher.go | 10 +- .../active_directory_upstream_watcher_test.go | 40 +-- .../endpoints/token/token_handler_test.go | 231 +++++++++++------- .../resolvedldap/resolved_ldap_provider.go | 2 +- .../upstreamprovider/upsteam_provider.go | 6 +- .../testutil/oidctestutil/testldapprovider.go | 25 +- .../testutil/oidctestutil/testoidcprovider.go | 21 +- .../testutil/testidplister/testidplister.go | 136 +++++++---- internal/upstreamldap/upstreamldap.go | 4 +- internal/upstreamldap/upstreamldap_test.go | 18 +- 10 files changed, 295 insertions(+), 198 deletions(-) diff --git a/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher.go b/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher.go index 42aa65097..fa5465cc9 100644 --- a/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher.go +++ b/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher.go @@ -344,7 +344,7 @@ func (c *activeDirectoryWatcherController) validateUpstream(ctx context.Context, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){ "objectGUID": microsoftUUIDFromBinaryAttr("objectGUID"), }, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ pwdLastSetAttribute: attributeUnchangedSinceLogin(pwdLastSetAttribute), userAccountControlAttribute: validUserAccountControl, userAccountControlComputedAttribute: validComputedUserAccountControl, @@ -445,7 +445,7 @@ func getDomainFromDistinguishedName(distinguishedName string) (string, error) { } //nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality -var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.RefreshAttributes) error { +var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.LDAPRefreshAttributes) error { userAccountControl, err := strconv.Atoi(entry.GetAttributeValue(userAccountControlAttribute)) if err != nil { return err @@ -459,7 +459,7 @@ var validUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.Refresh } //nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality -var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.RefreshAttributes) error { +var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider.LDAPRefreshAttributes) error { userAccountControl, err := strconv.Atoi(entry.GetAttributeValue(userAccountControlComputedAttribute)) if err != nil { return err @@ -473,8 +473,8 @@ var validComputedUserAccountControl = func(entry *ldap.Entry, _ upstreamprovider } //nolint:gochecknoglobals // this needs to be a global variable so that tests can check pointer equality -var attributeUnchangedSinceLogin = func(attribute string) func(*ldap.Entry, upstreamprovider.RefreshAttributes) error { - return func(entry *ldap.Entry, storedAttributes upstreamprovider.RefreshAttributes) error { +var attributeUnchangedSinceLogin = func(attribute string) func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error { + return func(entry *ldap.Entry, storedAttributes upstreamprovider.LDAPRefreshAttributes) error { prevAttributeValue := storedAttributes.AdditionalAttributes[attribute] newValues := entry.GetRawAttributeValues(attribute) diff --git a/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher_test.go b/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher_test.go index ed12e87d4..dd148e670 100644 --- a/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher_test.go +++ b/internal/controller/supervisorconfig/activedirectoryupstreamwatcher/active_directory_upstream_watcher_test.go @@ -228,7 +228,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -571,7 +571,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -641,7 +641,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: "sAMAccountName", }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -714,7 +714,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -794,7 +794,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -858,7 +858,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1009,7 +1009,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1159,7 +1159,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1231,7 +1231,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1498,7 +1498,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, GroupAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"sAMAccountName": groupSAMAccountNameWithDomainSuffix}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1558,7 +1558,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1622,7 +1622,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1686,7 +1686,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1898,7 +1898,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { GroupNameAttribute: testGroupSearchNameAttrName, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -1961,7 +1961,7 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { SkipGroupRefresh: true, }, UIDAttributeParsingOverrides: map[string]func(*ldap.Entry) (string, error){"objectGUID": microsoftUUIDFromBinaryAttr("objectGUID")}, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ "pwdLastSet": attributeUnchangedSinceLogin("pwdLastSet"), "userAccountControl": validUserAccountControl, "msDS-User-Account-Control-Computed": validComputedUserAccountControl, @@ -2102,8 +2102,8 @@ func TestActiveDirectoryUpstreamWatcherControllerSync(t *testing.T) { expectedRefreshAttributeChecks := copyOfExpectedValueForResultingCache.RefreshAttributeChecks actualRefreshAttributeChecks := actualConfig.RefreshAttributeChecks - copyOfExpectedValueForResultingCache.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{} - actualConfig.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{} + copyOfExpectedValueForResultingCache.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{} + actualConfig.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{} require.Equal(t, len(expectedRefreshAttributeChecks), len(actualRefreshAttributeChecks)) for k, v := range expectedRefreshAttributeChecks { require.NotNil(t, actualRefreshAttributeChecks[k]) @@ -2352,7 +2352,7 @@ func TestValidUserAccountControl(t *testing.T) { for _, test := range tests { tt := test t.Run(tt.name, func(t *testing.T) { - err := validUserAccountControl(tt.entry, upstreamprovider.RefreshAttributes{}) + err := validUserAccountControl(tt.entry, upstreamprovider.LDAPRefreshAttributes{}) if tt.wantErr != "" { require.Error(t, err) @@ -2413,7 +2413,7 @@ func TestValidComputedUserAccountControl(t *testing.T) { for _, test := range tests { tt := test t.Run(tt.name, func(t *testing.T) { - err := validComputedUserAccountControl(tt.entry, upstreamprovider.RefreshAttributes{}) + err := validComputedUserAccountControl(tt.entry, upstreamprovider.LDAPRefreshAttributes{}) if tt.wantErr != "" { require.Error(t, err) @@ -2488,7 +2488,7 @@ func TestAttributeUnchangedSinceLogin(t *testing.T) { tt := test t.Run(tt.name, func(t *testing.T) { initialValRawEncoded := base64.RawURLEncoding.EncodeToString([]byte(initialVal)) - err := attributeUnchangedSinceLogin(attributeName)(tt.entry, upstreamprovider.RefreshAttributes{AdditionalAttributes: map[string]string{attributeName: initialValRawEncoded}}) + err := attributeUnchangedSinceLogin(attributeName)(tt.entry, upstreamprovider.LDAPRefreshAttributes{AdditionalAttributes: map[string]string{attributeName: initialValRawEncoded}}) if tt.wantErr != "" { require.Error(t, err) require.Equal(t, tt.wantErr, err.Error()) diff --git a/internal/federationdomain/endpoints/token/token_handler_test.go b/internal/federationdomain/endpoints/token/token_handler_test.go index 5d11690c1..13be648f4 100644 --- a/internal/federationdomain/endpoints/token/token_handler_test.go +++ b/internal/federationdomain/endpoints/token/token_handler_test.go @@ -269,30 +269,43 @@ var ( } ) -type expectedUpstreamRefresh struct { +type expectedOIDCUpstreamRefresh struct { performedByUpstreamName string - args *oidctestutil.PerformRefreshArgs + args *oidctestutil.PerformOIDCRefreshArgs } -type expectedUpstreamValidateTokens struct { +type expectedLDAPUpstreamRefresh struct { + performedByUpstreamName string + args *oidctestutil.PerformLDAPRefreshArgs +} + +type expectedGithubUpstreamRefresh struct { + performedByUpstreamName string + args *oidctestutil.GetUserArgs +} + +type expectedOIDCUpstreamValidateTokens struct { performedByUpstreamName string args *oidctestutil.ValidateTokenAndMergeWithUserInfoArgs } type tokenEndpointResponseExpectedValues struct { - wantStatus int - wantSuccessBodyFields []string - wantErrorResponseBody string - wantClientID string - wantRequestedScopes []string - wantGrantedScopes []string - wantUsername string - wantGroups []string - wantUpstreamRefreshCall *expectedUpstreamRefresh - wantUpstreamOIDCValidateTokenCall *expectedUpstreamValidateTokens - wantCustomSessionDataStored *psession.CustomSessionData - wantWarnings []RecordedWarning - wantAdditionalClaims map[string]interface{} + wantStatus int + wantSuccessBodyFields []string + wantErrorResponseBody string + wantClientID string + wantRequestedScopes []string + wantGrantedScopes []string + wantUsername string + wantGroups []string + wantOIDCUpstreamRefreshCall *expectedOIDCUpstreamRefresh + wantLDAPUpstreamRefreshCall *expectedLDAPUpstreamRefresh + wantActiveDirectoryUpstreamRefreshCall *expectedLDAPUpstreamRefresh + wantGithubUpstreamRefreshCall *expectedGithubUpstreamRefresh + wantUpstreamOIDCValidateTokenCall *expectedOIDCUpstreamValidateTokens + wantCustomSessionDataStored *psession.CustomSessionData + wantWarnings []RecordedWarning + wantAdditionalClaims map[string]interface{} // The expected lifetime of the ID tokens issued by authcode exchange and refresh, but not token exchange. // When zero, will assume that the test wants the default value for ID token lifetime. wantIDTokenLifetimeSeconds int @@ -1925,48 +1938,63 @@ func TestRefreshGrant(t *testing.T) { return sessionData } - happyOIDCUpstreamRefreshCall := func() *expectedUpstreamRefresh { - return &expectedUpstreamRefresh{ + happyOIDCUpstreamRefreshCall := func() *expectedOIDCUpstreamRefresh { + return &expectedOIDCUpstreamRefresh{ performedByUpstreamName: oidcUpstreamName, - args: &oidctestutil.PerformRefreshArgs{ + args: &oidctestutil.PerformOIDCRefreshArgs{ Ctx: nil, // this will be filled in with the actual request context by the test below RefreshToken: oidcUpstreamInitialRefreshToken, }, } } - happyGitHubUpstreamRefreshCall := func() *expectedUpstreamRefresh { - return &expectedUpstreamRefresh{ + happyGitHubUpstreamRefreshCall := func() *expectedGithubUpstreamRefresh { + return &expectedGithubUpstreamRefresh{ performedByUpstreamName: githubUpstreamName, + args: &oidctestutil.GetUserArgs{ + Ctx: nil, // this will be filled in with the actual request context by the test below + AccessToken: githubUpstreamAccessToken, + IDPDisplayName: githubUpstreamName, + }, } } - happyLDAPUpstreamRefreshCall := func() *expectedUpstreamRefresh { - return &expectedUpstreamRefresh{ + happyLDAPUpstreamRefreshCall := func() *expectedLDAPUpstreamRefresh { + return &expectedLDAPUpstreamRefresh{ performedByUpstreamName: ldapUpstreamName, - args: &oidctestutil.PerformRefreshArgs{ - Ctx: nil, - DN: ldapUpstreamDN, - ExpectedSubject: goodSubject, - ExpectedUsername: goodUsername, + args: &oidctestutil.PerformLDAPRefreshArgs{ + Ctx: nil, // this will be filled in with the actual request context by the test below + StoredRefreshAttributes: upstreamprovider.LDAPRefreshAttributes{ + Username: goodUsername, + Subject: goodSubject, + DN: ldapUpstreamDN, + Groups: goodGroups, + AdditionalAttributes: nil, + }, + IDPDisplayName: ldapUpstreamName, }, } } - happyActiveDirectoryUpstreamRefreshCall := func() *expectedUpstreamRefresh { - return &expectedUpstreamRefresh{ + happyActiveDirectoryUpstreamRefreshCall := func() *expectedLDAPUpstreamRefresh { + return &expectedLDAPUpstreamRefresh{ performedByUpstreamName: activeDirectoryUpstreamName, - args: &oidctestutil.PerformRefreshArgs{ - Ctx: nil, - DN: activeDirectoryUpstreamDN, - ExpectedSubject: goodSubject, - ExpectedUsername: goodUsername, + args: &oidctestutil.PerformLDAPRefreshArgs{ + Ctx: nil, // this will be filled in with the actual request context by the test below + StoredRefreshAttributes: upstreamprovider.LDAPRefreshAttributes{ + Username: goodUsername, + Subject: goodSubject, + DN: activeDirectoryUpstreamDN, + Groups: goodGroups, + AdditionalAttributes: nil, + }, + IDPDisplayName: activeDirectoryUpstreamName, }, } } - happyUpstreamValidateTokenCall := func(expectedTokens *oauth2.Token, requireIDToken bool) *expectedUpstreamValidateTokens { - return &expectedUpstreamValidateTokens{ + happyUpstreamValidateTokenCall := func(expectedTokens *oauth2.Token, requireIDToken bool) *expectedOIDCUpstreamValidateTokens { + return &expectedOIDCUpstreamValidateTokens{ performedByUpstreamName: oidcUpstreamName, args: &oidctestutil.ValidateTokenAndMergeWithUserInfoArgs{ Ctx: nil, // this will be filled in with the actual request context by the test below @@ -2014,7 +2042,7 @@ func TestRefreshGrant(t *testing.T) { // same as the same values as the authcode exchange case. want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored) // Should always try to perform an upstream refresh. - want.wantUpstreamRefreshCall = happyOIDCUpstreamRefreshCall() + want.wantOIDCUpstreamRefreshCall = happyOIDCUpstreamRefreshCall() if expectToValidateToken != nil { want.wantUpstreamOIDCValidateTokenCall = happyUpstreamValidateTokenCall(expectToValidateToken, true) } @@ -2026,7 +2054,7 @@ func TestRefreshGrant(t *testing.T) { // same as the same values as the authcode exchange case. want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups) // Should always try to perform an upstream refresh. - want.wantUpstreamRefreshCall = happyOIDCUpstreamRefreshCall() + want.wantOIDCUpstreamRefreshCall = happyOIDCUpstreamRefreshCall() if expectToValidateToken != nil { want.wantUpstreamOIDCValidateTokenCall = happyUpstreamValidateTokenCall(expectToValidateToken, true) } @@ -2038,7 +2066,7 @@ func TestRefreshGrant(t *testing.T) { // same as the same values as the authcode exchange case. want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups) // Should always try to perform an upstream refresh. - want.wantUpstreamRefreshCall = happyGitHubUpstreamRefreshCall() + want.wantGithubUpstreamRefreshCall = happyGitHubUpstreamRefreshCall() return want } @@ -2050,19 +2078,19 @@ func TestRefreshGrant(t *testing.T) { happyRefreshTokenResponseForLDAP := func(wantCustomSessionDataStored *psession.CustomSessionData) tokenEndpointResponseExpectedValues { want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored) - want.wantUpstreamRefreshCall = happyLDAPUpstreamRefreshCall() + want.wantLDAPUpstreamRefreshCall = happyLDAPUpstreamRefreshCall() return want } happyRefreshTokenResponseForLDAPWithUsernameAndGroups := func(wantCustomSessionDataStored *psession.CustomSessionData, wantDownstreamUsername string, wantDownstreamGroups []string) tokenEndpointResponseExpectedValues { want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccessWithUsernameAndGroups(wantCustomSessionDataStored, wantDownstreamUsername, wantDownstreamGroups) - want.wantUpstreamRefreshCall = happyLDAPUpstreamRefreshCall() + want.wantLDAPUpstreamRefreshCall = happyLDAPUpstreamRefreshCall() return want } happyRefreshTokenResponseForActiveDirectory := func(wantCustomSessionDataStored *psession.CustomSessionData) tokenEndpointResponseExpectedValues { want := happyAuthcodeExchangeTokenResponseForOpenIDAndOfflineAccess(wantCustomSessionDataStored) - want.wantUpstreamRefreshCall = happyActiveDirectoryUpstreamRefreshCall() + want.wantActiveDirectoryUpstreamRefreshCall = happyActiveDirectoryUpstreamRefreshCall() return want } @@ -2252,7 +2280,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: transformationUsernamePrefix + goodUsername, wantGroups: testutil.AddPrefixToEach(transformationGroupsPrefix, goodGroups), - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshTokenWithUsername(oidcUpstreamRefreshedRefreshToken, transformationUsernamePrefix+goodUsername), }, @@ -2286,7 +2314,7 @@ func TestRefreshGrant(t *testing.T) { }, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -2326,7 +2354,7 @@ func TestRefreshGrant(t *testing.T) { }, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -2576,7 +2604,7 @@ func TestRefreshGrant(t *testing.T) { wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantUsername: "", wantGroups: goodGroups, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), }), }, @@ -2631,7 +2659,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: goodGroups, - wantUpstreamOIDCValidateTokenCall: &expectedUpstreamValidateTokens{ + wantUpstreamOIDCValidateTokenCall: &expectedOIDCUpstreamValidateTokens{ oidcUpstreamName, &oidctestutil.ValidateTokenAndMergeWithUserInfoArgs{ Ctx: nil, // this will be filled in with the actual request context by the test below @@ -2674,7 +2702,7 @@ func TestRefreshGrant(t *testing.T) { wantSuccessBodyFields: []string{"refresh_token", "access_token", "token_type", "expires_in", "scope"}, wantRequestedScopes: []string{"offline_access"}, wantGrantedScopes: []string{"offline_access", "username", "groups"}, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantUsername: goodUsername, @@ -2700,7 +2728,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: goodGroups, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithRefreshTokenWithoutIDToken(), false), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), }, @@ -2727,7 +2755,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantWarnings: []RecordedWarning{ @@ -2768,7 +2796,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantWarnings: nil, // dynamic clients should not get these warnings which are intended for the pinniped-cli client @@ -2796,7 +2824,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantWarnings: []RecordedWarning{ @@ -2827,7 +2855,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{}, // the user no longer belongs to any groups - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantWarnings: []RecordedWarning{ @@ -2857,7 +2885,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: goodGroups, // the same groups as from the initial login - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), }, @@ -2882,7 +2910,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), wantCustomSessionDataStored: happyLDAPCustomSessionData, wantWarnings: []RecordedWarning{ {Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`}, @@ -2920,7 +2948,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), wantCustomSessionDataStored: happyLDAPCustomSessionData, wantWarnings: nil, // dynamic clients should not get these warnings which are intended for the pinniped-cli client }, @@ -2945,7 +2973,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{}, - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), wantCustomSessionDataStored: happyLDAPCustomSessionData, wantWarnings: []RecordedWarning{ {Text: `User "some-username" has been removed from the following groups: ["group1" "groups2"]`}, @@ -2988,7 +3016,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, // username and groups were not requested, but granted anyway for backwards compatibility wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), wantCustomSessionDataStored: happyLDAPCustomSessionData, wantWarnings: []RecordedWarning{ {Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`}, @@ -3034,7 +3062,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, // username and groups were not requested, but granted anyway for backwards compatibility wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), wantWarnings: []RecordedWarning{ @@ -3087,7 +3115,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username"}, wantUsername: goodUsername, wantGroups: nil, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), }, @@ -3138,7 +3166,7 @@ func TestRefreshGrant(t *testing.T) { r.SetBasicAuth(dynamicClientID, testutil.PlaintextPassword1) // Use basic auth header instead. }, want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, // auth was rejected because of the upstream group to which the user belonged, as shown by the configured RejectedAuthenticationMessage appearing here @@ -3188,7 +3216,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "username", "groups"}, wantUsername: goodUsername, wantGroups: []string{"new-group1", "new-group2", "new-group3"}, // groups are updated even though the scope was not included - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), wantCustomSessionDataStored: happyLDAPCustomSessionData, wantWarnings: []RecordedWarning{ {Text: `User "some-username" has been added to the following groups: ["new-group1" "new-group2" "new-group3"]`}, @@ -3213,7 +3241,7 @@ func TestRefreshGrant(t *testing.T) { want: tokenEndpointResponseExpectedValues{ wantStatus: http.StatusUnauthorized, wantErrorResponseBody: fositeUpstreamGroupClaimErrorBody, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), }, }, @@ -3295,7 +3323,7 @@ func TestRefreshGrant(t *testing.T) { wantGrantedScopes: []string{"openid", "offline_access", "pinniped:request-audience", "username", "groups"}, wantUsername: goodUsername, wantGroups: goodGroups, - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantCustomSessionDataStored: upstreamOIDCCustomSessionDataWithNewRefreshToken(oidcUpstreamRefreshedRefreshToken), }, @@ -3793,8 +3821,8 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), - wantStatus: http.StatusUnauthorized, + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` { "error": "error", @@ -3814,7 +3842,7 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -3842,7 +3870,7 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -3867,7 +3895,7 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -3894,7 +3922,7 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -3921,7 +3949,7 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForOIDCUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), + wantOIDCUpstreamRefreshCall: happyOIDCUpstreamRefreshCall(), wantUpstreamOIDCValidateTokenCall: happyUpstreamValidateTokenCall(refreshedUpstreamTokensWithIDAndRefreshTokens(), true), wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` @@ -4011,8 +4039,8 @@ func TestRefreshGrant(t *testing.T) { }, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), - wantStatus: http.StatusUnauthorized, + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` { "error": "error", @@ -4051,8 +4079,8 @@ func TestRefreshGrant(t *testing.T) { }, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), - wantStatus: http.StatusUnauthorized, + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` { "error": "error", @@ -4125,7 +4153,7 @@ func TestRefreshGrant(t *testing.T) { wantCustomSessionDataStored: happyLDAPCustomSessionData, wantUsername: "", wantGroups: goodGroups, - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), }), }, }, @@ -4319,8 +4347,8 @@ func TestRefreshGrant(t *testing.T) { authcodeExchange: happyAuthcodeExchangeInputsForLDAPUpstream, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), - wantStatus: http.StatusUnauthorized, + wantLDAPUpstreamRefreshCall: happyLDAPUpstreamRefreshCall(), + wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` { "error": "error", @@ -4348,8 +4376,8 @@ func TestRefreshGrant(t *testing.T) { }, refreshRequest: refreshRequestInputs{ want: tokenEndpointResponseExpectedValues{ - wantUpstreamRefreshCall: happyActiveDirectoryUpstreamRefreshCall(), - wantStatus: http.StatusUnauthorized, + wantActiveDirectoryUpstreamRefreshCall: happyActiveDirectoryUpstreamRefreshCall(), + wantStatus: http.StatusUnauthorized, wantErrorResponseBody: here.Doc(` { "error": "error", @@ -4602,7 +4630,7 @@ func TestRefreshGrant(t *testing.T) { // Performing an authcode exchange should not have caused any upstream refresh, which should only // happen during a downstream refresh. - test.idps.RequireExactlyZeroCallsToPerformRefresh(t) + test.idps.RequireExactlyZeroCallsToAnyUpstreamRefresh(t) test.idps.RequireExactlyZeroCallsToValidateToken(t) // Wait one second before performing the refresh so we can see that the refreshed ID token has new issued @@ -4634,21 +4662,38 @@ func TestRefreshGrant(t *testing.T) { t.Logf("second response: %#v", refreshResponse) t.Logf("second response body: %q", refreshResponse.Body.String()) - // Test that we did or did not make a call to the upstream OIDC provider interface to perform a token refresh. - if test.refreshRequest.want.wantUpstreamRefreshCall != nil { - if test.authcodeExchange.customSessionData.ProviderType != "github" { - test.refreshRequest.want.wantUpstreamRefreshCall.args.Ctx = reqContext - } - test.idps.RequireExactlyOneCallToPerformRefresh(t, - test.refreshRequest.want.wantUpstreamRefreshCall.performedByUpstreamName, - test.refreshRequest.want.wantUpstreamRefreshCall.args, + // Test that we did or did not make a call to the upstream provider's interface to perform refresh. + switch { + case test.refreshRequest.want.wantOIDCUpstreamRefreshCall != nil: + test.refreshRequest.want.wantOIDCUpstreamRefreshCall.args.Ctx = reqContext + test.idps.RequireExactlyOneCallToOIDCPerformRefresh(t, + test.refreshRequest.want.wantOIDCUpstreamRefreshCall.performedByUpstreamName, + test.refreshRequest.want.wantOIDCUpstreamRefreshCall.args, ) - } else { - test.idps.RequireExactlyZeroCallsToPerformRefresh(t) + case test.refreshRequest.want.wantLDAPUpstreamRefreshCall != nil: + test.refreshRequest.want.wantLDAPUpstreamRefreshCall.args.Ctx = reqContext + test.idps.RequireExactlyOneCallToLDAPPerformRefresh(t, + test.refreshRequest.want.wantLDAPUpstreamRefreshCall.performedByUpstreamName, + test.refreshRequest.want.wantLDAPUpstreamRefreshCall.args, + ) + case test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall != nil: + test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.args.Ctx = reqContext + test.idps.RequireExactlyOneCallToActiveDirectoryPerformRefresh(t, + test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.performedByUpstreamName, + test.refreshRequest.want.wantActiveDirectoryUpstreamRefreshCall.args, + ) + case test.refreshRequest.want.wantGithubUpstreamRefreshCall != nil: + test.refreshRequest.want.wantGithubUpstreamRefreshCall.args.Ctx = reqContext + test.idps.RequireExactlyOneCallToGithubGetUser(t, + test.refreshRequest.want.wantGithubUpstreamRefreshCall.performedByUpstreamName, + test.refreshRequest.want.wantGithubUpstreamRefreshCall.args, + ) + default: + test.idps.RequireExactlyZeroCallsToAnyUpstreamRefresh(t) } // Test that we did or did not make a call to the upstream OIDC provider interface to validate the - // new ID token that was returned by the upstream refresh. + // new ID token that was returned by the upstream refresh, in the case of an OIDC upstream. if test.refreshRequest.want.wantUpstreamOIDCValidateTokenCall != nil { test.refreshRequest.want.wantUpstreamOIDCValidateTokenCall.args.Ctx = reqContext test.idps.RequireExactlyOneCallToValidateToken(t, diff --git a/internal/federationdomain/resolvedprovider/resolvedldap/resolved_ldap_provider.go b/internal/federationdomain/resolvedprovider/resolvedldap/resolved_ldap_provider.go index a700ae4fc..69d7096b8 100644 --- a/internal/federationdomain/resolvedprovider/resolvedldap/resolved_ldap_provider.go +++ b/internal/federationdomain/resolvedprovider/resolvedldap/resolved_ldap_provider.go @@ -221,7 +221,7 @@ func (p *FederationDomainResolvedLDAPIdentityProvider) UpstreamRefresh( plog.Debug("attempting upstream refresh request", "providerName", p.Provider.GetName(), "providerType", p.GetSessionProviderType(), "providerUID", p.Provider.GetResourceUID()) - refreshedUntransformedGroups, err := p.Provider.PerformRefresh(ctx, upstreamprovider.RefreshAttributes{ + refreshedUntransformedGroups, err := p.Provider.PerformRefresh(ctx, upstreamprovider.LDAPRefreshAttributes{ Username: identity.UpstreamUsername, Subject: identity.DownstreamSubject, DN: dn, diff --git a/internal/federationdomain/upstreamprovider/upsteam_provider.go b/internal/federationdomain/upstreamprovider/upsteam_provider.go index faf6af015..40da3f922 100644 --- a/internal/federationdomain/upstreamprovider/upsteam_provider.go +++ b/internal/federationdomain/upstreamprovider/upsteam_provider.go @@ -26,9 +26,9 @@ const ( AccessTokenType RevocableTokenType = "access_token" ) -// RefreshAttributes contains information about the user from the original login request +// LDAPRefreshAttributes contains information about the user from the original login request // and previous refreshes to be used during an LDAP session refresh. -type RefreshAttributes struct { +type LDAPRefreshAttributes struct { Username string Subject string DN string @@ -125,7 +125,7 @@ type UpstreamLDAPIdentityProviderI interface { authenticators.UserAuthenticator // PerformRefresh performs a refresh against the upstream LDAP identity provider - PerformRefresh(ctx context.Context, storedRefreshAttributes RefreshAttributes, idpDisplayName string) (groups []string, err error) + PerformRefresh(ctx context.Context, storedRefreshAttributes LDAPRefreshAttributes, idpDisplayName string) (groups []string, err error) } type GitHubUser struct { diff --git a/internal/testutil/oidctestutil/testldapprovider.go b/internal/testutil/oidctestutil/testldapprovider.go index b4ef6363f..b9f3ea153 100644 --- a/internal/testutil/oidctestutil/testldapprovider.go +++ b/internal/testutil/oidctestutil/testldapprovider.go @@ -14,6 +14,12 @@ import ( "go.pinniped.dev/internal/idtransform" ) +type PerformLDAPRefreshArgs struct { + Ctx context.Context + StoredRefreshAttributes upstreamprovider.LDAPRefreshAttributes + IDPDisplayName string +} + func NewTestUpstreamLDAPIdentityProviderBuilder() *TestUpstreamLDAPIdentityProviderBuilder { return &TestUpstreamLDAPIdentityProviderBuilder{} } @@ -102,7 +108,7 @@ type TestUpstreamLDAPIdentityProvider struct { // Fields for tracking actual calls make to mock functions. performRefreshCallCount int - performRefreshArgs []*PerformRefreshArgs + performRefreshArgs []*PerformLDAPRefreshArgs } var _ upstreamprovider.UpstreamLDAPIdentityProviderI = &TestUpstreamLDAPIdentityProvider{} @@ -123,16 +129,15 @@ func (u *TestUpstreamLDAPIdentityProvider) GetURL() *url.URL { return u.URL } -func (u *TestUpstreamLDAPIdentityProvider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.RefreshAttributes, _idpDisplayName string) ([]string, error) { +func (u *TestUpstreamLDAPIdentityProvider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.LDAPRefreshAttributes, idpDisplayName string) ([]string, error) { if u.performRefreshArgs == nil { - u.performRefreshArgs = make([]*PerformRefreshArgs, 0) + u.performRefreshArgs = make([]*PerformLDAPRefreshArgs, 0) } u.performRefreshCallCount++ - u.performRefreshArgs = append(u.performRefreshArgs, &PerformRefreshArgs{ - Ctx: ctx, - DN: storedRefreshAttributes.DN, - ExpectedUsername: storedRefreshAttributes.Username, - ExpectedSubject: storedRefreshAttributes.Subject, + u.performRefreshArgs = append(u.performRefreshArgs, &PerformLDAPRefreshArgs{ + Ctx: ctx, + StoredRefreshAttributes: storedRefreshAttributes, + IDPDisplayName: idpDisplayName, }) if u.PerformRefreshErr != nil { return nil, u.PerformRefreshErr @@ -144,9 +149,9 @@ func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshCallCount() int { return u.performRefreshCallCount } -func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshArgs(call int) *PerformRefreshArgs { +func (u *TestUpstreamLDAPIdentityProvider) PerformRefreshArgs(call int) *PerformLDAPRefreshArgs { if u.performRefreshArgs == nil { - u.performRefreshArgs = make([]*PerformRefreshArgs, 0) + u.performRefreshArgs = make([]*PerformLDAPRefreshArgs, 0) } return u.performRefreshArgs[call] } diff --git a/internal/testutil/oidctestutil/testoidcprovider.go b/internal/testutil/oidctestutil/testoidcprovider.go index 489f6304c..285988917 100644 --- a/internal/testutil/oidctestutil/testoidcprovider.go +++ b/internal/testutil/oidctestutil/testoidcprovider.go @@ -36,14 +36,11 @@ type PasswordCredentialsGrantAndValidateTokensArgs struct { Password string } -// PerformRefreshArgs is used to spy on calls to +// PerformOIDCRefreshArgs is used to spy on calls to // TestUpstreamOIDCIdentityProvider.PerformRefreshFunc(). -type PerformRefreshArgs struct { - Ctx context.Context - RefreshToken string - DN string - ExpectedUsername string - ExpectedSubject string +type PerformOIDCRefreshArgs struct { + Ctx context.Context + RefreshToken string } // RevokeTokenArgs is used to spy on calls to @@ -105,7 +102,7 @@ type TestUpstreamOIDCIdentityProvider struct { passwordCredentialsGrantAndValidateTokensCallCount int passwordCredentialsGrantAndValidateTokensArgs []*PasswordCredentialsGrantAndValidateTokensArgs performRefreshCallCount int - performRefreshArgs []*PerformRefreshArgs + performRefreshArgs []*PerformOIDCRefreshArgs revokeTokenCallCount int revokeTokenArgs []*RevokeTokenArgs validateTokenAndMergeWithUserInfoCallCount int @@ -217,10 +214,10 @@ func (u *TestUpstreamOIDCIdentityProvider) PasswordCredentialsGrantAndValidateTo func (u *TestUpstreamOIDCIdentityProvider) PerformRefresh(ctx context.Context, refreshToken string) (*oauth2.Token, error) { if u.performRefreshArgs == nil { - u.performRefreshArgs = make([]*PerformRefreshArgs, 0) + u.performRefreshArgs = make([]*PerformOIDCRefreshArgs, 0) } u.performRefreshCallCount++ - u.performRefreshArgs = append(u.performRefreshArgs, &PerformRefreshArgs{ + u.performRefreshArgs = append(u.performRefreshArgs, &PerformOIDCRefreshArgs{ Ctx: ctx, RefreshToken: refreshToken, }) @@ -244,9 +241,9 @@ func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshCallCount() int { return u.performRefreshCallCount } -func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshArgs(call int) *PerformRefreshArgs { +func (u *TestUpstreamOIDCIdentityProvider) PerformRefreshArgs(call int) *PerformOIDCRefreshArgs { if u.performRefreshArgs == nil { - u.performRefreshArgs = make([]*PerformRefreshArgs, 0) + u.performRefreshArgs = make([]*PerformOIDCRefreshArgs, 0) } return u.performRefreshArgs[call] } diff --git a/internal/testutil/testidplister/testidplister.go b/internal/testutil/testidplister/testidplister.go index 2dded4809..5aba22f21 100644 --- a/internal/testutil/testidplister/testidplister.go +++ b/internal/testutil/testidplister/testidplister.go @@ -330,60 +330,111 @@ func (b *UpstreamIDPListerBuilder) RequireExactlyZeroAuthcodeExchanges(t *testin ) } -func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToPerformRefresh( +func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToOIDCPerformRefresh( t *testing.T, expectedPerformedByUpstreamName string, - expectedArgs *oidctestutil.PerformRefreshArgs, + expectedArgs *oidctestutil.PerformOIDCRefreshArgs, ) { t.Helper() - var actualArgs *oidctestutil.PerformRefreshArgs + var actualArgs *oidctestutil.PerformOIDCRefreshArgs var actualNameOfUpstreamWhichMadeCall string - actualCallCountAcrossAllUpstreams := 0 - for _, upstreamOIDC := range b.upstreamOIDCIdentityProviders { - callCountOnThisUpstream := upstreamOIDC.PerformRefreshCallCount() - actualCallCountAcrossAllUpstreams += callCountOnThisUpstream - if callCountOnThisUpstream == 1 { - actualNameOfUpstreamWhichMadeCall = upstreamOIDC.Name - actualArgs = upstreamOIDC.PerformRefreshArgs(0) - } - } - for _, upstreamLDAP := range b.upstreamLDAPIdentityProviders { - callCountOnThisUpstream := upstreamLDAP.PerformRefreshCallCount() - actualCallCountAcrossAllUpstreams += callCountOnThisUpstream - if callCountOnThisUpstream == 1 { - actualNameOfUpstreamWhichMadeCall = upstreamLDAP.Name - actualArgs = upstreamLDAP.PerformRefreshArgs(0) - } - } - for _, upstreamAD := range b.upstreamActiveDirectoryIdentityProviders { - callCountOnThisUpstream := upstreamAD.PerformRefreshCallCount() - actualCallCountAcrossAllUpstreams += callCountOnThisUpstream - if callCountOnThisUpstream == 1 { - actualNameOfUpstreamWhichMadeCall = upstreamAD.Name - actualArgs = upstreamAD.PerformRefreshArgs(0) - } - } - for _, upstream := range b.upstreamGitHubIdentityProviders { - // Remember that GitHub does not have a traditional PerformRefresh function. - // GitHub calls GetUser during both the original authcode exchange and the refresh. - callCountOnThisUpstream := upstream.GetUserCallCount() - actualCallCountAcrossAllUpstreams += callCountOnThisUpstream + for _, upstream := range b.upstreamOIDCIdentityProviders { + callCountOnThisUpstream := upstream.PerformRefreshCallCount() if callCountOnThisUpstream == 1 { actualNameOfUpstreamWhichMadeCall = upstream.Name - actualArgs = nil + actualArgs = upstream.PerformRefreshArgs(0) } } - require.Equal(t, 1, actualCallCountAcrossAllUpstreams, - "should have been exactly one call to PerformRefresh() by all upstreams", + require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(), + "should have been exactly one call to upstream refresh by all upstreams", ) require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall, - "PerformRefresh() was called on the wrong upstream", + "upstream refresh was called on the wrong upstream", ) require.Equal(t, expectedArgs, actualArgs) } -func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToPerformRefresh(t *testing.T) { +func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToActiveDirectoryPerformRefresh( + t *testing.T, + expectedPerformedByUpstreamName string, + expectedArgs *oidctestutil.PerformLDAPRefreshArgs, +) { t.Helper() + var actualArgs *oidctestutil.PerformLDAPRefreshArgs + var actualNameOfUpstreamWhichMadeCall string + for _, upstream := range b.upstreamActiveDirectoryIdentityProviders { + callCountOnThisUpstream := upstream.PerformRefreshCallCount() + if callCountOnThisUpstream == 1 { + actualNameOfUpstreamWhichMadeCall = upstream.Name + actualArgs = upstream.PerformRefreshArgs(0) + } + } + require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(), + "should have been exactly one call to upstream refresh by all upstreams", + ) + require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall, + "upstream refresh was called on the wrong upstream", + ) + require.Equal(t, expectedArgs, actualArgs) +} + +func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToLDAPPerformRefresh( + t *testing.T, + expectedPerformedByUpstreamName string, + expectedArgs *oidctestutil.PerformLDAPRefreshArgs, +) { + t.Helper() + var actualArgs *oidctestutil.PerformLDAPRefreshArgs + var actualNameOfUpstreamWhichMadeCall string + for _, upstream := range b.upstreamLDAPIdentityProviders { + callCountOnThisUpstream := upstream.PerformRefreshCallCount() + if callCountOnThisUpstream == 1 { + actualNameOfUpstreamWhichMadeCall = upstream.Name + actualArgs = upstream.PerformRefreshArgs(0) + } + } + require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(), + "should have been exactly one call to upstream refresh by all upstreams", + ) + require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall, + "upstream refresh was called on the wrong upstream", + ) + require.Equal(t, expectedArgs, actualArgs) +} + +func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToGithubGetUser( + t *testing.T, + expectedPerformedByUpstreamName string, + expectedArgs *oidctestutil.GetUserArgs, +) { + t.Helper() + var actualArgs *oidctestutil.GetUserArgs + var actualNameOfUpstreamWhichMadeCall string + for _, upstream := range b.upstreamGitHubIdentityProviders { + // GitHub calls GetUser during both the original authcode exchange and the refresh. + callCountOnThisUpstream := upstream.GetUserCallCount() + if callCountOnThisUpstream == 1 { + actualNameOfUpstreamWhichMadeCall = upstream.Name + actualArgs = upstream.GetUserArgs(0) + } + } + require.Equal(t, 1, b.CountAllCallsToAnyUpstreamRefresh(), + "should have been exactly one call to upstream refresh by all upstreams", + ) + require.Equal(t, expectedPerformedByUpstreamName, actualNameOfUpstreamWhichMadeCall, + "upstream refresh was called on the wrong upstream", + ) + require.Equal(t, expectedArgs, actualArgs) +} + +func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToAnyUpstreamRefresh(t *testing.T) { + t.Helper() + require.Equal(t, 0, b.CountAllCallsToAnyUpstreamRefresh(), + "expected exactly zero calls to any upstream refresh mocks", + ) +} + +func (b *UpstreamIDPListerBuilder) CountAllCallsToAnyUpstreamRefresh() int { actualCallCountAcrossAllUpstreams := 0 for _, upstreamOIDC := range b.upstreamOIDCIdentityProviders { actualCallCountAcrossAllUpstreams += upstreamOIDC.PerformRefreshCallCount() @@ -394,11 +445,10 @@ func (b *UpstreamIDPListerBuilder) RequireExactlyZeroCallsToPerformRefresh(t *te for _, upstreamActiveDirectory := range b.upstreamActiveDirectoryIdentityProviders { actualCallCountAcrossAllUpstreams += upstreamActiveDirectory.PerformRefreshCallCount() } - // TODO: probably add GitHub loop once we flesh out the structs - - require.Equal(t, 0, actualCallCountAcrossAllUpstreams, - "expected exactly zero calls to PerformRefresh()", - ) + for _, upstreamGithub := range b.upstreamGitHubIdentityProviders { + actualCallCountAcrossAllUpstreams += upstreamGithub.GetUserCallCount() + } + return actualCallCountAcrossAllUpstreams } func (b *UpstreamIDPListerBuilder) RequireExactlyOneCallToValidateToken( diff --git a/internal/upstreamldap/upstreamldap.go b/internal/upstreamldap/upstreamldap.go index 7735b231b..2509c2921 100644 --- a/internal/upstreamldap/upstreamldap.go +++ b/internal/upstreamldap/upstreamldap.go @@ -118,7 +118,7 @@ type ProviderConfig struct { GroupAttributeParsingOverrides map[string]func(*ldap.Entry) (string, error) // RefreshAttributeChecks are extra checks that attributes in a refresh response are as expected. - RefreshAttributeChecks map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error + RefreshAttributeChecks map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error } // UserSearchConfig contains information about how to search for users in the upstream LDAP IDP. @@ -186,7 +186,7 @@ func closeAndLogError(conn Conn, doingWhat string) { } } -func (p *Provider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.RefreshAttributes, idpDisplayName string) ([]string, error) { +func (p *Provider) PerformRefresh(ctx context.Context, storedRefreshAttributes upstreamprovider.LDAPRefreshAttributes, idpDisplayName string) ([]string, error) { t := trace.FromContext(ctx).Nest("slow ldap refresh attempt", trace.Field{Key: "providerName", Value: p.GetName()}) defer t.LogIfLong(500 * time.Millisecond) // to help users debug slow LDAP searches userDN := storedRefreshAttributes.DN diff --git a/internal/upstreamldap/upstreamldap_test.go b/internal/upstreamldap/upstreamldap_test.go index f7cdcadbe..49e36968e 100644 --- a/internal/upstreamldap/upstreamldap_test.go +++ b/internal/upstreamldap/upstreamldap_test.go @@ -641,8 +641,8 @@ func TestEndUserAuthentication(t *testing.T) { username: testUpstreamUsername, password: testUpstreamPassword, providerConfig: providerConfig(func(p *ProviderConfig) { - p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error{ - "some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error { + p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error{ + "some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error { return nil }, } @@ -679,8 +679,8 @@ func TestEndUserAuthentication(t *testing.T) { username: testUpstreamUsername, password: testUpstreamPassword, providerConfig: providerConfig(func(p *ProviderConfig) { - p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error{ - "some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.RefreshAttributes) error { + p.RefreshAttributeChecks = map[string]func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error{ + "some-attribute-to-check-during-refresh": func(entry *ldap.Entry, attributes upstreamprovider.LDAPRefreshAttributes) error { return nil }, } @@ -1527,8 +1527,8 @@ func TestUpstreamRefresh(t *testing.T) { Filter: testGroupSearchFilter, GroupNameAttribute: testGroupSearchGroupNameAttribute, }, - RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ - pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.RefreshAttributes) error { return nil }, + RefreshAttributeChecks: map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ + pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error { return nil }, }, } if editFunc != nil { @@ -2124,8 +2124,8 @@ func TestUpstreamRefresh(t *testing.T) { { name: "search result has a changed pwdLastSet value", providerConfig: providerConfig(func(p *ProviderConfig) { - p.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.RefreshAttributes) error{ - pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.RefreshAttributes) error { + p.RefreshAttributeChecks = map[string]func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error{ + pwdLastSetAttribute: func(*ldap.Entry, upstreamprovider.LDAPRefreshAttributes) error { return errors.New(`value for attribute "pwdLastSet" has changed since initial value at login`) }, } @@ -2201,7 +2201,7 @@ func TestUpstreamRefresh(t *testing.T) { "ldaps://ldap.example.com:8443?base=some-upstream-user-base-dn&idpName=%s&sub=c29tZS11cHN0cmVhbS11aWQtdmFsdWU", testUpstreamName, ) - groups, err := ldapProvider.PerformRefresh(context.Background(), upstreamprovider.RefreshAttributes{ + groups, err := ldapProvider.PerformRefresh(context.Background(), upstreamprovider.LDAPRefreshAttributes{ Username: testUserSearchResultUsernameAttributeValue, Subject: subject, DN: tt.refreshUserDN,