From 10090a9aee94ed2adfb9695e9493c1bb0426a03b Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Tue, 26 Oct 2021 12:14:50 +0530 Subject: [PATCH 1/6] add function onSSOLogin to capture PII information --- modules/userId/index.js | 61 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index 2b5ebff47be..64e5fc193cd 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -142,6 +142,9 @@ import { createEidsArray, buildEidPermissions } from './eids.js'; import { getCoreStorageManager } from '../../src/storageManager.js'; import {getPrebidInternal} from '../../src/utils.js'; import includes from 'core-js-pure/features/array/includes.js'; +import MD5 from 'crypto-js/md5.js'; +import SHA1 from 'crypto-js/sha1.js'; +import SHA256 from 'crypto-js/sha256.js'; const MODULE_NAME = 'User ID'; const COOKIE = 'cookie'; @@ -654,6 +657,61 @@ function getUserIdentities() { return userIdentity; } +/** + * This function is used to read sso information from facebook and google apis. + * @param {String} provider SSO provider for which the api call is to be made + * @param {Object} userObject Google's user object, passed from google's callback function + */ +function onSSOLogin(data) { + //console.log("SSO - in onSSOLogin function"); + var refThis = this; + var email = undefined; + var emailHash = {}; + + switch (data.provider) { + case undefined: + case 'facebook': + window.FB && window.FB.api('/me?fields=email&access_token='+data.fbAccessToken, function (response) { + utils.logInfo("SSO - returned from fb api"); + if (response.error) { + utils.logInfo("SSO - User information could not be retrieved by facebook api [", response.error.message, "]"); + } + email = response.email || undefined; + utils.logInfo("SSO - User information retrieved by facebook api - ", email); + generateEmailHash(email, emailHash); + refThis.setUserIdentities({ + emailHash: emailHash + }); + }); + break; + case 'google': + var profile = data.googleUserObject.getBasicProfile(); + var email = profile.getEmail() || undefined; + utils.logInfo("SSO - data available from google api - ",email); + generateEmailHash(email, emailHash); + refThis.setUserIdentities({ + emailHash: emailHash + }); + break; + } +} + +/** + * This function is used to clear user login information once user logs out. + */ +function onSSOLogout() { + this.setUserIdentities({}); +} + +function generateEmailHash(email, emailHash) { + email = email !== undefined ? email.trim().toLowerCase() : ""; + var regex = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/); + if (regex.test(email)) { + emailHash.MD5 = MD5(email).toString(); + emailHash.SHA1 = SHA1(email).toString(); + emailHash.SHA256 = SHA256(email).toString(); + } +} /** * This hook returns updated list of submodules which are allowed to do get user id based on TCF 2 enforcement rules configured */ @@ -858,7 +916,8 @@ export function init(config) { (getGlobal()).refreshUserIds = refreshUserIds; (getGlobal()).setUserIdentities = setUserIdentities; (getGlobal()).getUserIdentities = getUserIdentities; - + (getGlobal()).onSSOLogin = onSSOLogin; + (getGlobal()).onSSOLogout = onSSOLogout; } // init config update listener to start the application From 12cbc89aa55bf06d0463887ee4095d09e328ee03 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Mon, 8 Nov 2021 16:58:49 +0530 Subject: [PATCH 2/6] fixed linting errors and added test cases for onSSOLogin function --- modules/userId/index.js | 25 ++++++++++++------------- test/spec/modules/userId_spec.js | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index 64e5fc193cd..613dc022869 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -504,9 +504,9 @@ function initializeSubmodulesAndExecuteCallbacks(continueAuction) { // initializedSubmodulesUpdated - flag to identify if any module has been added from the page post module initialization. This is specifically for OW use case if (initializedSubmodulesUpdated && initializedSubmodules !== undefined) { - for (var index in initializedSubmodules) { - submodules.push(initializedSubmodules[index]); - } + for (var index in initializedSubmodules) { + submodules.push(initializedSubmodules[index]); + } } // initialize submodules only when undefined @@ -604,7 +604,7 @@ function refreshUserIds(options, callback, moduleUpdated) { if (moduleUpdated !== undefined) { initializedSubmodulesUpdated = moduleUpdated; } - + let submoduleNames = options ? options.submoduleNames : null; if (!submoduleNames) { submoduleNames = []; @@ -663,21 +663,20 @@ function getUserIdentities() { * @param {Object} userObject Google's user object, passed from google's callback function */ function onSSOLogin(data) { - //console.log("SSO - in onSSOLogin function"); var refThis = this; - var email = undefined; + var email; var emailHash = {}; switch (data.provider) { case undefined: case 'facebook': - window.FB && window.FB.api('/me?fields=email&access_token='+data.fbAccessToken, function (response) { - utils.logInfo("SSO - returned from fb api"); + window.FB && window.FB.api('/me?fields=email&access_token=' + data.fbAccessToken, function (response) { + utils.logInfo('SSO - returned from fb api'); if (response.error) { - utils.logInfo("SSO - User information could not be retrieved by facebook api [", response.error.message, "]"); + utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); } email = response.email || undefined; - utils.logInfo("SSO - User information retrieved by facebook api - ", email); + utils.logInfo('SSO - User information retrieved by facebook api - ', email); generateEmailHash(email, emailHash); refThis.setUserIdentities({ emailHash: emailHash @@ -686,8 +685,8 @@ function onSSOLogin(data) { break; case 'google': var profile = data.googleUserObject.getBasicProfile(); - var email = profile.getEmail() || undefined; - utils.logInfo("SSO - data available from google api - ",email); + email = profile.getEmail() || undefined; + utils.logInfo('SSO - data available from google api - ', email); generateEmailHash(email, emailHash); refThis.setUserIdentities({ emailHash: emailHash @@ -704,7 +703,7 @@ function onSSOLogout() { } function generateEmailHash(email, emailHash) { - email = email !== undefined ? email.trim().toLowerCase() : ""; + email = email !== undefined ? email.trim().toLowerCase() : ''; var regex = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/); if (regex.test(email)) { emailHash.MD5 = MD5(email).toString(); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index ca82d6a4336..20288298e1f 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -2922,4 +2922,20 @@ describe('User ID', function () { }); }); }); + + describe('Handle SSO Login', function() { + it('Email hashes are stored in userIdentities Object on SSO login', function () { + function getEmail() { + return 'abc@def.com'; + } + function getBasicProfile() { + return { 'getEmail': getEmail } + } + var dummyGoogleUserObject = { 'getBasicProfile': getBasicProfile } + + expect(typeof (getGlobal()).onSSOLogin).to.equal('function'); + getGlobal().onSSOLogin({'provider': 'google', 'googleUserObject': dummyGoogleUserObject}); + expect((getGlobal()).getUserIdentities().emailHash).to.exist; + }); + }); }); From 6bad20feb5d943bb55d9c672c1ef39243ad775fd Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Thu, 11 Nov 2021 11:26:54 +0530 Subject: [PATCH 3/6] changes to facebook login status api --- modules/userId/index.js | 34 +++++++++++++++++++++----------- test/spec/modules/userId_spec.js | 25 +++++++++++++++++++++-- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index 613dc022869..017bfdde6db 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -667,21 +667,33 @@ function onSSOLogin(data) { var email; var emailHash = {}; + if (!window.PWT || !window.PWT.ssoEnabled) return; + switch (data.provider) { case undefined: case 'facebook': - window.FB && window.FB.api('/me?fields=email&access_token=' + data.fbAccessToken, function (response) { - utils.logInfo('SSO - returned from fb api'); - if (response.error) { - utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); + window.FB && window.FB.getLoginStatus(function(response) { + if (response.status === 'connected') { + window.PWT = window.PWT || {}; + window.PWT.fbAt = response.authResponse.accessToken; + + window.FB && window.FB.api('/me?fields=email&access_token=' + window.PWT.fbAt, function (response) { + utils.logInfo('SSO - returned from fb api'); + + if (response.error) { + utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); + return; + } + + email = response.email || undefined; + utils.logInfo('SSO - User information retrieved by facebook api - ', email); + generateEmailHash(email, emailHash); + refThis.setUserIdentities({ + emailHash: emailHash + }); + }); } - email = response.email || undefined; - utils.logInfo('SSO - User information retrieved by facebook api - ', email); - generateEmailHash(email, emailHash); - refThis.setUserIdentities({ - emailHash: emailHash - }); - }); + }, true); break; case 'google': var profile = data.googleUserObject.getBasicProfile(); diff --git a/test/spec/modules/userId_spec.js b/test/spec/modules/userId_spec.js index 20288298e1f..ca46c3221d4 100644 --- a/test/spec/modules/userId_spec.js +++ b/test/spec/modules/userId_spec.js @@ -2924,7 +2924,11 @@ describe('User ID', function () { }); describe('Handle SSO Login', function() { - it('Email hashes are stored in userIdentities Object on SSO login', function () { + beforeEach(function () { + (getGlobal()).setUserIdentities({}); + }); + + xit('Email hashes are stored in userIdentities Object on SSO login if ssoEnabled is true', function () { function getEmail() { return 'abc@def.com'; } @@ -2932,10 +2936,27 @@ describe('User ID', function () { return { 'getEmail': getEmail } } var dummyGoogleUserObject = { 'getBasicProfile': getBasicProfile } - + console.log('***************** window.PWT = ', window.PWT); + window.PWT = window.PWT || {}; + window.PWT.ssoEnabled = true; expect(typeof (getGlobal()).onSSOLogin).to.equal('function'); getGlobal().onSSOLogin({'provider': 'google', 'googleUserObject': dummyGoogleUserObject}); expect((getGlobal()).getUserIdentities().emailHash).to.exist; }); + + xit('Email hashes are not stored in userIdentities Object on SSO login if ssoEnabled is false', function () { + function getEmail() { + return 'abc@def.com'; + } + function getBasicProfile() { + return { 'getEmail': getEmail } + } + var dummyGoogleUserObject = { 'getBasicProfile': getBasicProfile } + window.PWT.ssoEnabled = false; + + expect(typeof (getGlobal()).onSSOLogin).to.equal('function'); + getGlobal().onSSOLogin({'provider': 'google', 'googleUserObject': dummyGoogleUserObject}); + expect((getGlobal()).getUserIdentities().emailHash).to.not.exist; + }); }); }); From b4c72b5e0883a5cc1e5595f86ec58ff2d27a1b6d Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Tue, 16 Nov 2021 10:58:11 +0530 Subject: [PATCH 4/6] changes to support fb login in firefox --- modules/userId/index.js | 47 ++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index 017bfdde6db..54079024b93 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -672,29 +672,32 @@ function onSSOLogin(data) { switch (data.provider) { case undefined: case 'facebook': - window.FB && window.FB.getLoginStatus(function(response) { - if (response.status === 'connected') { - window.PWT = window.PWT || {}; - window.PWT.fbAt = response.authResponse.accessToken; - - window.FB && window.FB.api('/me?fields=email&access_token=' + window.PWT.fbAt, function (response) { - utils.logInfo('SSO - returned from fb api'); - - if (response.error) { - utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); - return; - } - - email = response.email || undefined; - utils.logInfo('SSO - User information retrieved by facebook api - ', email); - generateEmailHash(email, emailHash); - refThis.setUserIdentities({ - emailHash: emailHash + setTimeout(function() { + window.FB && window.FB.getLoginStatus(function (response) { + if (response.status === 'connected') { + window.PWT = window.PWT || {}; + window.PWT.fbAt = response.authResponse.accessToken; + window.FB && window.FB.api('/me?fields=email&access_token=' + window.PWT.fbAt, function (response) { + __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - returned from fb api'); + + if (response.error) { + __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); + return; + } + + email = response.email || undefined; + __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - User information retrieved by facebook api - ', email); + generateEmailHash(email, emailHash); + refThis.setUserIdentities({ + emailHash: emailHash + }); }); - }); - } - }, true); - break; + } else { + __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]("SSO - error fetching login information from facebook"); + } + }, true); + }, 2000); + break; case 'google': var profile = data.googleUserObject.getBasicProfile(); email = profile.getEmail() || undefined; From 61133a71051a2675537e3a5e2e12cd22ccc4524c Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Tue, 16 Nov 2021 11:10:54 +0530 Subject: [PATCH 5/6] add timeout for fb script only for the first time --- modules/userId/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index 54079024b93..d454223e45f 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -672,32 +672,33 @@ function onSSOLogin(data) { switch (data.provider) { case undefined: case 'facebook': + var timeout = data.provider === 'facebook' ? 0 : 2000; setTimeout(function() { window.FB && window.FB.getLoginStatus(function (response) { if (response.status === 'connected') { window.PWT = window.PWT || {}; window.PWT.fbAt = response.authResponse.accessToken; window.FB && window.FB.api('/me?fields=email&access_token=' + window.PWT.fbAt, function (response) { - __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - returned from fb api'); + utils.logInfo('SSO - returned from fb api'); if (response.error) { - __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); + utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); return; } email = response.email || undefined; - __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]('SSO - User information retrieved by facebook api - ', email); + utils.logInfo('SSO - User information retrieved by facebook api - ', email); generateEmailHash(email, emailHash); refThis.setUserIdentities({ emailHash: emailHash }); }); } else { - __WEBPACK_IMPORTED_MODULE_3__src_utils_js__["logInfo"]("SSO - error fetching login information from facebook"); + utils.logInfo("SSO - error fetching login information from facebook"); } }, true); - }, 2000); - break; + }, timeout); + break;ß case 'google': var profile = data.googleUserObject.getBasicProfile(); email = profile.getEmail() || undefined; From c3acaf0e70f4b1eadacb51cfb3f1b16647dc2241 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Tue, 16 Nov 2021 15:01:29 +0530 Subject: [PATCH 6/6] changed log stmts --- modules/userId/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/userId/index.js b/modules/userId/index.js index d454223e45f..2c93010b2d0 100644 --- a/modules/userId/index.js +++ b/modules/userId/index.js @@ -679,7 +679,7 @@ function onSSOLogin(data) { window.PWT = window.PWT || {}; window.PWT.fbAt = response.authResponse.accessToken; window.FB && window.FB.api('/me?fields=email&access_token=' + window.PWT.fbAt, function (response) { - utils.logInfo('SSO - returned from fb api'); + utils.logInfo('SSO - Data received from FB API'); if (response.error) { utils.logInfo('SSO - User information could not be retrieved by facebook api [', response.error.message, ']'); @@ -687,14 +687,14 @@ function onSSOLogin(data) { } email = response.email || undefined; - utils.logInfo('SSO - User information retrieved by facebook api - ', email); + utils.logInfo('SSO - Information successfully retrieved by Facebook API.'); generateEmailHash(email, emailHash); refThis.setUserIdentities({ emailHash: emailHash }); }); } else { - utils.logInfo("SSO - error fetching login information from facebook"); + utils.logInfo('SSO - Error fetching login information from facebook'); } }, true); }, timeout); @@ -702,7 +702,7 @@ function onSSOLogin(data) { case 'google': var profile = data.googleUserObject.getBasicProfile(); email = profile.getEmail() || undefined; - utils.logInfo('SSO - data available from google api - ', email); + utils.logInfo('SSO - Information successfully retrieved by Google API'); generateEmailHash(email, emailHash); refThis.setUserIdentities({ emailHash: emailHash