Repository: prebid/prebid-server
Pull request #1565 (2020-11-05 02:43:15)

Remove legacy GDPR AMP config flag used to prevent buyer ID scrub on AMP requests
Related issue: https://github.com/prebid/prebid-server/issues/1312

The replacement strategy in https://github.com/prebid/prebid-server/pull/1564 should be merged in before this.

SyntaxNode: We'll wait to merge this until we build the final release this year. We had publisher complaints the first time around so this is deemed higher risk than normal, and we're not keen on doing this in Q4 2020. Also gives more time for hosts to discover the new GDPR account level config.
SyntaxNode: Let's discuss with the Prebid.org Committee how we want to handle feature deprecation.

Patch:
diff --git a/config/config.go b/config/config.go
index a51ddb67..ef1e0524 100755
--- a/config/config.go
+++ b/config/config.go
@@ -214,7 +214,7 @@ func (cfg *GDPR) validate(errs []error) []error {
 		glog.Warning("gdpr.host_vendor_id was not specified. Host company GDPR checks will be skipped.")
 	}
 	if cfg.AMPException == true {
-		glog.Warning("gdpr.amp_exception is deprecated and will be removed in a future version. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp).")
+		errs = append(errs, fmt.Errorf("gdpr.amp_exception has been discontinued and must be removed from your config. If you need to disable GDPR for AMP, you may do so per-account (gdpr.integration_enabled.amp) or at the host level for the default account (account_defaults.gdpr.integration_enabled.amp)"))
 	}
 	return errs
 }
@@ -588,7 +588,7 @@ func (cfg *Configuration) setDerivedDefaults() {
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderCpmstar, "https://server.cpmstar.com/usersync.aspx?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dcpmstar%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDatablocks, "https://sync.v5prebid.datablocks.net/s2ssync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7Buid%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDmx, "https://dmx.districtm.io/s/v1/img/s/10007?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddatablocks%26gdpr%3D%24%7Bgdpr%7D%26gdpr_consent%3D%24%7Bgdpr_consent%7D%26uid%3D%24%7Buid%7D")
-	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDeepintent, "https://cdn.deepintent.com/syncpixel.html?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BUID%5D")
+	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderDeepintent, "https://match.deepintent.com/usersync/136?id=unk&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redir="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5BUID%5D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEmxDigital, "https://cs.emxdgt.com/um?ssp=pbs&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Demx_digital%26uid%3D%24UID")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEngageBDR, "https://match.bnmla.com/usersync/s2s_sync?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Dengagebdr%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24%7BUUID%7D")
 	setDefaultUsersync(cfg.Adapters, openrtb_ext.BidderEPlanning, "https://ads.us.e-planning.net/uspd/1/?du="+url.QueryEscape(externalURL)+"%2Fsetuid%3Fbidder%3Deplanning%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%24UID")
diff --git a/exchange/utils.go b/exchange/utils.go
index d70829ff..a803e4e2 100644
--- a/exchange/utils.go
+++ b/exchange/utils.go
@@ -77,7 +77,6 @@ func cleanOpenRTBRequests(ctx context.Context,
 
 	gdpr := extractGDPR(req.BidRequest, usersyncIfAmbiguous)
 	consent := extractConsent(req.BidRequest)
-	ampGDPRException := (req.LegacyLabels.RType == metrics.ReqTypeAMP) && gDPR.AMPException()
 
 	ccpaEnforcer, err := extractCCPA(req.BidRequest, privacyConfig, &req.Account, aliases, integrationTypeMap[req.LegacyLabels.RType])
 	if err != nil {
@@ -125,7 +124,7 @@ func cleanOpenRTBRequests(ctx context.Context,
 			privacyEnforcement.GDPRID = false
 		}
 
-		privacyEnforcement.Apply(bidderRequest.BidRequest, ampGDPRException)
+		privacyEnforcement.Apply(bidderRequest.BidRequest)
 	}
 
 	return
diff --git a/gdpr/gdpr.go b/gdpr/gdpr.go
index 6d447beb..60a7cc1e 100644
--- a/gdpr/gdpr.go
+++ b/gdpr/gdpr.go
@@ -24,9 +24,6 @@ type Permissions interface {
 	//
 	// If the consent string was nonsensical, the returned error will be an ErrorMalformedConsent.
 	PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error)
-
-	// Exposes the AMP execption flag
-	AMPException() bool
 }
 
 // Versions of the GDPR TCF technical specification.
diff --git a/gdpr/impl.go b/gdpr/impl.go
index 2fbd9c5a..5b3b86fe 100644
--- a/gdpr/impl.go
+++ b/gdpr/impl.go
@@ -60,10 +60,6 @@ func (p *permissionsImpl) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return false, false, false, nil
 }
 
-func (p *permissionsImpl) AMPException() bool {
-	return p.cfg.AMPException
-}
-
 func (p *permissionsImpl) allowSync(ctx context.Context, vendorID uint16, consent string) (bool, error) {
 	// If we're not given a consent string, respect the preferences in the app config.
 	if consent == "" {
@@ -225,10 +221,6 @@ func (a AlwaysAllow) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext
 	return true, true, true, nil
 }
 
-func (a AlwaysAllow) AMPException() bool {
-	return false
-}
-
 // Exporting to allow for easy test setups
 type AlwaysFail struct{}
 
@@ -243,7 +235,3 @@ func (a AlwaysFail) BidderSyncAllowed(ctx context.Context, bidder openrtb_ext.Bi
 func (a AlwaysFail) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error) {
 	return false, false, false, nil
 }
-
-func (a AlwaysFail) AMPException() bool {
-	return false
-}
diff --git a/privacy/enforcement.go b/privacy/enforcement.go
index 3f157329..64070ae3 100644
--- a/privacy/enforcement.go
+++ b/privacy/enforcement.go
@@ -19,14 +19,14 @@ func (e Enforcement) Any() bool {
 }
 
 // Apply cleans personally identifiable information from an OpenRTB bid request.
-func (e Enforcement) Apply(bidRequest *openrtb.BidRequest, ampGDPRException bool) {
-	e.apply(bidRequest, ampGDPRException, NewScrubber())
+func (e Enforcement) Apply(bidRequest *openrtb.BidRequest) {
+	e.apply(bidRequest, NewScrubber())
 }
 
-func (e Enforcement) apply(bidRequest *openrtb.BidRequest, ampGDPRException bool, scrubber Scrubber) {
+func (e Enforcement) apply(bidRequest *openrtb.BidRequest, scrubber Scrubber) {
 	if bidRequest != nil && e.Any() {
 		bidRequest.Device = scrubber.ScrubDevice(bidRequest.Device, e.getDeviceIDScrubStrategy(), e.getIPv4ScrubStrategy(), e.getIPv6ScrubStrategy(), e.getGeoScrubStrategy())
-		bidRequest.User = scrubber.ScrubUser(bidRequest.User, e.getUserScrubStrategy(ampGDPRException), e.getGeoScrubStrategy())
+		bidRequest.User = scrubber.ScrubUser(bidRequest.User, e.getUserScrubStrategy(), e.getGeoScrubStrategy())
 	}
 }
 
@@ -70,7 +70,7 @@ func (e Enforcement) getGeoScrubStrategy() ScrubStrategyGeo {
 	return ScrubStrategyGeoNone
 }
 
-func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUser {
+func (e Enforcement) getUserScrubStrategy() ScrubStrategyUser {
 	if e.COPPA {
 		return ScrubStrategyUserIDAndDemographic
 	}
@@ -79,7 +79,7 @@ func (e Enforcement) getUserScrubStrategy(ampGDPRException bool) ScrubStrategyUs
 		return ScrubStrategyUserID
 	}
 
-	if e.GDPRID && !ampGDPRException {
+	if e.GDPRID {
 		return ScrubStrategyUserID
 	}
 


Test patch:
diff --git a/adapters/deepintent/usersync_test.go b/adapters/deepintent/usersync_test.go
index a752e6ba..06a221ca 100644
--- a/adapters/deepintent/usersync_test.go
+++ b/adapters/deepintent/usersync_test.go
@@ -11,7 +11,7 @@ import (
 )
 
 func TestDeepintentSyncer(t *testing.T) {
-	syncURL := "https://cdn.deepintent.com/syncpixel.html?gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D"
+	syncURL := "https://match.deepintent.com/usersync/136?id=unk&gdpr={{.GDPR}}&us_privacy={{.USPrivacy}}&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3D{{.GDPR}}%26gdpr_consent%3D{{.GDPRConsent}}%26uid%3D%5Bio_cid%5D"
 	syncURLTemplate := template.Must(
 		template.New("sync-template").Parse(syncURL),
 	)
@@ -28,7 +28,7 @@ func TestDeepintentSyncer(t *testing.T) {
 	})
 
 	assert.NoError(t, err)
-	assert.Equal(t, "https://cdn.deepintent.com/syncpixel.html?gdpr=A&us_privacy=C&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%5Bio_cid%5D", syncInfo.URL)
+	assert.Equal(t, "https://match.deepintent.com/usersync/136?id=unk&gdpr=A&us_privacy=C&url=https%3A%2F%2Flocalhost%3A8888%2Fsetuid%3Fbidder%3Ddeepintent%26gdpr%3DA%26gdpr_consent%3DB%26uid%3D%5Bio_cid%5D", syncInfo.URL)
 	assert.Equal(t, "redirect", syncInfo.Type)
 	assert.EqualValues(t, uint16(541), syncer.GDPRVendorID())
 	assert.Equal(t, false, syncInfo.SupportCORS)
diff --git a/endpoints/auction_test.go b/endpoints/auction_test.go
index f7f915cb..b5f0989e 100644
--- a/endpoints/auction_test.go
+++ b/endpoints/auction_test.go
@@ -424,10 +424,6 @@ func (m *auctionMockPermissions) PersonalInfoAllowed(ctx context.Context, bidder
 	return m.allowPI, m.allowGeo, m.allowID, nil
 }
 
-func (m *auctionMockPermissions) AMPException() bool {
-	return false
-}
-
 func TestBidSizeValidate(t *testing.T) {
 	bids := make(pbs.PBSBidSlice, 0)
 	// bid1 will be rejected due to undefined size when adunit has multiple sizes
diff --git a/endpoints/cookie_sync_test.go b/endpoints/cookie_sync_test.go
index 77be2590..ee29125b 100644
--- a/endpoints/cookie_sync_test.go
+++ b/endpoints/cookie_sync_test.go
@@ -257,7 +257,3 @@ func (g *gdprPerms) BidderSyncAllowed(ctx context.Context, bidder openrtb_ext.Bi
 func (g *gdprPerms) PersonalInfoAllowed(ctx context.Context, bidder openrtb_ext.BidderName, PublisherID string, consent string) (bool, bool, bool, error) {
 	return true, true, true, nil
 }
-
-func (g *gdprPerms) AMPException() bool {
-	return false
-}
diff --git a/endpoints/setuid_test.go b/endpoints/setuid_test.go
index ae063677..1f2c4040 100644
--- a/endpoints/setuid_test.go
+++ b/endpoints/setuid_test.go
@@ -441,10 +441,6 @@ func (g *mockPermsSetUID) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return g.allowPI, g.allowPI, g.allowPI, nil
 }
 
-func (g *mockPermsSetUID) AMPException() bool {
-	return false
-}
-
 func newFakeSyncer(familyName string) usersync.Usersyncer {
 	return fakeSyncer{
 		familyName: familyName,
diff --git a/exchange/utils_test.go b/exchange/utils_test.go
index 5fb5707c..757eb658 100644
--- a/exchange/utils_test.go
+++ b/exchange/utils_test.go
@@ -34,10 +34,6 @@ func (p *permissionsMock) PersonalInfoAllowed(ctx context.Context, bidder openrt
 	return p.personalInfoAllowed, p.personalInfoAllowed, p.personalInfoAllowed, nil
 }
 
-func (p *permissionsMock) AMPException() bool {
-	return false
-}
-
 func assertReq(t *testing.T, bidderRequests []BidderRequest,
 	applyCOPPA bool, consentedVendors map[string]bool) {
 	// assert individual bidder requests
diff --git a/privacy/enforcement_test.go b/privacy/enforcement_test.go
index 0cf36a61..9240aafc 100644
--- a/privacy/enforcement_test.go
+++ b/privacy/enforcement_test.go
@@ -59,7 +59,6 @@ func TestApply(t *testing.T) {
 	testCases := []struct {
 		description        string
 		enforcement        Enforcement
-		ampGDPRException   bool
 		expectedDeviceID   ScrubStrategyDeviceID
 		expectedDeviceIPv4 ScrubStrategyIPV4
 		expectedDeviceIPv6 ScrubStrategyIPV6
@@ -124,7 +123,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -132,23 +130,6 @@ func TestApply(t *testing.T) {
 			expectedUser:       ScrubStrategyUserID,
 			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
 		},
-		{
-			description: "GDPR Only - Full - AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   false,
-				GDPRGeo: true,
-				GDPRID:  true,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
-			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
-			expectedDeviceGeo:  ScrubStrategyGeoReducedPrecision,
-			expectedUser:       ScrubStrategyUserNone,
-			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
-		},
 		{
 			description: "GDPR Only - ID Only",
 			enforcement: Enforcement{
@@ -158,7 +139,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4None,
 			expectedDeviceIPv6: ScrubStrategyIPV6None,
@@ -166,23 +146,6 @@ func TestApply(t *testing.T) {
 			expectedUser:       ScrubStrategyUserID,
 			expectedUserGeo:    ScrubStrategyGeoNone,
 		},
-		{
-			description: "GDPR Only - ID Only - AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   false,
-				GDPRGeo: false,
-				GDPRID:  true,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4None,
-			expectedDeviceIPv6: ScrubStrategyIPV6None,
-			expectedDeviceGeo:  ScrubStrategyGeoNone,
-			expectedUser:       ScrubStrategyUserNone,
-			expectedUserGeo:    ScrubStrategyGeoNone,
-		},
 		{
 			description: "GDPR Only - Geo Only",
 			enforcement: Enforcement{
@@ -192,7 +155,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  false,
 				LMT:     false,
 			},
-			ampGDPRException:   false,
 			expectedDeviceID:   ScrubStrategyDeviceIDNone,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest16,
@@ -217,24 +179,7 @@ func TestApply(t *testing.T) {
 			expectedUserGeo:    ScrubStrategyGeoReducedPrecision,
 		},
 		{
-			description: "Interactions: COPPA Only + AMP Exception",
-			enforcement: Enforcement{
-				CCPA:    false,
-				COPPA:   true,
-				GDPRGeo: false,
-				GDPRID:  false,
-				LMT:     false,
-			},
-			ampGDPRException:   true,
-			expectedDeviceID:   ScrubStrategyDeviceIDAll,
-			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
-			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
-			expectedDeviceGeo:  ScrubStrategyGeoFull,
-			expectedUser:       ScrubStrategyUserIDAndDemographic,
-			expectedUserGeo:    ScrubStrategyGeoFull,
-		},
-		{
-			description: "Interactions: COPPA + GDPR Full + AMP Exception",
+			description: "Interactions: COPPA + GDPR Full",
 			enforcement: Enforcement{
 				CCPA:    false,
 				COPPA:   true,
@@ -242,7 +187,6 @@ func TestApply(t *testing.T) {
 				GDPRID:  true,
 				LMT:     false,
 			},
-			ampGDPRException:   true,
 			expectedDeviceID:   ScrubStrategyDeviceIDAll,
 			expectedDeviceIPv4: ScrubStrategyIPV4Lowest8,
 			expectedDeviceIPv6: ScrubStrategyIPV6Lowest32,
@@ -264,7 +208,7 @@ func TestApply(t *testing.T) {
 		m.On("ScrubDevice", req.Device, test.expectedDeviceID, test.expectedDeviceIPv4, test.expectedDeviceIPv6, test.expectedDeviceGeo).Return(replacedDevice).Once()
 		m.On("ScrubUser", req.User, test.expectedUser, test.expectedUserGeo).Return(replacedUser).Once()
 
-		test.enforcement.apply(req, test.ampGDPRException, m)
+		test.enforcement.apply(req, m)
 
 		m.AssertExpectations(t)
 		assert.Same(t, replacedDevice, req.Device, "Device")
@@ -284,7 +228,7 @@ func TestApplyNoneApplicable(t *testing.T) {
 		GDPRID:  false,
 		LMT:     false,
 	}
-	enforcement.apply(req, false, m)
+	enforcement.apply(req, m)
 
 	m.AssertNotCalled(t, "ScrubDevice")
 	m.AssertNotCalled(t, "ScrubUser")
@@ -294,7 +238,7 @@ func TestApplyNil(t *testing.T) {
 	m := &mockScrubber{}
 
 	enforcement := Enforcement{}
-	enforcement.apply(nil, false, m)
+	enforcement.apply(nil, m)
 
 	m.AssertNotCalled(t, "ScrubDevice")
 	m.AssertNotCalled(t, "ScrubUser")