├── .circleci └── config.yml ├── .gitattributes ├── .gitignore ├── .jscsrc ├── .jshintignore ├── .jshintrc ├── .npmignore ├── CNAME ├── README.md ├── TestIntegration ├── pom.xml ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── iabtechlab │ │ │ └── digitrust │ │ │ └── test │ │ │ └── Integration │ │ │ └── App.java │ └── test │ │ └── java │ │ └── com │ │ └── iabtechlab │ │ └── digitrust │ │ └── test │ │ └── Integration │ │ ├── SearchForDigitrustTests.java │ │ └── SimpleTests.java └── target │ └── classes │ └── META-INF │ └── MANIFEST.MF ├── _config.yml ├── deployment-sample.json ├── dist ├── dt.html ├── info.html └── redirect.html ├── documentation ├── README_development.md └── debugging.md ├── file_sizes.txt ├── jest.config.js ├── karma.conf.js ├── license.txt ├── misc ├── custom-dt.css ├── detectingadblockusers.png ├── faked_id_service_v1.json ├── page2.html ├── powered_by.jpg ├── powered_by.png ├── publisher.html └── publisher.jpg ├── package.json ├── pages ├── cmp-iframe.html ├── decrypting.html ├── dt.html ├── info.html ├── key.json ├── redirect.html └── selected_mark.png ├── samples ├── fromIframe.html ├── nested_frames │ ├── README.md │ ├── iframe_1.html │ ├── iframe_2.html │ └── index.html ├── pubhost_multiframe_sample.html ├── sample01.html └── sample03_largeconfig.html ├── serve.json ├── src ├── config │ ├── GeneralConfig.js │ ├── constants.json │ ├── env.json │ ├── errors.json │ ├── gdpr-lang.json │ ├── initializeOptions.json │ └── key.json ├── digitrust_client.js ├── modules │ ├── ConfigLoader.js │ ├── DebugControl.js │ ├── DigiTrust.js │ ├── DigiTrustCommunication.js │ ├── DigiTrustConsent.js │ ├── DigiTrustCookie.js │ ├── DigiTrustCrypto.js │ ├── MinPubSub.js │ ├── ServerCrypto.js │ ├── helpers.js │ └── logger.js └── tool_scripts │ ├── buildFrameV1.js │ ├── buildFrameV2.js │ ├── build_frame.js │ ├── checkSourceForConsole.js │ └── check_sourcecode.js └── test ├── distsizes.txt ├── integration └── Readme.md ├── jest ├── communication.test.js ├── configLoader.test.js ├── debugControl.test.js ├── digitrustBase.test.js ├── digitrustClient.test.js ├── helpers.test.js └── logger.test.js ├── s.binary.txt ├── s.txt └── unit ├── communicationSpec.js ├── digitrustClientSpec.js ├── dtCookieSpec.js └── helpersSpec.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: circleci/node:8-browsers 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/mongo:3.4.4 16 | 17 | working_directory: ~/repo 18 | 19 | steps: 20 | - checkout 21 | 22 | # Download and cache dependencies 23 | - restore_cache: 24 | keys: 25 | - v1-dependencies-{{ checksum "package.json" }} 26 | # fallback to using the latest cache if no exact match is found 27 | - v1-dependencies- 28 | 29 | - run: yarn install 30 | 31 | - save_cache: 32 | paths: 33 | - node_modules 34 | key: v1-dependencies-{{ checksum "package.json" }} 35 | 36 | # rebuild 37 | - run: yarn build 38 | 39 | # run tests! 40 | - run: sleep 5 41 | - run: yarn test 42 | 43 | - deploy: 44 | command: | 45 | echo -n '{"current":"prod"}' > src/config/env.json 46 | yarn run build 47 | sudo apt-get -y -qq install awscli 48 | echo "Here I am. Current dir and contents below" 49 | pwd 50 | sed -n 's/module.exports = \(.*\)/\1/gp' src/_version.js > versionmin.txt 51 | digi_version=`cat versionmin.txt` 52 | digi_version=`echo "${digi_version:1:${#digi_version}-2}"` 53 | echo "DigiTrust Version: $digi_version" 54 | echo "Ready aws client" 55 | echo "" 56 | aws s3 sync dist/ s3://js-origin-$CIRCLE_BRANCH.digitru.st/prod/$digi_version/ --delete --cache-control max-age=86400 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers 57 | aws s3 cp dist/digitrust.min.js s3://js-origin-$CIRCLE_BRANCH.digitru.st/prod/1/digitrust.min.js --cache-control max-age=86400 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers 58 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist/ 4 | coverage 5 | npm-debug.log 6 | doc 7 | deployment.json 8 | src/config/env.json 9 | *.class 10 | /TestIntegration/target/** 11 | yarn.lock 12 | test.log 13 | yarn-error.log 14 | web.config 15 | src/_version.js 16 | out 17 | .vs 18 | package-lock.json -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "yandex", 3 | "excludeFiles": [ 4 | "node_modules/**", 5 | "README.md", 6 | "dist/**", 7 | "coverage/**", 8 | "karma.conf.js", 9 | "Gruntfile.js", 10 | "pages/**" 11 | ], 12 | "disallowEmptyBlocks": null, 13 | "requireDotNotation": { 14 | "allExcept": ["keywords"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | src/tests/** 3 | dist/** 4 | coverage/** 5 | karma.conf.js 6 | Gruntfile.js 7 | pages/** -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Stricter flags 3 | "bitwise": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "forin": true, 7 | "freeze": true, 8 | "futurehostile": true, 9 | "latedef": true, 10 | "noarg": true, 11 | "nonbsp": true, 12 | "nonew": true, 13 | "strict": true, 14 | "undef": true, 15 | "sub": true, 16 | "browserify": true, 17 | "browser": true, 18 | "predef": ["ActiveXObject", "crypto", "msCrypto", "console", "Promise"] 19 | 20 | } 21 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | CNAME 2 | misc 3 | node-server.js 4 | test 5 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | docs.digitru.st -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DigiTrust 2 | 3 | DigiTrust is an independent third-party anonymous identity provider. 4 | 5 | The DigiTrust code base relies on Node.js, Grunt and Browserify among other libraries. 6 | Please review the file `README_development.md` for setup of development environment. 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestIntegration/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.iabtechlab.digitrust.test 7 | TestIntegration 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | TestIntegration 12 | http://maven.apache.org 13 | 14 | 15 | UTF-8 16 | 1.8 17 | 5.3.1 18 | 1.3.1 19 | 3.14.0 20 | ${java.version} 21 | ${java.version} 22 | 23 | 24 | 25 | 26 | 27 | maven-compiler-plugin 28 | 3.1 29 | 30 | ${java.version} 31 | ${java.version} 32 | 33 | 34 | 35 | maven-surefire-plugin 36 | 2.22.0 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.junit.jupiter 44 | junit-jupiter-engine 45 | ${junit.jupiter.version} 46 | test 47 | 48 | 49 | org.junit.jupiter 50 | junit-jupiter-api 51 | ${junit.jupiter.version} 52 | test 53 | 54 | 55 | 56 | org.junit.platform 57 | junit-platform-runner 58 | ${junit.platform.version} 59 | test 60 | 61 | 62 | org.seleniumhq.selenium 63 | selenium-java 64 | 3.14.0 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-surefire-plugin 71 | 2.22.0 72 | test 73 | 74 | 75 | 76 | org.seleniumhq.selenium 77 | selenium-java 78 | ${selenium.version} 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /TestIntegration/src/main/java/com/iabtechlab/digitrust/test/Integration/App.java: -------------------------------------------------------------------------------- 1 | package com.iabtechlab.digitrust.test.Integration; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello DigiTrust Testing. This is a Selenium test project for DigiTrust library" ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /TestIntegration/src/test/java/com/iabtechlab/digitrust/test/Integration/SearchForDigitrustTests.java: -------------------------------------------------------------------------------- 1 | package com.iabtechlab.digitrust.test.Integration; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.chrome.ChromeDriver; 6 | import org.openqa.selenium.support.ui.ExpectedCondition; 7 | import org.openqa.selenium.support.ui.WebDriverWait; 8 | 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | import java.io.IOException; 12 | 13 | import org.junit.jupiter.api.AfterAll; 14 | import org.junit.jupiter.api.BeforeAll; 15 | import org.junit.jupiter.api.Test; 16 | import org.openqa.selenium.By; 17 | import org.openqa.selenium.TakesScreenshot; 18 | 19 | public class SearchForDigitrustTests { 20 | private String baseUrl; 21 | private WebDriver driver; 22 | // private ScreenshotHelper screenshotHelper; 23 | 24 | @BeforeAll 25 | public void openBrowser() { 26 | baseUrl = System.getProperty("webdriver.base.url"); 27 | driver = new ChromeDriver(); 28 | driver.get(baseUrl); 29 | // screenshotHelper = new ScreenshotHelper(); 30 | } 31 | 32 | @AfterAll 33 | public void saveScreenshotAndCloseBrowser() throws IOException { 34 | // screenshotHelper.saveScreenshot("screenshot.png"); 35 | driver.quit(); 36 | } 37 | 38 | 39 | @Test 40 | public void pageTitleAfterSearchShouldBeginWithDigi() throws IOException { 41 | assertEquals("The page title should equal Google at the start of the test.", "Google", driver.getTitle()); 42 | WebElement searchField = driver.findElement(By.name("q")); 43 | searchField.sendKeys("digit"); 44 | searchField.submit(); 45 | 46 | WebDriverWait wait = new WebDriverWait(driver, 10); 47 | Object objResult = wait.until(new ExpectedCondition() { 48 | @Override 49 | public Object apply(Object drv) { 50 | WebDriver d = (WebDriver)drv; 51 | return d.getTitle().toLowerCase().startsWith("digitr"); 52 | } 53 | }); 54 | 55 | // assertTrue("Title has something", objResult); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /TestIntegration/src/test/java/com/iabtechlab/digitrust/test/Integration/SimpleTests.java: -------------------------------------------------------------------------------- 1 | package com.iabtechlab.digitrust.test.Integration; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.BeforeEach; 7 | 8 | class SimpleTests { 9 | 10 | @BeforeEach 11 | void setUp() throws Exception { 12 | } 13 | 14 | @Test 15 | void test() { 16 | assertTrue(true); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /TestIntegration/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Built-By: chris.cole 3 | Build-Jdk: 1.8.0_181 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /deployment-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /dist/dt.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | DigiTru.st Identity 6 | 7 | 8 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /dist/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | INFO PAGE 4 | 5 |
You are opted:
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dist/redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DigiTru.st Identity 6 | 7 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /documentation/README_development.md: -------------------------------------------------------------------------------- 1 | # DigiTrust 2 | 3 | The DigiTrust code base relies on Node.js, Grunt and Browserify among other libraries. 4 | 5 | ### Local Development 6 | 7 | To initialize your local repository for development, clone this repository and run: 8 | 9 | #install dependencies 10 | yarn install 11 | # build only 12 | yarn build 13 | 14 | # build & watch script for client 15 | yarn devwatch 16 | 17 | # generate new key pair 18 | grunt generateKey --keyversion N 19 | 20 | 21 | #### Environment Setup 22 | Use your host file to set this host pointer for two local websites. You will need webserver 23 | on your system for your environment. If you don't have IIS or Apache available, try nginx. 24 | Webserver configuration is beyond scope of this document. 25 | 26 | local.digitru.st 127.0.0.1 27 | local.pubsite.ed 127.0.0.1 28 | 29 | Point your webserver and both sites to the root of your source repository. 30 | Access your site samples at: 31 | 32 | http://local.pubsite.ed/samples/sample01.html 33 | 34 | For best results setup SSL certificates on your site. One option is SSL and details 35 | will be specific to your webserver. 36 | https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/ 37 | https://aboutssl.org/how-to-create-a-self-signed-certificate-in-iis/ 38 | 39 | 40 | Available environments: *local*, *build*, *prod*. Modify the file `src/config/env.json` to use *local* 41 | for local development. 42 | 43 | Before committing, you can run the following to validate your code 44 | 45 | yarn test 46 | 47 | They will be automatically run on push. The Circle CI build will fail if the unit tests fail 48 | 49 | 50 | ### Production Releases 51 | 52 | In general we are using "[three-flow](http://www.nomachetejuggling.com/2017/04/09/a-different-branching-strategy/)" to manage mostly automated releases. 53 | Releases are branched off of master into `candidate` and then into a `release` branch. 54 | In order to get automated Releases in github we tag releases in master as well. 55 | 56 | To verify the current release version, consult this URL https://cdn.digitru.st/prod/1/digitrust.min.js or load the 57 | test page Prebid.js/integrationExamples/gpt/digitrust_Full.html and type `DigiTrust.version` in the debug console. 58 | 59 | 1. Update `version` in `package.json` 60 | 2. Build with command `yarn build` 61 | 3. Commit and push your changes to master branch 62 | 4. git checkout candidate 63 | 5. git pull 64 | 6. git merge --no-ff master 65 | 7. git tag v1.5.42 (update to your version number as set in step 1) 66 | 8. git push --follow-tags (and then wait to confirm CircleCI build is successful) 67 | 9. git push --force origin v1.5.42:release (then wait for successful CircleCI build) 68 | 10. git checkout master 69 | 11. git push origin v1.5.42 70 | 12. Go to project site on Github and draft a new release 71 | 13. Reflect release notes in the `Release Notes` wiki page at https://github.com/digi-trust/dt-cdn/wiki/Release-Notes 72 | 73 | 74 | ## Development Roadmap Notes 75 | The library is moving to slim down and remove unused code from the iframe. Within the package.json file are two script commands that are part of this, but unused at the moment: 76 | * "buildFrameScript": "browserify src/digitrust_iframe_embed.js -do dist/digitrust_iframe.js", 77 | * "packFrameScript": "uglifyjs dist/digitrust_iframe.js -o dist/digitrust_iframe.min.js", 78 | -------------------------------------------------------------------------------- /documentation/debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging DigiTrust 2 | 3 | A live system may investigated and debugged be interrogating the logs and config settings. 4 | DigiTrust maintains an internal log buffer for these purposes that may be dumped. 5 | 6 | ## Viewing log statements 7 | 8 | After a page load you may instruct DigiTrust to output the log as an array to the developer console. 9 | This array may also be programmatically accessed via the same method. Only the publisher-side logs are 10 | returned from this method. The console output will contain both publisher side (host page) and 11 | DigiTrust IFrame (*.digitru.st domain) log statements. 12 | 13 | ~~~~ 14 | 15 | DigiTrust.debugControl.dumpLogs(); 16 | 17 | ~~~~ 18 | 19 | ## Viewing configuration settings 20 | 21 | The `dumpConfig()` method will output the current configuration settings of the DigiTrust library. 22 | ~~~~ 23 | 24 | DigiTrust.debugControl.dumpConfig(); 25 | 26 | ~~~~ 27 | 28 | ## Enabling heightened debug mode 29 | 30 | DigiTrust can be instructed to enable debug logging. This also causes both publisher side and digitru.st side code 31 | to output basic library information, such as version number, browser, and execution domain. The logs are more often 32 | useful as the initialization information will be included in the log statements. 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /file_sizes.txt: -------------------------------------------------------------------------------- 1 | 2 | List of File Sizes 3 | ================== 4 | This is to track progress on trimming code size. Goal of DIS-28 is to slim down overall size of iframe and associated code. 5 | 6 | 7 | 2/12/2019 8 | 9 | digitrust.min.js 38.7kb 10 | dt.html 5.25kb 11 | dt-embed.html 38.2kb 12 | 13 | 14 | 4/3/2019 15 | 16 | digitrust.min.js 36.9kb 17 | digitrust_iframe.min.js 37.6kb 18 | dt.html 4.98kb 19 | dt-embed.html 42.6kb 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | // All imported modules in your tests should be mocked automatically 6 | // automock: false, 7 | 8 | // Stop running tests after `n` failures 9 | // bail: 0, 10 | 11 | // Respect "browser" field in package.json when resolving modules 12 | // browser: false, 13 | 14 | // The directory where Jest should store its cached dependency information 15 | // cacheDirectory: "C:\\Users\\chris.cole\\AppData\\Local\\Temp\\jest", 16 | 17 | // Automatically clear mock calls and instances between every test 18 | clearMocks: true, 19 | 20 | // Indicates whether the coverage information should be collected while executing the test 21 | // collectCoverage: false, 22 | 23 | // An array of glob patterns indicating a set of files for which coverage information should be collected 24 | // collectCoverageFrom: null, 25 | 26 | // The directory where Jest should output its coverage files 27 | coverageDirectory: "coverage", 28 | 29 | // An array of regexp pattern strings used to skip coverage collection 30 | // coveragePathIgnorePatterns: [ 31 | // "\\\\node_modules\\\\" 32 | // ], 33 | 34 | // A list of reporter names that Jest uses when writing coverage reports 35 | // coverageReporters: [ 36 | // "json", 37 | // "text", 38 | // "lcov", 39 | // "clover" 40 | // ], 41 | 42 | // An object that configures minimum threshold enforcement for coverage results 43 | // coverageThreshold: null, 44 | 45 | // A path to a custom dependency extractor 46 | // dependencyExtractor: null, 47 | 48 | // Make calling deprecated APIs throw helpful error messages 49 | // errorOnDeprecated: false, 50 | 51 | // Force coverage collection from ignored files using an array of glob patterns 52 | // forceCoverageMatch: [], 53 | 54 | // A path to a module which exports an async function that is triggered once before all test suites 55 | // globalSetup: null, 56 | 57 | // A path to a module which exports an async function that is triggered once after all test suites 58 | // globalTeardown: null, 59 | 60 | // A set of global variables that need to be available in all test environments 61 | // globals: {}, 62 | 63 | // An array of directory names to be searched recursively up from the requiring module's location 64 | // moduleDirectories: [ 65 | // "node_modules" 66 | // ], 67 | 68 | // An array of file extensions your modules use 69 | // moduleFileExtensions: [ 70 | // "js", 71 | // "json", 72 | // "jsx", 73 | // "ts", 74 | // "tsx", 75 | // "node" 76 | // ], 77 | 78 | // A map from regular expressions to module names that allow to stub out resources with a single module 79 | // moduleNameMapper: {}, 80 | 81 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 82 | // modulePathIgnorePatterns: [], 83 | 84 | // Activates notifications for test results 85 | // notify: false, 86 | 87 | // An enum that specifies notification mode. Requires { notify: true } 88 | // notifyMode: "failure-change", 89 | 90 | // A preset that is used as a base for Jest's configuration 91 | // preset: null, 92 | 93 | // Run tests from one or more projects 94 | // projects: null, 95 | 96 | // Use this configuration option to add custom reporters to Jest 97 | // reporters: undefined, 98 | 99 | // Automatically reset mock state between every test 100 | // resetMocks: false, 101 | 102 | // Reset the module registry before running each individual test 103 | // resetModules: false, 104 | 105 | // A path to a custom resolver 106 | // resolver: null, 107 | 108 | // Automatically restore mock state between every test 109 | // restoreMocks: false, 110 | 111 | // The root directory that Jest should scan for tests and modules within 112 | // rootDir: null, 113 | 114 | // A list of paths to directories that Jest should use to search for files in 115 | // roots: [ 116 | // "" 117 | // ], 118 | 119 | // Allows you to use a custom runner instead of Jest's default test runner 120 | // runner: "jest-runner", 121 | 122 | // The paths to modules that run some code to configure or set up the testing environment before each test 123 | // setupFiles: [], 124 | 125 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 126 | // setupFilesAfterEnv: [], 127 | 128 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 129 | // snapshotSerializers: [], 130 | 131 | // The test environment that will be used for testing 132 | // testEnvironment: "jest-environment-jsdom", 133 | 134 | // Options that will be passed to the testEnvironment 135 | // testEnvironmentOptions: {}, 136 | 137 | // Adds a location field to test results 138 | // testLocationInResults: false, 139 | 140 | // The glob patterns Jest uses to detect test files 141 | // testMatch: [ 142 | // "**/__tests__/**/*.[jt]s?(x)", 143 | // "**/?(*.)+(spec|test).[tj]s?(x)" 144 | // ], 145 | 146 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 147 | // testPathIgnorePatterns: [ 148 | // "\\\\node_modules\\\\" 149 | // ], 150 | 151 | // The regexp pattern or array of patterns that Jest uses to detect test files 152 | // testRegex: [], 153 | 154 | // This option allows the use of a custom results processor 155 | // testResultsProcessor: null, 156 | 157 | // This option allows use of a custom test runner 158 | testRunner: "jasmine2", 159 | 160 | // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href 161 | // testURL: "http://localhost", 162 | 163 | // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" 164 | // timers: "real", 165 | 166 | // A map from regular expressions to paths to transformers 167 | // transform: null, 168 | 169 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 170 | // transformIgnorePatterns: [ 171 | // "\\\\node_modules\\\\" 172 | // ], 173 | 174 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 175 | // unmockedModulePathPatterns: undefined, 176 | 177 | // Indicates whether each individual test should be reported during the run 178 | // verbose: null, 179 | 180 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 181 | // watchPathIgnorePatterns: [], 182 | 183 | // Whether to use watchman for file crawling 184 | // watchman: true, 185 | }; 186 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Wed Sep 05 2018 12:53:10 GMT-0700 (Pacific Daylight Time) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jasmine', 'browserify'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'test/unit/*.js' 19 | ], 20 | 21 | 22 | // list of files / patterns to exclude 23 | exclude: [ 24 | ], 25 | 26 | 27 | // preprocess matching files before serving them to the browser 28 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 29 | preprocessors: { 30 | 'test/unit/*.js': ['browserify'] 31 | }, 32 | 33 | // test results reporter to use 34 | // possible values: 'dots', 'progress' 35 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 36 | reporters: ['progress'], 37 | 38 | 39 | // web server port 40 | port: 9876, 41 | 42 | 43 | // enable / disable colors in the output (reporters and logs) 44 | colors: true, 45 | 46 | 47 | // level of logging 48 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 49 | logLevel: config.LOG_DEBUG, 50 | 51 | 52 | // enable / disable watching file and executing tests whenever any file changes 53 | autoWatch: true, 54 | 55 | 56 | // start these browsers 57 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 58 | // browsers: ['Chrome', 'Firefox', 'IE'], 59 | browsers: ['Firefox'], 60 | 61 | browserConsoleLogOptions: { 62 | level: "debug", 63 | path: "./test.log" 64 | }, 65 | 66 | 67 | // Continuous Integration mode 68 | // if true, Karma captures browsers, runs the tests and exits 69 | singleRun: false, 70 | 71 | // Concurrency level 72 | // how many browser should be started simultaneous 73 | concurrency: Infinity 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /misc/custom-dt.css: -------------------------------------------------------------------------------- 1 | #digitrust-adb-reload { 2 | cursor: pointer; 3 | background: #006080; 4 | color: #FFF; 5 | font-size: 15px; 6 | font-weight: 600; 7 | letter-spacing: .05em; 8 | position: absolute; 9 | text-align: center; 10 | border-bottom: 10px solid #279CBF; 11 | padding: 30px 50px 20px; 12 | bottom: -45px; 13 | right: 30px; 14 | text-transform: uppercase; 15 | width: 365px; 16 | } 17 | 18 | #digitrust-publisher-logo { 19 | display: block; 20 | max-width: 90%; 21 | } 22 | 23 | #digitrust-powered-by-logo { 24 | width: 150px; 25 | } 26 | 27 | #digitrust-powered-by-container { 28 | font-size: .8em; 29 | color: #9B9B99; 30 | position: absolute; 31 | bottom: 20px; 32 | left: 30px; 33 | } 34 | 35 | /* configGeneral.htmlIDs.dtAdbMessage */ 36 | #digitrust-adb-message { 37 | float: left; 38 | width: 250px; 39 | margin: 15px 0 85px; 40 | } 41 | 42 | /* configGeneral.htmlIDs.publisherPicture */ 43 | #dt-pub-pic { 44 | margin: 15px 0 20px 0; 45 | float: right; 46 | width: 465px; 47 | } 48 | 49 | /* configGeneral.htmlIDs.dtAdbContainer */ 50 | #digitrust-adb-container { 51 | width: 740px; 52 | font-weight: 300; 53 | position: absolute; 54 | padding: 50px 30px 30px 30px; 55 | margin: 80px 0 70px; 56 | left: 50%; 57 | transform: translate(-50%, 0); 58 | background: #ffffff; 59 | color: #000000; 60 | opacity: 1; 61 | font-family: Arial, sans-serif; 62 | font-size: 15px; 63 | text-shadow: none; 64 | border: 1px solid #D8D8D8; 65 | border-top-width: 30px; 66 | border-top-left-radius: 7px; 67 | border-top-right-radius: 7px; 68 | border-bottom-width: 10px; 69 | border-bottom-left-radius: 7px; 70 | border-bottom-right-radius: 7px; 71 | border-bottom-color: #2E7C97; 72 | box-shadow: 0px 0px 15px 5px rgba(0,0,0,0.15); 73 | } 74 | 75 | #digitrust-scroll-container { 76 | overflow-y: scroll; 77 | width: 100%; 78 | height: 100%; 79 | position: absolute; 80 | } 81 | 82 | #digitrust-adb-bg { 83 | z-index: 999999; 84 | width: 100%; 85 | height: 100%; 86 | top: 0; 87 | left: 0; 88 | position: fixed; 89 | overflow-y: scroll; 90 | } 91 | 92 | #digitrust-optout { 93 | padding: 0 0 0 10px; 94 | } 95 | 96 | #digitrust-c-text { 97 | padding: 5px 50px; 98 | } 99 | 100 | #digitrust-c-info { 101 | padding: 5px 15px; 102 | float: left; 103 | background: #999999; 104 | color: #ffffff; 105 | font-size: 16px; 106 | font-style: italic; 107 | top: 0; 108 | left: 0; 109 | position: absolute; 110 | border-bottom-right-radius: 5px; 111 | } 112 | 113 | #digitrust-c-bg { 114 | width: 100%; 115 | bottom: 0; 116 | left: 0; 117 | position: fixed; 118 | font-size: 12px; 119 | line-height: 18px; 120 | } 121 | 122 | #digitrust-apps-options { 123 | bottom: 0; 124 | left: 0; 125 | right: 0; 126 | padding: 5px; 127 | position: fixed; 128 | font-size: 12px; 129 | line-height: 18px; 130 | } 131 | 132 | #digitrust-apps-options-close { 133 | cursor: pointer; 134 | position: absolute; 135 | right: 7px; 136 | top: 5px; 137 | font-weight: bold; 138 | } 139 | 140 | #digitrust-apps-select-container { 141 | height: 370px; 142 | width: 485px; 143 | float: right; 144 | margin: 10px -10px 10px 0; 145 | overflow-y: scroll; 146 | } 147 | 148 | .dt-app { 149 | font-size: 10px; 150 | width: 200px; 151 | float: left; 152 | text-align: left; 153 | border: 1px solid #EEE; 154 | margin: 10px; 155 | padding: 30px 10px 10px 10px; 156 | box-shadow: 0px 0px 5px 5px rgba(0,0,0,0.10); 157 | cursor: pointer; 158 | } -------------------------------------------------------------------------------- /misc/detectingadblockusers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/misc/detectingadblockusers.png -------------------------------------------------------------------------------- /misc/faked_id_service_v1.json: -------------------------------------------------------------------------------- 1 | {"id":"gUBPJsGtVPfCErmfcZLvNYeAoILjSMGuIRSWCHZc25q8Sk3BBMoKA1Ly14mze53y6x8z0BDclX8Yv2+PbTglcQAihOAOIsqvCiaqPseTbWQV3VFA2CVMdiRTj6JxM7rmyhmWz1qYDNSL1+6S0QArI00PIUlu9GbFod3uyU8/FqrfPSn+xDnweVIqDpnwTEOlidXCotgjY1aKR4y81ZRZ7YG1OE2u76qVb2MvqL5Brq/LiarvMTc4uHxT3p44VgQSQ2/cmigf6VRVEPmSjK0L/77pMc2Z2b3lWQPRS41SUwky+cst8G+QRmKhibglAM6cV39lg8xnXAKxqINmgXQuhw==","version":2,"producer":"1CrsdUNAo6","privacy":{"optout":false},"keyv":4} -------------------------------------------------------------------------------- /misc/page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | 28 | 29 | 30 |

Page 2

31 | This is just. 32 |
A test.
33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /misc/powered_by.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/misc/powered_by.jpg -------------------------------------------------------------------------------- /misc/powered_by.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/misc/powered_by.png -------------------------------------------------------------------------------- /misc/publisher.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 45 | 46 | 47 | plain text. 48 |

Great news

49 |

This is something you are reading.

50 | 51 | Link external 52 | 53 |


54 | clear cookie 55 |


56 | Link internal: page.html 57 |


58 | Link internal: ./page.html 59 |


60 | Link internal: /misc/page.html 61 |


62 | Link internal: #foobar 63 |


64 | This is just. 65 |
A test.
66 |
67 |
68 |
69 |
70 |
A test.
71 |
72 |
73 |
74 |
75 |
A test.
76 |
77 |
78 |
79 |
80 |
A test.
81 |
82 |
83 |
84 |
85 |
A test.
86 |
87 |
88 |
89 |
90 |
A test.
91 |
92 |
93 |
94 |
95 |
A test.
96 |
97 |
98 |
99 |
100 |
A test.
101 |
102 |
103 |
104 |
105 | 106 | -------------------------------------------------------------------------------- /misc/publisher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/misc/publisher.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digitrust", 3 | "version": "1.5.41", 4 | "description": "Package for a universal ID for registered ad servers", 5 | "main": "dist/digitrust.min.js", 6 | "scripts": { 7 | "oldtest": "karma start karma.conf.js --single-run", 8 | "oldunit": "karma start karma.conf.js", 9 | "test": "jest", 10 | "jest": "jest", 11 | "coverage": "jest --coverage", 12 | "copypages": "copyfiles -f ./pages/*.* ./dist", 13 | "versionUpdate": "genversion src/_version.js", 14 | "buildclient": "browserify src/digitrust_client.js -do dist/digitrust.js", 15 | "buildFrameScript": "browserify src/digitrust_iframe_embed.js -do dist/digitrust_iframe.js", 16 | "packFrameScript": "uglifyjs dist/digitrust_iframe.js -o dist/digitrust_iframe.min.js", 17 | "buildFrame": "npm-run-series buildFrameScript packFrameScript buildV2DebugFrame", 18 | "buildV2DebugFrame": "node ./src/tool_scripts/buildFrameV2.js", 19 | "buildV1DebugFrame": "node ./src/tool_scripts/buildFrameV1.js", 20 | "checkSourcecode": "node ./src/tool_scripts/checkSourceForConsole.js", 21 | "uglifyc": "uglifyjs dist/digitrust.js -o dist/digitrust.min.js", 22 | "uglify": "npm-run-series uglifyc", 23 | "build": "npm-run-series versionUpdate checkSourcecode buildclient uglify copypages buildV1DebugFrame", 24 | "devwatch": "watchify src/digitrust_client.js -do dist/digitrust.js", 25 | "docCompiled": "jsdoc ./dist/digitrust.js -P package.json", 26 | "document": "jsdoc ./dist/digitrust.js -P package.json" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git@github.com:digi-trust/dt-cdn.git" 31 | }, 32 | "author": "IAB Tech Lab / Digitrust (http://www.digitru.st/)", 33 | "license": "Apache-2.0", 34 | "bugs": { 35 | "url": "https://github.com/digi-trust/dt-cdn/issues" 36 | }, 37 | "homepage": "https://github.com/digi-trust/dt-cdn#readme", 38 | "devDependencies": { 39 | "browserify": "^16.2.2", 40 | "copyfiles": "^2.1.0", 41 | "genversion": "^2.1.0", 42 | "jasmine-core": "^3.2.1", 43 | "jest": "^24.7.1", 44 | "jsdoc": "^3.5.5", 45 | "karma": "^3.0.0", 46 | "karma-browserify": "^5.3.0", 47 | "karma-chrome-launcher": "^2.2.0", 48 | "karma-firefox-launcher": "^1.1.0", 49 | "karma-ie-launcher": "^1.0.0", 50 | "karma-jasmine": "^1.1.2", 51 | "npm-run-series": "^1.0.1", 52 | "uglify-js": "^3.4.9", 53 | "watchify": "^3.11.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pages/cmp-iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /pages/decrypting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Decrypting: DigiTrust ID 5 | 6 | 18 | 19 | 20 | 21 | 22 |

How to decrypt the DigiTrust ID

23 |

OpenSSL

24 |
25 |
 26 | base64 -D -i encrypted_id_from_iframe.txt -o encrypted_id_binary.txt
 27 | /usr/local/bin/openssl pkeyutl -decrypt -inkey pkcs8.pem -pkeyopt rsa_padding_mode:oaep -in encrypted_id_binary.txt
 28 | 
29 | 30 | 31 | 32 |

PHP

33 |
<?php
 34 |     $pemPrivateKey = '-----BEGIN PRIVATE KEY-----
 35 | YOUR KEY HERE
 36 | -----END PRIVATE KEY-----';
 37 | 
 38 |     $encryptedMessage =  'BASE64 ENCRYPTED MESSAGE';
 39 | 
 40 |     $privateKey = openssl_get_privatekey($pemPrivateKey);
 41 |     if (!$privateKey) {
 42 |         echo "Cannot get private key";
 43 |     }
 44 |     
 45 |     $binaryMessage = base64_decode($encryptedMessage);
 46 |     $b = openssl_private_decrypt($binaryMessage, $decr, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);
 47 |     if (!$b) {
 48 |         echo "Cannot decode message";
 49 |     }
 50 |     echo "Decrypted message: " . $decr;
 51 | ?>
 52 | 
53 | 54 | 55 |

Java

56 |
package com.something.misc;
 57 | 
 58 | import java.io.DataInputStream;
 59 | import java.io.File;
 60 | import java.io.FileInputStream;
 61 | import java.security.Key;
 62 | import java.security.KeyFactory;
 63 | import java.security.spec.PKCS8EncodedKeySpec;
 64 | 
 65 | import javax.crypto.Cipher;
 66 | 
 67 | public class DigiTrustIdParsing {
 68 |     final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
 69 | 
 70 |     public static void main(String[] args) throws Exception {
 71 | 
 72 |         Key privKey = readPrivateKey();
 73 | 
 74 |         // read in ciphertext
 75 |         byte[] ciphertext = readFully(new File("/Users/stingleff/src/digitrust-sandbox/encrypted-string.txt"));
 76 | 
 77 |         Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
 78 |         cipher.init(Cipher.DECRYPT_MODE, privKey);
 79 |         byte[] plainText = cipher.doFinal(ciphertext);
 80 | 
 81 |         System.out.println(new String(plainText));
 82 |     }
 83 | 
 84 |     private static Key readPrivateKey() throws Exception {
 85 |         // given an openssl private key in pem format
 86 |         // first do this
 87 |         // openssl pkcs8 -topk8 -nocrypt -in private.pem -outform DER -out private.pkcs8
 88 | 
 89 |         byte[] privKeyBytes = readFully(new File(
 90 |                 "/path-to/private.pkcs8"));
 91 |         PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privKeyBytes);
 92 |         KeyFactory kf = KeyFactory.getInstance("RSA");
 93 |         Key privKey = kf.generatePrivate(spec);
 94 |         return privKey;
 95 |     }
 96 | 
 97 |     public static byte[] hexStringToByteArray(String s) {
 98 |         int len = s.length();
 99 |         byte[] data = new byte[len / 2];
100 |         for (int i = 0; i < len; i += 2) {
101 |             data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
102 |                                  + Character.digit(s.charAt(i+1), 16));
103 |         }
104 |         return data;
105 |     }
106 | 
107 |     private static String bytesToHex(byte[] bytes) {
108 |         char[] hexChars = new char[bytes.length * 2];
109 |         for ( int j = 0; j < bytes.length; j++ ) {
110 |             int v = bytes[j] & 0xFF;
111 |             hexChars[j * 2] = hexArray[v >>> 4];
112 |             hexChars[j * 2 + 1] = hexArray[v & 0x0F];
113 |         }
114 |         return new String(hexChars);
115 |     }
116 | 
117 |     private static byte[] readFully(File f) throws Exception {
118 |         FileInputStream fis = new FileInputStream(f);
119 |         DataInputStream dis = new DataInputStream(fis);
120 |         byte[] bytes = new byte[(int) f.length()];
121 |         dis.readFully(bytes);
122 |         dis.close();
123 |         fis.close();
124 |         return bytes;
125 |     }
126 | }
127 | 
128 | 129 |

Node.js

130 |
// https://www.npmjs.com/package/subtle
131 | subtle.importKey(
132 |     'pkcs8',
133 |     new Buffer('base64 encoded private key', 'base64'),
134 |     {
135 |         name: "RSA-OAEP",
136 |         hash: {
137 |             name: "SHA-1"
138 |         }
139 |     },
140 |     false,
141 |     ["decrypt"]
142 | )
143 | .then( function(cryptokey) {
144 |     subtle.decrypt(
145 |         {
146 |             name: "RSA-OAEP",
147 |             hash: {
148 |                 name: "SHA-1"
149 |             }
150 |         },
151 |         cryptokey,
152 |         new Buffer('value to decrypt', 'base64')
153 |     )
154 |     .then( function (decryptedValueArrayBuffer) {
155 |         console.log('Just decrypted: ', decryptedValueArrayBuffer.toString());
156 |     });
157 | });
158 | 
159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /pages/dt.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | DigiTru.st Identity 6 | 7 | 8 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /pages/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | INFO PAGE 4 | 5 |
You are opted:
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /pages/key.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "RSA-OAEP", 3 | "hash": { 4 | "name": "SHA-1" 5 | }, 6 | "version": 4, 7 | "spki": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgrdFWb07eQFRtdmXcnVRpSZFoibNFMZDEZHn71j6oa5Ohw7miu/Cpl77h2Pp/0bLt3dHr6RcinqA9cck2nPjJEw2svSzJOHY1409Cxr7cyAhfmueLazL/C8DOyFSe3e4QGNsJtPTlNy6Etmnb4dvctpm/nQ2nDaPw5wnb0hWI6Ik7wtvjbH9SaCRlXcyEKpF1oXy55jDJeovSxQz9eL+bgObD2Lz43gidU4B/zPhbNI+KmMkV539okyFfmcBwrCQARkh9d3eI8kAH+PptTalApVAefPSGZdWkSvkNw7HEbcnLMWWWXKeF7z2lMBd7RbnCyBUmgtHLY6d8HX6JPWB6QIDAQAB", 8 | "jwk": { 9 | "kty": "RSA", 10 | "kid": "fb8cd98a-d21b-4cd6-8b3c-182727effee4", 11 | "n": "grdFWb07eQFRtdmXcnVRpSZFoibNFMZDEZHn71j6oa5Ohw7miu_Cpl77h2Pp_0bLt3dHr6RcinqA9cck2nPjJEw2svSzJOHY1409Cxr7cyAhfmueLazL_C8DOyFSe3e4QGNsJtPTlNy6Etmnb4dvctpm_nQ2nDaPw5wnb0hWI6Ik7wtvjbH9SaCRlXcyEKpF1oXy55jDJeovSxQz9eL-bgObD2Lz43gidU4B_zPhbNI-KmMkV539okyFfmcBwrCQARkh9d3eI8kAH-PptTalApVAefPSGZdWkSvkNw7HEbcnLMWWWXKeF7z2lMBd7RbnCyBUmgtHLY6d8HX6JPWB6Q", 12 | "e": "AQAB", 13 | "alg": "RSA-OAEP", 14 | "ext": true, 15 | "key_ops": [ 16 | "encrypt" 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /pages/redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DigiTru.st Identity 6 | 7 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /pages/selected_mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/pages/selected_mark.png -------------------------------------------------------------------------------- /samples/fromIframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Accessing Digitrust Id from Iframe 5 | 6 | 7 | This is a second iframe with domain name: 8 |

Trying to access Digitrust library 9 | 10 |

11 | 
12 | 	
13 | 14 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /samples/nested_frames/README.md: -------------------------------------------------------------------------------- 1 | # DigiTrust-IframeSupport 2 | 3 | # Problem 4 | When publisher loads the DigiTrust library on top-frame of the page, the ad-tech partners executing in cross-domain iframes on the page are not able to access the DigiTrust library and are unable to retrieve the Digitrust Id. As many tags / user-syncup executes in iframes it makes Digitrust Id un-accessible for these partners. 5 | 6 | # Solution 7 | Above code example attempts to create a bridge between Top-frame and iframes that are trying to access Digitrust Id from top-frame. 8 | 9 | # How it works 10 | An extra code (mentioned in index.html) will be loaded with the DigiTrust library, this code will create a friendly-iframe with name "dtLocator" and will add a message event listener which will respond to postMessages coming from iframes to get DigiTrust Id. 11 | 12 | Any partner in cross-domain iframe, trying to access DigiTrust Id will implement/copy the function callDigitrustWhileInIframe (mentioned in iframe_2.html), this function will simply try to find the dtLocator iframe and will send a PostMessage to retrieve the DigiTrust Id, the function accepts a callback as an argument, this callback will execute upon retrieving the DigiTrust Id. 13 | 14 | The iframe created for dt.html can also be named as dtLocator to avoid two iframes being created. 15 | 16 | The solution is inspired from cmpLocator module from CMPs used in GDPR. 17 | 18 | # How to use? 19 | Assuming you already have a web server running on your machine on port 80. 20 | 21 | Edit "hosts" file on your machine with command, sudo vi /etc/hosts 22 | Add following entries to "hosts" file and save the file 23 | 127.0.0.1 example1.com 24 | 127.0.0.1 example2.com 25 | 127.0.0.1 example_nest.com 26 | 27 | To apply new DNS entries made in hosts file execute this command, sudo killall -HUP mDNSResponder 28 | Now open http://buzz.com/Digitrust-IframeSupport/ in your browser 29 | If new DNS entries are still not reflecting, then if you are using Chrome browser, open chrome://net-internals/#dns in your browser and click button "Clear host cache". 30 | 31 | -------------------------------------------------------------------------------- /samples/nested_frames/iframe_1.html: -------------------------------------------------------------------------------- 1 | 2 | This is a first iframe with domain name: 3 |


4 | 5 | -------------------------------------------------------------------------------- /samples/nested_frames/iframe_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | This is a second iframe with domain name: 8 |

Trying to access Digitrust library 9 | 10 |

11 | 
12 | 	
13 | 14 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /samples/nested_frames/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Here we will load Digitrust library... 8 | 9 |
10 | 11 | 12 | 19 | 20 |
21 | And some extra code to support iframes 22 | 23 | 70 | 71 |
72 | 73 | 74 |
75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /samples/pubhost_multiframe_sample.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Digitrust Multi IFrame Sample 10 | 11 | 12 | 13 | 57 | 58 | 69 | 70 | 71 | 72 |

Digitrust IFrame Publisher Sample

73 | 74 |

75 | This page demonstrates usage across multiple IFrames 76 |

77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /samples/sample01.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Digitrust Sample top level page 10 | 11 | 12 | 13 | 62 | 63 | 64 |

Digitrust Publisher Sample

65 | 66 |

67 | This page demonstrates how to integrate the Digitrust framework into a publisher site. 68 |

69 | 70 | plain text. 71 |

Great news

72 |

This is something you are reading.

73 | 74 | Link external 75 | 76 |


77 | clear cookie 78 |


79 | Link internal: page.html 80 |


81 | Link internal: ./page.html 82 |


83 | Link internal: /misc/page.html 84 |


85 | Link internal: #foobar 86 |


87 | This is just. 88 |
A test.
89 |
90 |
91 |
92 |
93 |
A test.
94 |
95 |
96 |
97 |
98 |
A test.
99 |
100 |
101 |
102 |
103 |
A test.
104 |
105 |
106 |
107 |
108 |
A test.
109 |
110 |
111 |
112 |
113 |
A test.
114 |
115 |
116 |
117 |
118 |
A test.
119 |
120 |
121 |
122 |
123 |
A test.
124 |
125 |
126 |
127 |
128 | 129 | -------------------------------------------------------------------------------- /serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": [ 3 | { 4 | "key" : "P3P" 5 | "value" : 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"' 6 | }, 7 | { 8 | "key" : "Access-Control-Allow-Origin", 9 | "value" : "*" 10 | }, 11 | { 12 | "key" : "Foo", 13 | "value" : "Chris" 14 | } 15 | ], 16 | { 17 | "source" : "404.html", 18 | "headers" : [{ 19 | "key" : "Cache-Control", 20 | "value" : "max-age=300" 21 | }] 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /src/config/GeneralConfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * GeneralConfig 5 | * @module 6 | * 7 | * @description Configuration settings for various environments. 8 | * Adapted from general.json to avoid errors with manual version number updates. 9 | * @author Chris Cole 10 | * 11 | * */ 12 | 13 | var VERSION = require('../_version.js'); 14 | 15 | // Add an explicit value here to control how builds verify during the build automation testing. 16 | // Normally a build assumes one version prior. This can be used to specify a build number for 17 | // testing purposes in the CircleCI build. Leave null for default behavior 18 | var BUILD_VERSION_OVERRIDE = null; 19 | 20 | var VARIABLE_CURRENT_VERSION = "%CURRENT_VERSION%"; 21 | var VARIABLE_PRIOR_VERSION = "%PRIOR_VERSION%"; 22 | 23 | var configJson = { 24 | "prod": { 25 | "urls": { 26 | "digitrustHostPath": "https://cdn.digitru.st/prod/%CURRENT_VERSION%/", 27 | "digitrustRedirect": "https://cdn.digitru.st/prod/%CURRENT_VERSION%/redirect.html", 28 | "digitrustIframe": "https://cdn.digitru.st/prod/%CURRENT_VERSION%/dt.html", 29 | "digitrustIdService": "https://cdn-cf.digitru.st/id/v1", 30 | "optoutInfo": "http://www.digitru.st/about-this-notice/", 31 | "adblockCheck": "http://stats.aws.rubiconproject.com/" 32 | }, 33 | "redirectInterval": { 34 | "exp": 7 35 | }, 36 | "cookie": { 37 | "version": 2, 38 | "producer": "1CrsdUNAo6", 39 | "publisher": { 40 | "domainKeyValue": "", 41 | "pathKeyValue": "path=/;", 42 | "maxAgeMiliseconds": 604800000, 43 | "userObjectKey": "DigiTrust.v1.identity" 44 | }, 45 | "digitrust": { 46 | "domainKeyValue": "domain=.digitru.st;", 47 | "pathKeyValue": "path=/;", 48 | "maxAgeMiliseconds": 31536000000, 49 | "userObjectKey": "DigiTrust.v1.identity", 50 | "resetKey": "DeleteEverything", 51 | "challenge": "DTChal", 52 | "optout": "optout", 53 | "optoutUser": { 54 | "id": "", 55 | "privacy": { 56 | "optout": true 57 | } 58 | }, 59 | "errorUser": { 60 | "error": true 61 | } 62 | } 63 | }, 64 | "iframe": { 65 | "timeoutDuration": 10000, 66 | "postMessageOrigin": "https://cdn.digitru.st" 67 | }, 68 | "crypto": { 69 | "serverCryptoRate": 0.0 70 | }, 71 | "logging": { 72 | "enable": false, 73 | "level": "ERROR" 74 | }, 75 | "gvlVendorId": 64 76 | }, 77 | "build": { 78 | "urls": { 79 | "digitrustHostPath": "https://cdn.digitru.st/prod/%PRIOR_VERSION%/", 80 | "digitrustRedirect": "https://cdn.digitru.st/prod/%PRIOR_VERSION%/redirect.html", 81 | "digitrustIframe": "https://cdn.digitru.st/prod/%PRIOR_VERSION%/dt.html", 82 | "digitrustIdService": "https://cdn-cf.digitru.st/id/v1", 83 | "optoutInfo": "http://www.digitru.st/about-this-notice/", 84 | "adblockCheck": "http://stats.aws.rubiconproject.com/" 85 | } 86 | }, 87 | "local": { 88 | "urls": { 89 | "digitrustHostPath": "//localhost/dist/", 90 | "digitrustRedirect": "//localhost/dist/redirect.html", 91 | "digitrustIframe": "//local.digitru.st/dist/dt_debug.html", 92 | "digitrustIdService": "http://local.digitru.st/misc/faked_id_service_v1.json", 93 | "optoutInfo": "//localhost/dist/info.html", 94 | "adblockCheck": "//stats.aws.rubiconproject.com/" 95 | }, 96 | "iframe": { 97 | "timeoutDuration": 10000, 98 | "postMessageOrigin": "http://local.digitru.st" 99 | }, 100 | "crypto": { 101 | "serverCryptoRate": 1.0 102 | }, 103 | "logging": { 104 | "level": "DEBUG" 105 | }, 106 | "gvlVendorId": 64 107 | } 108 | } 109 | 110 | 111 | // =============================== METHODS TO RETURN SNAPSHOT OF CONFIG ====================== 112 | 113 | /** 114 | * Calculates the current version and previous version for purposes of file paths 115 | * in config. 116 | * @param {String} ver a package version number 117 | * @param {any} prevVer optional override to previous version for build purposes 118 | */ 119 | function computeVersions(ver, prevVer) { 120 | ver = ver || VERSION; 121 | 122 | var result = { 123 | current: null, 124 | prior: null 125 | }; 126 | 127 | var currentVersion, prevVersion; 128 | var verParts = ver.split('.'); 129 | var prevMinor = parseInt(verParts[verParts.length - 1]); 130 | 131 | if (prevVer == null && BUILD_VERSION_OVERRIDE == null) { 132 | if (isNaN(prevMinor)) { 133 | prevMinor = 0; 134 | } 135 | else { 136 | prevMinor = prevMinor - 1; 137 | } 138 | 139 | currentVersion = ver; 140 | verParts[verParts.length - 1] = new String(prevMinor); 141 | 142 | prevVersion = verParts.join('.'); 143 | } 144 | else { 145 | if (prevVer != null) { 146 | prevVersion = prevVer; 147 | } 148 | else if (BUILD_VERSION_OVERRIDE != null) { 149 | prevVersion = BUILD_VERSION_OVERRIDE; 150 | } 151 | } 152 | 153 | result.current = currentVersion; 154 | result.prior = prevVersion; 155 | 156 | return result; 157 | } 158 | 159 | function replaceUrlVariables(urlObj, variable, value) { 160 | var key, val; 161 | // Replace known URL values 162 | for (key in urlObj) { 163 | if (urlObj.hasOwnProperty(key)) { 164 | val = urlObj[key]; 165 | if (val.indexOf(variable) > -1) { 166 | urlObj[key] = val.replace(variable, value); 167 | } 168 | } 169 | } 170 | } 171 | 172 | /** 173 | * Returns the full configuration JSON with adjustments applied for version numbering 174 | * @function 175 | * 176 | * */ 177 | function getFullConfig(ver, prevVersion) { 178 | ver = ver || VERSION; 179 | 180 | var versionResult = computeVersions(ver, prevVersion); 181 | 182 | var config = configJson; 183 | replaceUrlVariables(config.prod.urls, VARIABLE_CURRENT_VERSION, versionResult.current); 184 | replaceUrlVariables(config.build.urls, VARIABLE_PRIOR_VERSION, versionResult.prior); 185 | 186 | return config; 187 | } 188 | 189 | 190 | module.exports = { 191 | getFullConfig: getFullConfig, 192 | computeVersions: computeVersions 193 | } 194 | -------------------------------------------------------------------------------- /src/config/constants.json: -------------------------------------------------------------------------------- 1 | /* 2 | THIS IS NOW CONSIDERED A DEAD FILE - REMOVE IN FUTURE BUILD 3 | * Constants and IDs that do not change. 4 | * These have been extracted from the general config. 5 | * We do not use the const keyword because at time of writing (2018) not 6 | * all browsers natively support the keyword. Browserfy does not transform 7 | * to rewrite this to a var or let at this time. 8 | */ 9 | { 10 | /* ID values used when building the DigiTrust framework DOM objects */ 11 | /* 12 | "consentLinkId": "digitrust-optout", 13 | "dtAdbContainer": "digitrust-adb-container", // not used 14 | "dtAdbMessage": "digitrust-adb-message", // not used 15 | "publisherPicture": "dt-pub-pic", //not used? 16 | */ 17 | /* dt common frame name */ 18 | /* 19 | "locatorFrameName": "__dtLocator" 20 | */ 21 | } 22 | -------------------------------------------------------------------------------- /src/config/env.json: -------------------------------------------------------------------------------- 1 | {"current":"build"} -------------------------------------------------------------------------------- /src/config/errors.json: -------------------------------------------------------------------------------- 1 | { 2 | "en": { 3 | "memberId": "[DigiTrust Client Error] Missing member ID, add the member ID to the function call options", 4 | "postMessageOrigin": "[DigiTrust Client Error] Origin of postMessage call was not the official DigiTrust domain", 5 | "iframeError": "[DigiTrust Iframe Error] Client could not connect to the iframe", 6 | "appManifestXHR": "[DigiTrust Publisher Error] Client could not retrieve Publisher App Manifest JSON file", 7 | "appManifestInvalid": "[DigiTrust Publisher Error] Publisher App Manifest does not contain valid JSON", 8 | "appNameInvalid": "[DigiTrust App Error] App name does not match available apps in manifest.json", 9 | "iframeMissingMember": "[DigiTrust Iframe Error] Client did not send Member string", 10 | "iframeMissingAppName": "[DigiTrust Iframe Error] Client did not send App Name string" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/config/gdpr-lang.json: -------------------------------------------------------------------------------- 1 | { 2 | "gdprLanguages": [ 3 | "bg", 4 | "hr", 5 | "tr", 6 | "cs", 7 | "da", 8 | "et", 9 | "fi", 10 | "fr", 11 | "fr-be", 12 | "fr-fr", 13 | "fr-lu", 14 | "fr-mc", 15 | "fr-ch", 16 | "de", 17 | "de-at", 18 | "de-de", 19 | "de-li", 20 | "de-lu", 21 | "de-ch", 22 | "el", 23 | "hu", 24 | "gd-ie", 25 | "ga", 26 | "it", 27 | "it-ch", 28 | "lv", 29 | "lt", 30 | "lb", 31 | "mt", 32 | "nl", 33 | "nl-be", 34 | "pl", 35 | "pt", 36 | "rm", 37 | "ro", 38 | "ro-mo", 39 | "sk", 40 | "sl", 41 | "es", 42 | "es-es", 43 | "cy", 44 | "sv", 45 | "sv-fi", 46 | "sv-sv", 47 | "en-gb", 48 | "en-ie", 49 | "mo", 50 | "ru-mo", 51 | "eu", 52 | "ca", 53 | "co", 54 | "fo", 55 | "fy", 56 | "fur", 57 | "gd", 58 | "gl", 59 | "is", 60 | "la", 61 | "no", 62 | "nb", 63 | "nn", 64 | "oc", 65 | "sc", 66 | "sb", 67 | "hsb", 68 | "vo", 69 | "wa", 70 | "ar", 71 | "ast", 72 | "br", 73 | "eo" 74 | ] 75 | } -------------------------------------------------------------------------------- /src/config/initializeOptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "member": "", 3 | "site": "", 4 | "sample": 1, 5 | "redirects": false, 6 | "adblocker": { 7 | "detection": false, 8 | "blockContent": false, 9 | "userMessage": "Did you know advertising pays for this brilliant content? Please disable your ad blocker, then press the Reload button below ... and thank you for your visit!", 10 | "popupFontColor": "#5F615D", 11 | "popupBackgroundColor": "#FFFFFF", 12 | "logoSrc": null, 13 | "logoText": null, 14 | "pictureSrc": null 15 | }, 16 | "consent": { 17 | "requires": "none", 18 | "userMessage": "This site uses cookies and is a member of DigiTrust, a non-profit consortium of companies working together to improve your Web experience. By clicking on this page you agree to the use of cookies. This notice only appears once. You can read more or opt out of DigiTrust here.", 19 | "popupFontColor": "#ffffff", 20 | "popupBackgroundColor": "#000000" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/config/key.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "RSA-OAEP", 3 | "hash": { 4 | "name": "SHA-1" 5 | }, 6 | "version": 4, 7 | "spki": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgrdFWb07eQFRtdmXcnVRpSZFoibNFMZDEZHn71j6oa5Ohw7miu/Cpl77h2Pp/0bLt3dHr6RcinqA9cck2nPjJEw2svSzJOHY1409Cxr7cyAhfmueLazL/C8DOyFSe3e4QGNsJtPTlNy6Etmnb4dvctpm/nQ2nDaPw5wnb0hWI6Ik7wtvjbH9SaCRlXcyEKpF1oXy55jDJeovSxQz9eL+bgObD2Lz43gidU4B/zPhbNI+KmMkV539okyFfmcBwrCQARkh9d3eI8kAH+PptTalApVAefPSGZdWkSvkNw7HEbcnLMWWWXKeF7z2lMBd7RbnCyBUmgtHLY6d8HX6JPWB6QIDAQAB", 8 | "jwk": { 9 | "kty": "RSA", 10 | "kid": "fb8cd98a-d21b-4cd6-8b3c-182727effee4", 11 | "n": "grdFWb07eQFRtdmXcnVRpSZFoibNFMZDEZHn71j6oa5Ohw7miu_Cpl77h2Pp_0bLt3dHr6RcinqA9cck2nPjJEw2svSzJOHY1409Cxr7cyAhfmueLazL_C8DOyFSe3e4QGNsJtPTlNy6Etmnb4dvctpm_nQ2nDaPw5wnb0hWI6Ik7wtvjbH9SaCRlXcyEKpF1oXy55jDJeovSxQz9eL-bgObD2Lz43gidU4B_zPhbNI-KmMkV539okyFfmcBwrCQARkh9d3eI8kAH-PptTalApVAefPSGZdWkSvkNw7HEbcnLMWWWXKeF7z2lMBd7RbnCyBUmgtHLY6d8HX6JPWB6Q", 12 | "e": "AQAB", 13 | "alg": "RSA-OAEP", 14 | "ext": true, 15 | "key_ops": [ 16 | "encrypt" 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /src/digitrust_client.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Digitrust Client-side base module. 3 | * This is the root JS file for building the dependency tree and assigning to the global Window object. 4 | * Copyright 2015-2018 IAB Tech Lab. All rights reserved. 5 | * 6 | * @license 7 | * This code is licensed and distributed under the Apache 2.0 license. 8 | * Please see license.txt file for full text. 9 | * 10 | */ 11 | var DigiTrust = require('./modules/DigiTrust'); 12 | 13 | if (window !== undefined && window.DigiTrust == null) { 14 | window.DigiTrust = DigiTrust; 15 | } 16 | -------------------------------------------------------------------------------- /src/modules/ConfigLoader.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * ConfigLoader 5 | * @module 6 | * 7 | * @description Centralizes loading and access of configuration values to reduce duplication. 8 | * @author Chris Cole 9 | * 10 | * */ 11 | 12 | var buildEnv = require('../config/env.json').current; 13 | var genConfig = require('../config/GeneralConfig').getFullConfig(); 14 | var activeConfig = genConfig[buildEnv]; 15 | var helpers = require('./helpers'); 16 | var myConfig; 17 | var noop = function () { }; 18 | 19 | var loadDepth = 0; // beak over recursion 20 | 21 | var LOGID = 'DigiTrust_ConfigLoader'; 22 | var log = {}; // this will later be re-initialized if the init pass requires 23 | var logInitialized = false; 24 | // Unit tests fail to have some helper methods initialized 25 | var mockLog = { 26 | log: noop, 27 | warn: noop, 28 | info: noop, 29 | error: noop 30 | } 31 | 32 | function initLog() { 33 | if (logInitialized) { return; } 34 | 35 | if (typeof (helpers.createLogger) === 'function') { 36 | log = helpers.createLogger(LOGID); 37 | } 38 | else { 39 | // this is a false positive that happens in jest tests 40 | log = mockLog; 41 | } 42 | logInitialized = true; 43 | } 44 | 45 | 46 | /** 47 | * Loads an object of values into the config. 48 | * @param {any} settings 49 | */ 50 | function loadConfig(settings) { 51 | initLog(); 52 | loadDepth = 0; 53 | loadOver(settings, myConfig); 54 | return myConfig; 55 | } 56 | 57 | 58 | function loadOver(newVals, targetObject) { 59 | var otype = typeof (newVals); 60 | var k, v, vtype; 61 | var next; 62 | if (loadDepth++ > 7) { 63 | log.warn('DigiTrust load config over recurse page: ' + document.location); 64 | return targetObject; 65 | } 66 | if (otype != 'object' || newVals == null) { 67 | return targetObject; 68 | } 69 | 70 | for (k in newVals) { 71 | if (newVals.hasOwnProperty(k)) { 72 | v = newVals[k]; 73 | vtype = typeof (v); 74 | if (vtype == 'object') { 75 | if (targetObject[k] == null) { 76 | targetObject[k] = {}; 77 | } 78 | next = targetObject[k] 79 | targetObject[k] = loadOver(v, next); 80 | loadDepth--; 81 | } 82 | else { 83 | targetObject[k] = v; 84 | } 85 | } 86 | } 87 | 88 | return targetObject; 89 | } 90 | 91 | function reset() { 92 | myConfig = null; 93 | setBaseConfig(); 94 | } 95 | 96 | function setBaseConfig() { 97 | var conf = Object.assign({}, genConfig['prod']); 98 | myConfig = conf 99 | // merge in activeConfig 100 | if (buildEnv != 'prod') { 101 | loadConfig(activeConfig); 102 | } 103 | return myConfig; 104 | } 105 | 106 | /** 107 | * Gets a value from the config based upon a key. 108 | * Key can be of format keyA.keyB.keyX 109 | * @param {string} key 110 | */ 111 | function getVal(key) { 112 | return helpers.deepGet(myConfig, key); 113 | } 114 | 115 | setBaseConfig(); 116 | 117 | module.exports = { 118 | loadConfig: loadConfig, 119 | getValue: getVal, 120 | reset: reset, 121 | all: function () { return myConfig; } 122 | } -------------------------------------------------------------------------------- /src/modules/DebugControl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Digitrust.debugControl 3 | * @module 4 | * Namespace to contain debug control methods. This object is attached to DigiTrust.debugControl 5 | * */ 6 | 7 | 'use strict'; 8 | 9 | var Dcom = require('./DigiTrustCommunication'); 10 | 11 | /** 12 | * DebugControl class 13 | * This exposes methods used for debugging DigiTrust. 14 | * @class 15 | * @param {any} parent 16 | */ 17 | function Dbug(parent) { 18 | this.parent = parent || window.DigiTrust; 19 | var me = this; // closure hook 20 | 21 | } 22 | 23 | var logTagStyle = 'display: inline-block; color: #fff; background: [BG_COLOR]; padding: 1px 4px; border-radius: 3px;font-size:1.1rem;'; 24 | function getStyle() { 25 | var dt = this.parent || window.DigiTrust; 26 | var bgColor = dt.isClient ? '#395BA8' : '#ff9900'; 27 | var tagStyle = logTagStyle.replace('[BG_COLOR]', bgColor); 28 | return tagStyle; 29 | } 30 | 31 | /** 32 | * Returns true or false to indicate if DigiTrust is in a debug state 33 | * @memberof DigiTrust.debugControl 34 | */ 35 | Dbug.prototype.isDebug = function () { 36 | return this.parent.util.isDebugEnabled(); 37 | }; 38 | 39 | /** 40 | * Toggles debug state 41 | * @memberof DigiTrust.debugControl 42 | */ 43 | Dbug.prototype.setDebug = function (isSet) { 44 | var util = this.parent.util; 45 | var isClient = this.parent.isClient; 46 | if (typeof isSet !== 'boolean') { 47 | isSet = true; 48 | } 49 | var result = util.setDebug(isSet); 50 | if (isClient) { 51 | Dcom.setFrameDebug(true); 52 | } 53 | 54 | return result; 55 | }; 56 | 57 | /** 58 | * Outputs all log entries to Con sole.log 59 | * and also returns them as an array 60 | * @memberof DigiTrust.debugControl 61 | */ 62 | Dbug.prototype.dumpLogs = function (header) { 63 | var util = this.parent.util; 64 | var buffer = util.getGlobalLogger().getBuffer(); 65 | 66 | forceWrite(util.getGlobalLogger().name); 67 | var hasHeader = header != null; 68 | if (hasHeader) { 69 | var style = getStyle.call(this); 70 | forceWrite("%c" + header, style); 71 | forceGroup(true, header); 72 | } 73 | forceWrite(buffer); 74 | if (hasHeader) { 75 | forceGroup(false); 76 | } 77 | var isClient = this.parent.isClient; 78 | if (isClient) { 79 | Dcom.dumpFrameLogs(); 80 | } 81 | 82 | return buffer; 83 | }; 84 | 85 | Dbug.prototype.dumpConfig = function () { 86 | var conf = DigiTrust._config.initOptions; 87 | forceWrite(conf); 88 | return conf; 89 | } 90 | 91 | /* 92 | * @function 93 | * Circumvents the build checks against using console for debugging purposes. 94 | * Outputs to con sole.log 95 | */ 96 | function forceWrite() { 97 | // circumvent build checks in this one instance 98 | var key = 'con' + 'sole'; 99 | var con = window[key]; 100 | con.log.apply(con, arguments); 101 | return; 102 | } 103 | 104 | function forceGroup(isGroup, text) { 105 | // circumvent build checks in this one instance 106 | var key = 'con' + 'sole'; 107 | var con = window[key]; 108 | if (isGroup) { 109 | con.group(text); 110 | } 111 | else { 112 | con.groupEnd(); 113 | } 114 | } 115 | 116 | 117 | // Export statements 118 | module.exports = { 119 | /** 120 | * Factory method to initialize debug controller 121 | * 122 | * @param {any} parent 123 | */ 124 | createDebugControl: function (parent) { 125 | var p = parent || window.DigiTrust; 126 | return new Dbug(p); 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /src/modules/DigiTrust.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Digitrust 3 | * @module 4 | * Main entry point object for the entire DigiTrust suite 5 | * */ 6 | 7 | 'use strict'; 8 | 9 | var config = require('./ConfigLoader'); 10 | var configErrors = require('../config/errors.json'); 11 | var configInitializeOptions = require('../config/initializeOptions.json'); 12 | var helpers = require('./helpers'); 13 | var DigiTrustConsent = require('./DigiTrustConsent'); 14 | var DigiTrustCookie = require('./DigiTrustCookie'); 15 | var DigiTrustCommunication = require('./DigiTrustCommunication'); 16 | var DigiTrustCrypto = require('./DigiTrustCrypto'); 17 | var debugCtrl = require('./DebugControl'); 18 | 19 | var LOGID = 'Digitrust'; // const, but older browser support 20 | var logObj = require('./logger'); 21 | var log = logObj.createLogger(LOGID, {level: 'ERROR', enabled: false}); // this will later be re-initialized if the init pass requires 22 | var VERSION = require('../_version.js'); 23 | 24 | /** 25 | * Top level namespace object for DigiTrust 26 | * 27 | * @namespace DigiTrust 28 | * */ 29 | var DigiTrust = { 30 | version: VERSION, 31 | /** 32 | * Flag to indicate if library is running in host Publisher site (true) or in DigiTrust domain iFrame (false) 33 | */ 34 | isClient: false, 35 | _config: { 36 | loader: config, 37 | errors: configErrors, 38 | initOptions: configInitializeOptions, 39 | crypto: DigiTrustCrypto 40 | }, 41 | cookie: DigiTrustCookie, 42 | util: helpers 43 | }; 44 | 45 | 46 | 47 | var noop = function(){} 48 | 49 | DigiTrust.debugControl = debugCtrl.createDebugControl(DigiTrust); 50 | 51 | DigiTrust.initializeOptions = {}; 52 | 53 | /** 54 | * Tests to see if a member ID is valid 55 | * @param {any} memberId 56 | */ 57 | var isMemberIdValid = function (memberId) { 58 | if (memberId && memberId.length > 0) { 59 | return true; 60 | } else { 61 | throw configErrors.en.memberId; 62 | } 63 | }; 64 | 65 | /** 66 | * @function 67 | * Set options on the global DigiTrust object by merging base options 68 | * with consumer supplied options. 69 | * @param {object} -supplied initialization options 70 | * @return {object} The combined options object that was assigned to DigiTrust.initializeOptions 71 | */ 72 | DigiTrust._setDigiTrustOptions = function (options) { 73 | // we have added a polyfill to handle IE. In this manner the base objects aren't corrupted 74 | var opts = Object.assign({}, configInitializeOptions, options); 75 | window.DigiTrust.initializeOptions = opts; // TODO: hunt this down and redirect references to _config 76 | 77 | log.debug('options set', opts); 78 | return window.DigiTrust.initializeOptions; 79 | }; 80 | 81 | 82 | 83 | var configLoaded = false; // flag value to control merge of init options 84 | 85 | /** 86 | * Force the copy of config to update 87 | * */ 88 | DigiTrust._config.reload = function () { 89 | configLoaded = false; 90 | DigiTrust._config.loader.reset(); 91 | } 92 | 93 | /** 94 | * @function 95 | * Wrapper method that merges any initialized options into the general configuration. 96 | * @deprecated Move to new ConfigLoader object 97 | */ 98 | DigiTrust._config.getConfig = function() { 99 | var opts = window.DigiTrust.initializeOptions; 100 | var initEnv = opts && opts.environment || null; 101 | var i; 102 | 103 | if (configLoaded) { 104 | return DigiTrust._config.loader; 105 | } 106 | 107 | var configX = {}; 108 | // go for specific items from initialization environment 109 | var keys = ['urls', 'iframe', 'redirectInterval', 'redir'] 110 | 111 | // function to set the specific override values 112 | var setVals = function (target, source, key) { 113 | var k; 114 | try { 115 | if (source[key] == null) { return; } 116 | if (target[key] == null) { 117 | target[key] = {}; 118 | } 119 | for (k in source[key]) { 120 | if (source[key].hasOwnProperty(k)) { 121 | target[key][k] = source[key][k]; 122 | } 123 | } 124 | } 125 | catch (ex) { } 126 | } 127 | 128 | if (initEnv != null) { 129 | for (i = 0; i < keys.length; i++) { 130 | setVals(configX, initEnv, keys[i]); 131 | } 132 | DigiTrust._config.loader.loadConfig(configX); 133 | } 134 | 135 | configLoaded = true; 136 | 137 | return DigiTrust._config.loader; 138 | } 139 | 140 | 141 | /* 142 | * Internal initializer routine to setup the DigiTrust library. 143 | * 144 | * @memberof DigiTrust 145 | * @param {any} options 146 | * @param {any} initializeCallback 147 | */ 148 | var initInternal = function (options, initializeCallback) { 149 | log.debug('initialize of DigiTrust begins', options); // wont fire unless default config is reset 150 | try { 151 | if (initializeCallback === undefined) { 152 | log.debug('noop callback'); 153 | initializeCallback = noop; 154 | } 155 | var identityResponseObject = { success: false }; 156 | if (options && options.environment) { 157 | log.debug('loading custom environement settings', options.environment); 158 | config.loadConfig(options.environment); 159 | } 160 | options = DigiTrust._setDigiTrustOptions(options); 161 | log = helpers.createLogger(LOGID); // reinitialize with passed options 162 | log.debug('init options completed'); 163 | 164 | // allow for a circuit break to disable the world 165 | if (Math.random() > options.sample) { 166 | return initializeCallback(identityResponseObject); 167 | } 168 | 169 | // Verify Publisher's Member ID 170 | if (!isMemberIdValid(options.member)) { 171 | log.debug('init fail! Invalid DigiTrust member or no member value passed') 172 | return initializeCallback(identityResponseObject); 173 | } 174 | 175 | DigiTrustConsent.hasConsent(null, function (consent) { 176 | if (consent) { 177 | DigiTrustCookie.getUser(options, function (err, identityObject) { 178 | if (!err) { 179 | identityResponseObject.success = true; 180 | identityResponseObject.identity = identityObject; 181 | } 182 | return initializeCallback(identityResponseObject); 183 | }); 184 | } else { 185 | log.debug('user consent missing - fail'); 186 | return initializeCallback(identityResponseObject); 187 | } 188 | }); 189 | } catch (e) { 190 | log.error('Error in DigiTrust initializer', e); 191 | return initializeCallback({ success: false }); 192 | } 193 | } 194 | 195 | /** 196 | * Initialization entry point for boot up of DigiTrust 197 | * @memberof DigiTrust 198 | * @namespace DigiTrust.initialize 199 | * @param {object} options 200 | * @param {function} initializeCallback 201 | */ 202 | DigiTrust.initialize = function (options, initializeCallback) { 203 | log = helpers.createLogger(LOGID); // first initialize with default options 204 | helpers.setGlobalLogger(log); 205 | 206 | var document = window.document; 207 | var ready = document.readyState; 208 | DigiTrust.isClient = true; // init only called on clients 209 | 210 | if(!ready || ready == 'loading') { 211 | document.addEventListener("DOMContentLoaded", function(event) { 212 | DigiTrust.initialize(options, initializeCallback); 213 | }); 214 | } 215 | else{ 216 | initInternal(options, initializeCallback); 217 | } 218 | }; 219 | 220 | /** 221 | * Call to obtain the current user object. 222 | * @memberof DigiTrust 223 | * @namespace DigiTrust.getUser 224 | * @param {object} options 225 | * @param {function} callback Callback method that will receive the response. 226 | */ 227 | DigiTrust.getUser = function (options, callback) { 228 | 229 | options = DigiTrust._setDigiTrustOptions(options); 230 | var async = (typeof callback === 'function') ? true : false; 231 | var identityResponseObject = { 232 | success: false 233 | }; 234 | 235 | try { 236 | // Verify Publisher's Member ID 237 | if (!isMemberIdValid(options.member)) { 238 | return (async === false) ? identityResponseObject : callback(identityResponseObject); 239 | } 240 | 241 | if (async === false) { 242 | // Get publisher cookie 243 | var identityJSON = DigiTrustCookie.getUser(); 244 | if (!helpers.isEmpty(identityJSON)) { 245 | identityResponseObject.success = true; 246 | identityResponseObject.identity = identityJSON; 247 | } 248 | return identityResponseObject; 249 | } else { 250 | DigiTrustConsent.hasConsent(null, function (consent) { 251 | if (consent) { 252 | options.ignoreLocalCookies = true; 253 | DigiTrustCookie.getUser(options, function (err, identityObject) { 254 | if (err) { 255 | return callback(identityResponseObject); 256 | } else { 257 | identityResponseObject.success = true; 258 | identityResponseObject.identity = identityObject; 259 | return callback(identityResponseObject); 260 | } 261 | }); 262 | } else { 263 | return callback(identityResponseObject); 264 | } 265 | }); 266 | } 267 | } catch (e) { 268 | return (async === false) ? identityResponseObject : callback(identityResponseObject); 269 | } 270 | }; 271 | 272 | /** 273 | * Instructs the DigiTrust library to reset the user ID cookie locally and globally (digitru.st domain) 274 | * @memberof DigiTrust 275 | * @namespace DigiTrust.sendReset 276 | * @param {object} options 277 | * @param {function} initializeCallback 278 | */ 279 | DigiTrust.sendReset = function (options, callback) { 280 | DigiTrustCommunication.sendReset(); 281 | }; 282 | 283 | /** 284 | * Toggles the debug state of DigiTrust 285 | * @memberof DigiTrust 286 | * @namespace DigiTrust.setDebug 287 | * @param {boolean} isSet true or false to enable or disable debug state 288 | */ 289 | DigiTrust.setDebug = function (isSet) { 290 | var me = DigiTrust; 291 | me.debugControl.setDebug(isSet); 292 | }; 293 | 294 | 295 | module.exports = DigiTrust 296 | -------------------------------------------------------------------------------- /src/modules/DigiTrustCommunication.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var configErrors = require('../config/errors.json'); 4 | 5 | var LOGID = 'DigiTrustCommunication'; 6 | var logObj = require('./logger'); 7 | var log = logObj.createLogger(LOGID, {level: 'ERROR'}); // this will later be re-initialized if the init pass requires 8 | var logInitialized = false; 9 | var pubsub = require('./MinPubSub').createPubSub({ 10 | host: location.host 11 | }); 12 | 13 | var DC = {}; 14 | var noop = function () { }; 15 | 16 | var Dt = 'DigiTrust', 17 | kID = Dt + '.identity', 18 | kIframe = Dt + '.iframe'; 19 | 20 | // Pubsub sync keys 21 | var MKEY = { 22 | ready: kIframe + '.ready', 23 | ifrErr: kIframe + '.error', 24 | idSync: kID + '.response.sync', 25 | idResp: kID + '.response', 26 | idReset: kID + '.reset', 27 | idGet: kID + '.request', 28 | frameDebug: kIframe + '.setDebug', 29 | frameDumpLogs: kIframe + '.dumpLogs', 30 | debugMsg: kIframe + '.debugMsg' 31 | }; 32 | 33 | var getConfig = function () { 34 | return window.DigiTrust._config.getConfig(); 35 | } 36 | 37 | var getLogger = function () { 38 | return window.DigiTrust.util.getGlobalLogger(); 39 | } 40 | 41 | /** 42 | * Pull in options information from global Digitrust object 43 | */ 44 | function initOptions(){ 45 | initLog(); 46 | } 47 | 48 | function isFunc(fn) { 49 | return typeof (fn) === 'function'; 50 | } 51 | 52 | // TODO: REMOVE THIS 53 | function initLog(){ 54 | if(logInitialized){ return; } 55 | var opts = window.DigiTrust.initializeOptions; 56 | if(opts.logging != null){ 57 | if(opts.logging.enable == false){ 58 | // disable logging 59 | log = logObj.createLogger(LOGID, {level: 'ERROR'}); 60 | log.enabled = false; 61 | } 62 | else{ 63 | if(opts.logging.level == null){ 64 | opts.logging.level = "INFO"; 65 | } 66 | log = logObj.createLogger(LOGID, opts.logging); 67 | } 68 | } 69 | logInitialized = true; 70 | } 71 | 72 | 73 | DC.iframe = null; 74 | DC.iframeStatus = 0; // 0: no iframe; 1: connecting; 2: ready 75 | 76 | /** 77 | * Post Message handler 78 | * @function 79 | * 80 | * @param {any} evt 81 | */ 82 | function _messageHandler(evt) { 83 | var log = getLogger(); 84 | var iframeOrigin = getConfig().getValue('iframe.postMessageOrigin'); 85 | var msgKey = evt.data.type; 86 | 87 | log.debug('pubsub event received: ' + evt.msgKey, evt); 88 | if (evt.origin !== iframeOrigin) { 89 | log.info('pubsub event origin does not match iframeOrigin from config: ' + evt.origin + ' : ' + iframeOrigin); 90 | switch (msgKey) { 91 | case 'Digitrust.shareIdToIframe.request': 92 | if (DigiTrust) { 93 | DigiTrust.getUser({ member: window.DigiTrust.initializeOptions.member }, function (resp) { 94 | resp.type = "Digitrust.shareIdToIframe.response"; 95 | evt.source.postMessage(resp, evt.origin); 96 | }); 97 | } else { 98 | log.warn("DigiTrust not found"); 99 | } 100 | break; 101 | default: 102 | log.warn('message origin error. allowed: ' + iframeOrigin + ' \nwas from: ' + evt.origin); 103 | } 104 | } 105 | else { 106 | switch (msgKey) { 107 | case MKEY.ready: 108 | pubsub.publish(msgKey, [true]); 109 | break; 110 | default: 111 | pubsub.publish(msgKey, [evt.data.value]); 112 | break; 113 | } 114 | } 115 | }; 116 | 117 | DC.startConnection = function (loadSuccess) { 118 | initOptions(); // initialization point 119 | var iframeConf = getConfig().getValue('iframe'); 120 | 121 | /* 122 | If there is a connection problem, or if adblocker blocks the request, 123 | start a 10 second timeout to notify the caller. Clear the timeout upon 124 | successful connection to the iframe 125 | 126 | Note: onload is executed even on non 2XX HTTP STATUSES (e.g. 404, 500) 127 | for cross-domain iframe requests 128 | */ 129 | var iframeLoadErrorTimeout = setTimeout(function () { 130 | var log = getLogger(); 131 | log.warn('pubsub MESSAGE TIMEOUT ERROR'); 132 | loadSuccess(false); 133 | DC.iframeStatus = 0; 134 | }, iframeConf.timeoutDuration); 135 | 136 | pubsub.subscribe(MKEY.ready, function (iframeReady) { 137 | clearTimeout(iframeLoadErrorTimeout); 138 | iframeLoadErrorTimeout = 0; 139 | DC.iframeStatus = 2; 140 | loadSuccess(true); 141 | }); 142 | 143 | // Add postMessage listeners 144 | window.addEventListener('message', _messageHandler, false); 145 | 146 | DC.iframe = document.createElement('iframe'); 147 | DC.iframe.style.display = 'none'; 148 | DC.iframe.src = getConfig().getValue('urls.digitrustIframe'); 149 | DC.iframe.name = '__dtLocator'; // locatorFrameName 150 | DC.iframeStatus = 1; 151 | document.body.appendChild(DC.iframe); 152 | 153 | log.debug('communication frame added'); 154 | }; 155 | 156 | /** 157 | * Publishes a request to the communication pipe. 158 | * @param {any} sendRequestFunction 159 | * @param {any} options 160 | */ 161 | DC.sendRequest = function (sendRequestFunction, options) { 162 | if (DC.iframeStatus === 2) { 163 | sendRequestFunction(options); 164 | } else if (DC.iframeStatus === 1) { 165 | // This mimics a "delay", until the iframe is ready 166 | pubsub.subscribe(MKEY.ready, function (iframeReady) { 167 | sendRequestFunction(options); 168 | }); 169 | } else if (DC.iframeStatus === 0) { 170 | // Create communication gateway with digitru.st iframe 171 | DC.startConnection(function (loadSuccess) { 172 | if (loadSuccess) { 173 | sendRequestFunction(options); 174 | } else { 175 | throw new Error(configErrors.en.iframeError); 176 | } 177 | }); 178 | } 179 | }; 180 | 181 | /** 182 | * Request the identity cookie from the DigiTrust iframe domain. 183 | * @param {any} options 184 | */ 185 | DC.getIdentity = function (options) { 186 | var log = getLogger(); 187 | log.debug('pubsub request identity'); 188 | 189 | options = options ? options : {}; 190 | var _sendIdentityRequest = function (options) { 191 | var identityRequest = { 192 | version: 1, 193 | type: MKEY.idGet, 194 | syncOnly: options.syncOnly ? options.syncOnly : false, 195 | redirects: options.redirects ? options.redirects : false, 196 | value: {} 197 | }; 198 | DC.iframe.contentWindow.postMessage(identityRequest, DC.iframe.src); 199 | }; 200 | 201 | DC.sendRequest(_sendIdentityRequest, options); 202 | }; 203 | 204 | DC.sendReset = function (options) { 205 | var DigiTrustCookie = require('./DigiTrustCookie'); 206 | DigiTrustCookie.setResetCookie(); 207 | var _request = function (options) { 208 | var requestPayload = { 209 | version: 1, 210 | type: MKEY.idReset 211 | }; 212 | DC.iframe.contentWindow.postMessage(requestPayload, DC.iframe.src); 213 | }; 214 | 215 | DC.sendRequest(_request, options); 216 | }; 217 | 218 | /** 219 | * Enable or disable debug mode in the iframe 220 | * 221 | * @param {any} options 222 | */ 223 | DC.setFrameDebug = function (options) { 224 | var log = getLogger(); 225 | var isClient = window.DigiTrust.isClient; 226 | if (!isClient) { 227 | log.warn('invalid call to DigiTrustCommunication.setFrameDebug. Only valid from client'); 228 | return; 229 | } 230 | 231 | var type = typeof options; 232 | if (type == 'boolean') { 233 | options = { debug: options }; 234 | } 235 | else { 236 | options = options || { debug: true }; 237 | } 238 | var cb = options.callback || noop; 239 | var reqFunc = function (opts) { 240 | var reqData = { 241 | value: options.debug || true, 242 | type: MKEY.frameDebug 243 | } 244 | 245 | DC.iframe.contentWindow.postMessage(reqData, DC.iframe.src); 246 | } 247 | 248 | DC.sendRequest(reqFunc, options); 249 | } 250 | 251 | /** 252 | * Enable or disable debug mode in the iframe 253 | * 254 | * @param {any} options 255 | */ 256 | DC.dumpFrameLogs = function (options) { 257 | var log = getLogger(); 258 | var isClient = window.DigiTrust.isClient; 259 | if (!isClient) { 260 | log.warn('invalid call to DigiTrustCommunication.dumpFrameLogs. Only valid from client'); 261 | return; 262 | } 263 | 264 | options = options || {}; 265 | 266 | var cb = options.callback || noop; 267 | var reqFunc = function (opts) { 268 | var reqData = { 269 | value: {}, 270 | type: MKEY.frameDumpLogs 271 | } 272 | 273 | DC.iframe.contentWindow.postMessage(reqData, DC.iframe.src); 274 | } 275 | 276 | DC.sendRequest(reqFunc, options); 277 | } 278 | 279 | 280 | /** 281 | * Subscribe to given message topic in the global pubsub object. 282 | * @param {any} message topic in pubsub 283 | * @param {any} handler 284 | */ 285 | function listen(message, handler) { 286 | if (!isFunc(handler)) { 287 | return; 288 | } 289 | pubsub.subscribe(message, handler); 290 | } 291 | 292 | // var DigiTrustCommunication = DC; 293 | 294 | module.exports = { 295 | getIdentity: DC.getIdentity, 296 | startConnection: DC.startConnection, 297 | sendReset: DC.sendReset, 298 | setFrameDebug: DC.setFrameDebug, 299 | dumpFrameLogs: DC.dumpFrameLogs, 300 | MsgKey: MKEY, 301 | listen: listen 302 | }; 303 | -------------------------------------------------------------------------------- /src/modules/DigiTrustConsent.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var env = require('../config/env.json').current; 4 | var gdprInfo = require('../config/gdpr-lang.json'); 5 | 6 | var DigiTrustConsent = {}; 7 | 8 | var getConfig = function () { 9 | return DigiTrust._config.getConfig(); 10 | } 11 | 12 | var getLogger = function () { 13 | return window.DigiTrust.util.getGlobalLogger(); 14 | } 15 | 16 | DigiTrustConsent.browserLanguageIsEU = function (languages) { 17 | for (var i = 0; i < languages.length; i++) { 18 | if (gdprInfo.gdprLanguages.indexOf(languages[i].toLowerCase()) >= 0) { 19 | return true; 20 | } 21 | } 22 | return false; 23 | }; 24 | 25 | DigiTrustConsent.cmpConsent = function (languages) { 26 | return false; 27 | }; 28 | 29 | DigiTrustConsent.gdprApplies = function (options) { 30 | var browserLanguageCheckResult = DigiTrustConsent.browserLanguageIsEU(navigator.languages || 31 | [navigator.browserLanguage]); 32 | return browserLanguageCheckResult; 33 | }; 34 | 35 | DigiTrustConsent.hasConsent = function (options, callback) { 36 | var log = getLogger(); 37 | 38 | var applies = DigiTrustConsent.gdprApplies(); 39 | var vendorId = getConfig().getValue('gvlVendorId'); 40 | if (env === 'local' || env === 'localdev') { applies = false; } // dev test 41 | 42 | if (typeof (window.__cmp) !== 'undefined') { 43 | window.__cmp('ping', null, function (pingReturn) { 44 | if (applies || (pingReturn.gdprAppliesGlobally)) { 45 | log.debug('GDPR consent rules apply from language or global GDPR settings.') 46 | window.__cmp('getVendorConsents', [vendorId], function (result) { 47 | var myconsent = result.vendorConsents[vendorId]; 48 | log.debug('GDPR user consent value: ' + myconsent); 49 | callback(myconsent); 50 | }); 51 | } else { 52 | callback(true); 53 | } 54 | }); 55 | } else if (applies) { 56 | log.debug('GDPR consent rules apply.') 57 | callback(false); 58 | } else { 59 | callback(true); 60 | } 61 | }; 62 | 63 | module.exports = { 64 | hasConsent: DigiTrustConsent.hasConsent 65 | }; 66 | -------------------------------------------------------------------------------- /src/modules/DigiTrustCookie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = require('./ConfigLoader'); 4 | var Dcom = require('./DigiTrustCommunication'); 5 | var helpers = require('./helpers'); 6 | 7 | function getConfig() { 8 | if (window && window.DigiTrust && window.DigiTrust._config) { 9 | return window.DigiTrust._config.getConfig(); 10 | } 11 | // if not on global return new instance 12 | return config; 13 | } 14 | 15 | var getLogger = function () { 16 | return window.DigiTrust.util.getGlobalLogger(); 17 | } 18 | 19 | 20 | var _maxAgeToDate = function (milliseconds) { 21 | var date = new Date(); 22 | date.setTime(date.getTime() + milliseconds); 23 | return date.toUTCString(); 24 | }; 25 | 26 | var _setCookie = function (cookieKV, expiresKV, domainKV, pathKV) { 27 | var str = cookieKV + expiresKV + domainKV + pathKV; 28 | if (str.substr(str.length - 1) != ';') { 29 | str += ';' 30 | } 31 | str += "SameSite=None; Secure;"; 32 | document.cookie = str; 33 | }; 34 | 35 | var _setIdentityCookie = function (cookieV) { 36 | 37 | var cookieConfig = window.DigiTrust.isClient ? getConfig().getValue('cookie.publisher') : getConfig().getValue('cookie.digitrust'); 38 | 39 | var cookieKV = cookieConfig.userObjectKey + '=' + cookieV + ';'; 40 | var expiresKV = 'expires=' + _maxAgeToDate(cookieConfig.maxAgeMiliseconds) + ';'; 41 | var domainKV = cookieConfig.domainKeyValue; 42 | var pathKV = cookieConfig.pathKeyValue; 43 | 44 | _setCookie(cookieKV, expiresKV, domainKV, pathKV); 45 | }; 46 | 47 | var _verifyUserCookieStructure = function (userJSON) { 48 | if (!userJSON) { return false; } 49 | 50 | var hasUserId = userJSON.hasOwnProperty('id'); 51 | var hasPrivacy = userJSON.hasOwnProperty('privacy'); 52 | 53 | if (!hasUserId || !hasPrivacy || ((!userJSON.privacy.optout) && (userJSON.id.length < 1))) { 54 | return false; 55 | } 56 | 57 | if (hasPrivacy) { 58 | var hasOptout = userJSON.privacy.hasOwnProperty('optout'); 59 | if (!hasOptout) { 60 | return false; 61 | } 62 | } else { 63 | return false; 64 | } 65 | 66 | return true; 67 | }; 68 | 69 | var DigiTrustCookie = {}; 70 | DigiTrustCookie.getIdentityCookieJSON = function (cookieKey) { 71 | var log = getLogger(); 72 | var cookieKey = cookieKey || getConfig().getValue('cookie.digitrust.userObjectKey'); 73 | var localUserCookie = DigiTrustCookie.getCookieByName(cookieKey); 74 | 75 | if (localUserCookie) { 76 | log.debug('local user identity cookie found on domain ' + location.host); 77 | var localUserCookieJSON = {}; 78 | try { 79 | localUserCookieJSON = DigiTrustCookie.unobfuscateCookieValue(localUserCookie); 80 | } catch (e) { 81 | log.warn('error parsing user cookie - generating new identity') 82 | localUserCookieJSON = { 83 | id: helpers.generateUserId(), 84 | version: getConfig().getValue('cookie.version'), 85 | producer: getConfig().getValue('cookie.producer'), 86 | privacy: { 87 | optout: false 88 | } 89 | }; 90 | _setIdentityCookie(DigiTrustCookie.obfuscateCookieValue(localUserCookieJSON)); 91 | } 92 | if (_verifyUserCookieStructure(localUserCookieJSON)) { 93 | return localUserCookieJSON; 94 | } else { 95 | log.info('failure in verifying cookie structure ' + JSON.stringify(localUserCookieJSON)); 96 | return {}; 97 | } 98 | } else { 99 | log.debug('no local user identity'); 100 | return {}; 101 | } 102 | }; 103 | 104 | DigiTrustCookie.setResetCookie = function () { 105 | var cookieConf = getConfig().getValue('cookie'); 106 | var cookieKV = cookieConf.digitrust.resetKey + '=true;'; 107 | var expiresKV = 'expires=' + _maxAgeToDate(cookieConf.digitrust.maxAgeMiliseconds) + ';'; 108 | var domainKV = cookieConf.digitrust.domainKeyValue; 109 | var pathKV = cookieConf.digitrust.pathKeyValue; 110 | 111 | _setCookie(cookieKV, expiresKV, domainKV, pathKV); 112 | }; 113 | 114 | /** 115 | * Expires a cookie such that any subsequent page loads the cookie will not be present. 116 | * The original cookie exists until the page is reloaded. 117 | * @param {any} cookieKey 118 | */ 119 | DigiTrustCookie.expireCookie = function (cookieKey) { 120 | var cookieConf = getConfig().getValue('cookie'); 121 | 122 | var cookieKV = cookieKey + '=; ', 123 | expiresKV = 'expires=expires=Thu, 01 Jan 1970 00:00:01 GMT;', 124 | domainKV = '', 125 | pathKV = cookieConf.digitrust.pathKeyValue; 126 | 127 | try { 128 | if (location.host.indexOf(cookieConf.digitrust.domainKeyValue) > -1) { 129 | domainKV = cookieConf.digitrust.domainKeyValue; 130 | } 131 | } 132 | catch (ex) { } 133 | 134 | _setCookie(cookieKV, expiresKV, domainKV, pathKV); 135 | }; 136 | 137 | DigiTrustCookie.setDigitrustCookie = function (cookieV) { 138 | var log = getLogger(); 139 | var cookieConf = getConfig().getValue('cookie'); 140 | var cookieKV = cookieConf.digitrust.userObjectKey + '=' + cookieV + ';'; 141 | var expiresKV = 'expires=' + _maxAgeToDate(cookieConf.digitrust.maxAgeMiliseconds) + ';'; 142 | var domainKV = cookieConf.digitrust.domainKeyValue; 143 | var pathKV = cookieConf.digitrust.pathKeyValue; 144 | 145 | log.debug('setting identity cookie'); 146 | _setCookie(cookieKV, expiresKV, domainKV, pathKV); 147 | }; 148 | 149 | DigiTrustCookie.getUser = function (options, callback) { 150 | var log = getLogger(); 151 | 152 | var cookieConf = getConfig().getValue('cookie'); 153 | 154 | options = options || {}; 155 | var useCallback = (typeof callback === 'function') ? true : false; 156 | var localUserCookieJSON = {}; 157 | var _createSyncOnlySubscription = function () { 158 | // LISTENER: Only update publisher cookie, do not return anywhere 159 | Dcom.listen(Dcom.MsgKey.idSync, function (userJSON) { // 'DigiTrust.pubsub.identity.response.syncOnly' 160 | if (DigiTrustCookie.verifyPublisherDomainCookie(userJSON)) { 161 | var cookieStringEncoded = DigiTrustCookie.obfuscateCookieValue(userJSON); 162 | _setIdentityCookie(cookieStringEncoded); 163 | } 164 | }); 165 | }; 166 | 167 | if (useCallback === false) { 168 | localUserCookieJSON = DigiTrustCookie.getIdentityCookieJSON(cookieConf.publisher.userObjectKey); 169 | // Do a sync with digitrust official domain 170 | _createSyncOnlySubscription(); 171 | Dcom.getIdentity({ syncOnly: true }); 172 | return (!helpers.isEmpty(localUserCookieJSON)) ? localUserCookieJSON : {}; 173 | } else { 174 | /* 175 | postMessage doesn't have a callback, so we listen for an event emitted by the 176 | DigiTrustCommunication module telling us that a message arrived from http://digitru.st 177 | and now we can complete the callback 178 | 179 | LISTENER: listen for message from digitrust iframe 180 | */ 181 | Dcom.listen(Dcom.MsgKey.idResp, function (userJSON) { // 'DigiTrust.pubsub.identity.response' 182 | if (DigiTrustCookie.verifyPublisherDomainCookie(userJSON)) { 183 | var cookieStringEncoded = DigiTrustCookie.obfuscateCookieValue(userJSON); 184 | _setIdentityCookie(cookieStringEncoded); 185 | return callback(false, userJSON); 186 | } else { 187 | // No DigiTrust cookie exists on digitru.st domain 188 | if (helpers.isEmpty(userJSON) && (!userJSON.hasOwnProperty('error'))) { 189 | if (options.redirects) { 190 | helpers.createConsentClickListener(); 191 | } 192 | } 193 | return callback(true); 194 | } 195 | }); 196 | 197 | if (options.ignoreLocalCookies === true) { 198 | Dcom.getIdentity(); 199 | } else { 200 | localUserCookieJSON = DigiTrustCookie.getIdentityCookieJSON( 201 | cookieConf.publisher.userObjectKey 202 | ); 203 | if (DigiTrustCookie.verifyPublisherDomainCookie(localUserCookieJSON)) { 204 | // OK to proceed & show content 205 | // Grab remote cookie & update local 206 | _createSyncOnlySubscription(); 207 | Dcom.getIdentity({ syncOnly: true }); 208 | return callback(false, localUserCookieJSON); 209 | } else { 210 | // Connect to iframe to check remote cookies 211 | Dcom.getIdentity({ syncOnly: false, redirects: options.redirects }); 212 | } 213 | } 214 | } 215 | }; 216 | 217 | DigiTrustCookie.obfuscateCookieValue = function (value) { 218 | return encodeURIComponent(btoa(JSON.stringify(value))); 219 | }; 220 | DigiTrustCookie.unobfuscateCookieValue = function (value) { 221 | return JSON.parse(atob(decodeURIComponent(value))); 222 | }; 223 | 224 | DigiTrustCookie.getCookieByName = function (name) { 225 | var value = '; ' + document.cookie; 226 | var parts = value.split('; ' + name + '='); 227 | if (parts.length >= 2) { // sometimes multiple values found 228 | return parts.pop().split(';').shift(); 229 | } 230 | }; 231 | 232 | DigiTrustCookie.createUserCookiesOnDigitrustDomain = function () { 233 | var cookieConf = getConfig().getValue('cookie'); 234 | 235 | var userId = helpers.generateUserId(); 236 | var userJSON = { 237 | id: userId, 238 | version: cookieConf.version, 239 | producer: cookieConf.producer, 240 | privacy: { 241 | optout: false 242 | } 243 | }; 244 | var cookieStringEncoded = DigiTrustCookie.obfuscateCookieValue(userJSON); 245 | 246 | DigiTrustCookie.setDigitrustCookie(cookieStringEncoded); 247 | return userJSON; 248 | }; 249 | 250 | DigiTrustCookie.verifyPublisherDomainCookie = function (userJSON) { 251 | if (helpers.isEmpty(userJSON) || !_verifyUserCookieStructure(userJSON)) { return false; } 252 | if (!userJSON.hasOwnProperty('keyv')) { return false; } 253 | 254 | return true; 255 | }; 256 | 257 | module.exports = DigiTrustCookie; 258 | -------------------------------------------------------------------------------- /src/modules/DigiTrustCrypto.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //var env = require('../config/env.json').current; 4 | //var configGeneral = require('../config/general')[env]; 5 | var config = require('./ConfigLoader'); 6 | var helpers = require('./helpers'); 7 | var ServerCrypto = require('./ServerCrypto'); 8 | var DTPublicKeyObject = require('../config/key.json'); 9 | 10 | var LOGID = 'DigiTrustCrypto'; 11 | var log = {}; // this will later be re-initialized if the init pass requires 12 | var logInitialized = false; 13 | 14 | var crypto_browser = helpers.getBrowserCrypto(); 15 | 16 | function initLog(){ 17 | if(logInitialized){ return; } 18 | log = helpers.createLogger(LOGID); 19 | logInitialized = true; 20 | } 21 | 22 | /** 23 | * @function 24 | * Tests to see if we are dealing with the legacy msCrypto object from IE 11. 25 | */ 26 | function isMsCrypto(cryptoObj){ 27 | var msg; 28 | if(!cryptoObj || !cryptoObj.subtle){ 29 | cryptoObj = window.crypto; 30 | } 31 | if(!cryptoObj || !cryptoObj.subtle){ 32 | msg = 'Invalid browser crypt object'; 33 | log.debug(msg); 34 | //throw msg; 35 | return false; 36 | } 37 | 38 | if(!window.msCrypto){ 39 | return false; 40 | } 41 | 42 | try{ 43 | var genOp = cryptoObj.subtle.generateKey( 44 | { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]) }, 45 | false, 46 | ["encrypt", "decrypt"]); 47 | 48 | if(typeof(genOp.oncomplete) !== 'undefined'){ 49 | return true; 50 | } 51 | return false; 52 | } 53 | catch(ex){ 54 | return false; 55 | } 56 | } 57 | 58 | var DigiTrustCrypto = {}; 59 | 60 | DigiTrustCrypto.getKeyVersion = function () { 61 | return DTPublicKeyObject.version; 62 | }; 63 | 64 | // Returns base64 string 65 | DigiTrustCrypto.encrypt = function (valueToEncrypt, callback) { 66 | var keyType; 67 | var publicKey; 68 | initLog(); 69 | 70 | if(crypto_browser == null){ 71 | crypto_browser = helpers.getBrowserCrypto(); 72 | } 73 | 74 | if (helpers.isSafari()) { 75 | keyType = 'jwk'; 76 | publicKey = DTPublicKeyObject.jwk; 77 | } else { 78 | keyType = 'spki'; 79 | publicKey = helpers.base64StringToArrayBuffer(DTPublicKeyObject.spki); 80 | } 81 | if (window.crypto && !window.crypto.subtle && helpers.isChrome() && 82 | (Math.random() < config.getValue('crypto.serverCryptoRate') )) { 83 | // chrome 61 removes crypto.subtle on insecure origins 84 | crypto_browser.subtle = ServerCrypto.mockCryptoSubtle(); 85 | } 86 | 87 | log.debug('encrypt value: ', valueToEncrypt); 88 | 89 | if(isMsCrypto(crypto_browser)){ 90 | msieEncrypt(valueToEncrypt, keyType, publicKey, callback); 91 | return; 92 | } 93 | 94 | 95 | crypto_browser.subtle.importKey( 96 | keyType, 97 | publicKey, 98 | { 99 | name: DTPublicKeyObject.type, 100 | hash: { 101 | name: DTPublicKeyObject.hash.name 102 | } 103 | }, 104 | false, 105 | ['encrypt'] 106 | ) 107 | .then(function (cryptokey) { 108 | crypto_browser.subtle.encrypt( 109 | { 110 | name: DTPublicKeyObject.type, 111 | hash: { 112 | name: DTPublicKeyObject.hash.name 113 | } 114 | }, 115 | cryptokey, 116 | // string (User ID) to array buffer 117 | helpers.str2ab(valueToEncrypt) 118 | ) 119 | .then(function (encryptedValue) { 120 | // Returns an ArrayBuffer containing the encrypted data 121 | // ServerCrypto returns a string value; in-browser crypto returns ArrayBuffer 122 | var encryptedValueEncodedB64 = (typeof(encryptedValue) === 'string') ? 123 | encryptedValue : 124 | helpers.arrayBufferToBase64String(encryptedValue); 125 | return callback(encryptedValueEncodedB64); 126 | }) 127 | .catch(function (err) { 128 | log.error('Failure encrypting value.', err); 129 | }); 130 | }); 131 | }; 132 | 133 | DigiTrustCrypto.decrypt = function (valueToDecrypt, callback) { 134 | var keyType = 'jwk'; 135 | var privateKey = DTPublicKeyObject.jwkPrivate; 136 | var publicKey; 137 | initLog(); 138 | 139 | log.debug('attempt to decrypt value: ', valueToDecrypt); 140 | 141 | if(crypto_browser == null){ 142 | crypto_browser = helpers.getBrowserCrypto(); 143 | } 144 | 145 | if (helpers.isSafari()) { 146 | keyType = 'jwk'; 147 | publicKey = DTPublicKeyObject.jwk; 148 | } else { 149 | keyType = 'spki'; 150 | publicKey = helpers.base64StringToArrayBuffer(DTPublicKeyObject.spki); 151 | } 152 | 153 | if(isMsCrypto(crypto_browser)){ 154 | msieDecrypt(valueToDecrypt, keyType, publicKey, callback); 155 | return; 156 | } 157 | 158 | log.debug('ready to create key'); 159 | var cryptKey = crypto_browser.subtle.importKey( 160 | keyType, 161 | privateKey, 162 | { 163 | name: DTPublicKeyObject.type, 164 | hash: { 165 | name: DTPublicKeyObject.hash.name 166 | } 167 | }, 168 | false, 169 | ['decrypt'] 170 | ); 171 | 172 | cryptKey.then(function (cryptokey) { 173 | log.debug('enter decrypt with key', cryptokey); 174 | 175 | crypto_browser.subtle.decrypt( 176 | { 177 | name: DTPublicKeyObject.type, 178 | hash: { 179 | name: DTPublicKeyObject.hash.name 180 | } 181 | }, 182 | cryptokey, 183 | // Encrypted User ID (b64) into array buffer 184 | helpers.base64StringToArrayBuffer(valueToDecrypt) 185 | ) 186 | .then(function (decryptedValueArrayBuffer) { 187 | var decryptedValueString = helpers.ab2str(decryptedValueArrayBuffer); 188 | log.debug('just decrypted', keyType, decryptedValueString); 189 | return callback(decryptedValueString); 190 | }); 191 | }); 192 | }; 193 | 194 | /** 195 | * Decrypt using the proprietary 196 | */ 197 | var msieDecrypt = function (valueToDecrypt, keyType, privateKey, callback) { 198 | 199 | var keyOp = crypto_browser.subtle.importKey( 200 | keyType, 201 | privateKey, 202 | { 203 | name: DTPublicKeyObject.type, 204 | hash: { 205 | name: DTPublicKeyObject.hash.name 206 | } 207 | }, 208 | false, 209 | ['decrypt'] 210 | ); 211 | 212 | keyOp.oncomplete = function(evt){ 213 | var cryptokey = evt.target.result; 214 | var decryptOp = crypto_browser.subtle.decrypt( 215 | { 216 | name: DTPublicKeyObject.type, 217 | hash: { 218 | name: DTPublicKeyObject.hash.name 219 | } 220 | }, 221 | cryptokey, 222 | // Encrypted User ID (b64) into array buffer 223 | helpers.base64StringToArrayBuffer(valueToDecrypt) 224 | ) 225 | decryptOp.onerror = function(e){ 226 | log.error(e); 227 | } 228 | 229 | decryptOp.oncomplete = function(e){ 230 | var decryptedValueArrayBuffer = e.target.result; 231 | 232 | var decryptedValueString = helpers.ab2str(decryptedValueArrayBuffer); 233 | log.debug('just decrypted', keyType, decryptedValueString); 234 | return callback(decryptedValueString); 235 | 236 | } 237 | } 238 | } 239 | 240 | /** 241 | * @function 242 | * Encryption path for MSIE 11 browsers that don't support current Crypto object standard. 243 | */ 244 | var msieEncrypt = function (valueToEncrypt, keyType, publicKey, callback) { 245 | 246 | var keyOp = crypto_browser.subtle.importKey( 247 | keyType, 248 | publicKey, 249 | { 250 | name: DTPublicKeyObject.type, 251 | hash: { 252 | name: DTPublicKeyObject.hash.name 253 | } 254 | }, 255 | false, 256 | ['encrypt'] 257 | ); 258 | 259 | keyOp.oncomplete = function(evt){ 260 | var cryptokey = evt.target.result; 261 | 262 | try{ 263 | var encryptOp = crypto_browser.subtle.encrypt( 264 | { 265 | name: DTPublicKeyObject.type, 266 | hash: { 267 | name: DTPublicKeyObject.hash.name 268 | } 269 | }, 270 | cryptokey, 271 | // string (User ID) to array buffer 272 | helpers.str2ab(valueToEncrypt) 273 | ); 274 | 275 | encryptOp.oncomplete = function(e){ 276 | var encryptedValue = e.target.result; 277 | var encryptedValueEncodedB64 = (typeof(encryptedValue) === 'string') ? 278 | encryptedValue : 279 | helpers.arrayBufferToBase64String(encryptedValue); 280 | log.debug('just encrypted', keyType, encryptedValueEncodedB64); 281 | return callback(encryptedValueEncodedB64); 282 | }; 283 | } 284 | catch(err){ 285 | log.error('Digitrust server MSIE Encrypt error', err); 286 | } 287 | } 288 | } 289 | 290 | 291 | 292 | module.exports = DigiTrustCrypto; 293 | -------------------------------------------------------------------------------- /src/modules/MinPubSub.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @class MinPubSub 5 | * 6 | * @classdesc A simple publish/subscribe class for passing postMessage messages between frames. 7 | * 8 | * Adapted from https://github.com/daniellmb/MinPubSub 9 | * */ 10 | 11 | 12 | function MinPubSub(options) { 13 | var cache = window.c_ || {}; // check for 'c_' cache for unit testing 14 | var me = this; 15 | 16 | this.publish = function (topic, args) { 17 | var subs = cache[topic]; 18 | var len = subs ? subs.length : 0; 19 | 20 | while (len--) { 21 | subs[len].apply(window, args || []); 22 | } 23 | }; 24 | 25 | this.subscribe = function (topic, callback) { 26 | if (!cache[topic]) { 27 | cache[topic] = []; 28 | } 29 | cache[topic].push(callback); 30 | return [topic, callback]; 31 | }; 32 | 33 | this.unsubscribe = function (handle, callback) { 34 | 35 | var subs = cache[callback ? handle : handle[0]]; 36 | callback = callback || handle[1]; 37 | var len = subs ? subs.length : 0; 38 | 39 | while (len--) { 40 | if (subs[len] === callback) { 41 | subs.splice(len, 1); 42 | } 43 | } 44 | }; 45 | } 46 | 47 | 48 | module.exports = { 49 | createPubSub: function (opts) { 50 | return new MinPubSub(opts); 51 | } 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/modules/ServerCrypto.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = require('./ConfigLoader'); 4 | var helpers = require('./helpers'); 5 | 6 | var ServerCrypto = {}; 7 | 8 | function getConfig() { 9 | if (window && window.DigiTrust && window.DigiTrust._config) { 10 | return window.DigiTrust._config.getConfig(); 11 | } 12 | // if not on global return new instance 13 | return config; 14 | } 15 | 16 | 17 | ServerCrypto.mockCryptoSubtle = function () { 18 | return { 19 | importKey: function (keyType, publicKey, conf, ignored, operations) { 20 | return new Promise(function (resolve, reject) { 21 | resolve(); 22 | }); 23 | }, 24 | encrypt: function (options, cryptokey, raw) { 25 | return new Promise(function (resolve, reject) { 26 | helpers.xhr.promise('GET', getConfig().getValue('urls.digitrustIdService')) 27 | .then(function (contents) { 28 | var encryptedIdentity = JSON.parse(contents); 29 | resolve(encryptedIdentity.id); 30 | }) 31 | .catch(function (err) { 32 | reject(err); 33 | }); 34 | }); 35 | } 36 | }; 37 | }; 38 | 39 | module.exports = ServerCrypto; 40 | -------------------------------------------------------------------------------- /src/modules/logger.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Logger sets logging methods for code 3 | * 4 | * 5 | */ 6 | 7 | 8 | 'use strict' 9 | 10 | // Default log level 11 | var DEF_LOGLEVEL = "ERROR"; 12 | 13 | 14 | var logLevels = { 15 | "DEBUG": {val: 0, log: 'log'}, 16 | "INFO": {val: 1, log: 'log'}, 17 | "WARN": {val: 2, log: 'warn'}, 18 | "ERROR": {val: 3, log: 'error'}, 19 | "LOG": {val: 99, log: 'log'} 20 | } 21 | 22 | var logLevelsByNum = [ 23 | logLevels.DEBUG, 24 | logLevels.INFO, 25 | logLevels.WARN, 26 | logLevels.ERROR, 27 | logLevels.LOG 28 | ]; 29 | 30 | /** 31 | * @function 32 | * Return a numeric value for the level 33 | * @return {number} mapped numeric value or the "ERROR" level value 34 | */ 35 | function getLevelVal(level) { 36 | var ltype = typeof (level); 37 | var lvl; 38 | if (ltype === 'string') { 39 | lvl = logLevels[level]; 40 | } 41 | else if (ltype === 'number') { 42 | lvl = logLevelsByNum[level]; 43 | } 44 | else { 45 | return 3; 46 | } 47 | 48 | if(lvl == null){ 49 | return 3; 50 | } 51 | return lvl.val; 52 | } 53 | 54 | function getLevelObject(level){ 55 | var numVal = -1; 56 | if(typeof(level) === 'string'){ 57 | numVal = getLevelVal(level); 58 | } 59 | 60 | return logLevelsByNum[numVal]; 61 | } 62 | 63 | /** 64 | * @function 65 | * Convert obj into an array 66 | */ 67 | function toArray(obj){ 68 | var arr = []; 69 | var val; 70 | var i; 71 | if(obj == null){ 72 | return arr; 73 | } 74 | if((typeof(obj) === 'object') && obj.length == null){ 75 | arr.push(obj); 76 | return arr; 77 | } 78 | for(i=0;i= myLevel); 194 | } 195 | 196 | /** 197 | * @function 198 | * Begin a grouping level 199 | * */ 200 | this.group = function () { 201 | var args = toArray(arguments); 202 | var cw = consoleWrapper; 203 | cw['group'].apply(null, args); 204 | } 205 | 206 | /** 207 | * @function 208 | * End a grouping 209 | * */ 210 | this.groupEnd = function () { 211 | var args = toArray(arguments); 212 | var cw = consoleWrapper; 213 | cw['groupEnd'].apply(null, args); 214 | } 215 | 216 | /** 217 | * @function 218 | * Central method for writing the log value 219 | */ 220 | this.log = function(){ 221 | var args = toArray(arguments); 222 | var msg, lvlArg; 223 | var logIt = true; 224 | var levelDef = logLevels.LOG; 225 | var doTrace = false; 226 | var i; 227 | 228 | if(args.length >= 2){ 229 | if(typeof(args[args.length - 1]) === 'string'){ 230 | lvlArg = args.pop(); 231 | logIt = doLog(lvlArg); 232 | levelDef = logLevels[lvlArg]; 233 | } 234 | else if(typeof(args[args.length - 1]) === 'number'){ 235 | lvlArg = args.pop(); 236 | logIt = (lvlArg >= getLevelVal(me.opts.level)); 237 | levelDef = logLevelsByNum[lvlArg]; 238 | } 239 | } 240 | 241 | if(!levelDef){ levelDef = logLevels.LOG; } 242 | 243 | if(args.length == 0){ 244 | msg = this.name + ": [no message]"; 245 | } 246 | else if(typeof(args[0]) === 'string'){ 247 | msg = this.name + ': ' + args.shift(); 248 | } 249 | else{ 250 | msg = this.name; 251 | } 252 | 253 | args.unshift(msg); 254 | doTrace = (levelDef.val == logObj.WARN || levelDef.val == logObj.ERROR); 255 | if(doTrace || levelDef.val == logObj.DEBUG){ 256 | args.push({ page: document.location.href }); 257 | } 258 | 259 | // Add to buffer, even if we don't log 260 | if (buffer.length > maxBuffer) { 261 | buffer.shift(); 262 | } 263 | // todo stringify 264 | buffer.push(args); 265 | 266 | // end if disabled, but item is in the buffer 267 | if (this.enabled != true) { 268 | return; 269 | } 270 | 271 | if (!logIt) { 272 | return; 273 | } 274 | 275 | var result; 276 | var cw = consoleWrapper; 277 | if(cw[levelDef.log]){ 278 | result = cw[levelDef.log].apply(null, args); 279 | } 280 | else{ 281 | result = cw.log.apply(null, args); 282 | } 283 | if (doTrace && cw.trace){ 284 | cw.trace(); 285 | } 286 | 287 | return result; 288 | } 289 | } 290 | 291 | /** 292 | * @function 293 | * Change the internal log level after initialization 294 | */ 295 | Logger.prototype.setLogLevel = function (level) { 296 | var lvlType = typeof (level); 297 | var lvlObj; 298 | if (lvlType === 'string') { 299 | this.opts.level = level; 300 | } 301 | else if (lvlType === 'number') { 302 | lvlObj = logLevelsByNum[level]; 303 | if (lvlObj) { 304 | try { 305 | this.opts.level = lvlObj.log.toUpperCase(); 306 | } 307 | catch (ex) { } 308 | } 309 | } 310 | } 311 | 312 | Logger.prototype.getLevels = function(){ 313 | return logLevels; 314 | } 315 | 316 | Logger.prototype.debug = function(){ 317 | var args = toArray(arguments); 318 | args.push(logObj.DEBUG); 319 | return this.log.apply(this, args); 320 | } 321 | Logger.prototype.info = function(){ 322 | var args = toArray(arguments); 323 | args.push(logObj.INFO); 324 | return this.log.apply(this, args); 325 | } 326 | Logger.prototype.warn = function(){ 327 | var args = toArray(arguments); 328 | args.push(logObj.WARN); 329 | return this.log.apply(this, args); 330 | } 331 | Logger.prototype.error = function(){ 332 | var args = toArray(arguments); 333 | args.push(logObj.ERROR); 334 | return this.log.apply(this, args); 335 | } 336 | 337 | var logObj = { 338 | createLogger: function(){ 339 | return new Logger(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 340 | }, 341 | DEBUG: 0, 342 | INFO: 1, 343 | WARN: 2, 344 | ERROR: 3 345 | }; 346 | 347 | module.exports = logObj; 348 | 349 | -------------------------------------------------------------------------------- /src/tool_scripts/buildFrameV1.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var buildHelper = require('./build_frame'); 4 | 5 | buildHelper.buildDebugFrameV1(); 6 | 7 | -------------------------------------------------------------------------------- /src/tool_scripts/buildFrameV2.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var buildHelper = require('./build_frame'); 4 | 5 | buildHelper.buildEmbedAll(); 6 | 7 | -------------------------------------------------------------------------------- /src/tool_scripts/build_frame.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Script to build the iframe with embedded code inside. 3 | * Also generates debug versions of iframe and IPT redirect file 4 | * */ 5 | 6 | var fs = require('fs'); 7 | 8 | var redirectBuffer = null, 9 | iframeBuffer = null, 10 | scriptFullBuffer = null, 11 | scriptMinBuffer = null; 12 | 13 | const DEBUG_IDAPI_SETTING = 'configGeneral.urls.digitrustIdService = "../misc/faked_id_service_v1.json" //http://local.digitru.st/misc/faked_id_service_v1.json' 14 | const DEBUG_SCRIPT_TAG = "" 15 | const PROD_V2_SCRIPT_TAG = "" 16 | const DEBUG_V1_SCRIPT_TAG = "" 17 | const PROD_V1_SCRIPT_TAG = "" 18 | const PROD_REDIR_SCRIPT_TAG = "" 19 | const DEBUG_REDIR_SCRIPT_TAG = "" 20 | 21 | const outputFile = { 22 | EMBEDDED: 'dt-embed.html', 23 | REF: 'dt.html', 24 | DEBUG: 'dt_debug.html', 25 | REDIR: 'redirect.html', 26 | DEBUG_REDIR: 'redirect_debug.html' 27 | }; 28 | 29 | const replaceTokens = { 30 | SCRIPTREF: "", 31 | CONFIG_DEBUG: '/* TOKEN ADDITIONAL SETTINGS */' 32 | } 33 | 34 | 35 | function writeEmbedScriptAll() { 36 | fs.readFile('./dist/digitrust_iframe.min.js', 'utf8', function (err, contents) { 37 | scriptMinBuffer = contents; 38 | checkComplete(scriptMinBuffer, scriptFullBuffer, iframeBuffer, true, PROD_V2_SCRIPT_TAG); 39 | }); 40 | fs.readFile('./dist/digitrust_iframe.js', 'utf8', function (err, contents) { 41 | scriptFullBuffer = contents; 42 | checkComplete(scriptMinBuffer, scriptFullBuffer, iframeBuffer, true, PROD_V2_SCRIPT_TAG); 43 | }); 44 | fs.readFile('./pages/dt.html', 'utf8', function (err, contents) { 45 | iframeBuffer = contents; 46 | checkComplete(scriptMinBuffer, scriptFullBuffer, iframeBuffer, true, PROD_V2_SCRIPT_TAG); 47 | }); 48 | 49 | fs.readFile('./pages/redirect.html', 'utf8', function (err, contents) { 50 | redirectBuffer = contents; 51 | writeRedirectFiles(redirectBuffer); 52 | }); 53 | } 54 | 55 | 56 | function writeV1FrameFiles() { 57 | scriptMinBuffer = " /* DIGITRUST IFRAME */" 58 | scriptFullBuffer = "IGNORE"; 59 | 60 | fs.readFile('./pages/dt.html', 'utf8', function (err, contents) { 61 | iframeBuffer = contents; 62 | checkComplete(scriptMinBuffer, scriptFullBuffer, iframeBuffer, false, PROD_V1_SCRIPT_TAG); 63 | }); 64 | 65 | fs.readFile('./pages/redirect.html', 'utf8', function (err, contents) { 66 | redirectBuffer = contents; 67 | writeRedirectFiles(redirectBuffer); 68 | }); 69 | } 70 | 71 | 72 | 73 | 74 | /** 75 | * Tests that all needed contents are loaded. 76 | * If so, proceeds with writing the files 77 | * @param {any} scripts 78 | * @param {any} markup 79 | */ 80 | function checkComplete(scriptMin, scriptFull, markup, writeEmbed, prodScriptRef){ 81 | if (scriptMin == null 82 | || scriptFull == null 83 | || markup == null) { 84 | return; 85 | } 86 | 87 | var debugMarkup = formatDebugFile(markup, writeEmbed); 88 | var embedMarkup = formatEmbedFile(markup, scriptMin); 89 | var refMarkup = formatScriptRef(markup, prodScriptRef); 90 | var fileRef; 91 | 92 | var files = [ 93 | { file: './dist/' + outputFile.REF, data: refMarkup }, 94 | { file: './dist/' + outputFile.DEBUG, data: debugMarkup } 95 | ]; 96 | 97 | if (writeEmbed) { 98 | files.push({ file: './dist/' + outputFile.EMBEDDED, data: embedMarkup }); 99 | } 100 | 101 | 102 | for (let i = 0; i < files.length; i++) { 103 | fileRef = files[i].file; 104 | if (fs.existsSync(fileRef)) { 105 | fs.unlinkSync(fileRef); 106 | } 107 | 108 | fs.writeFile(fileRef, files[i].data, function (err, data) { 109 | if (err) { 110 | console.log(err); 111 | return; 112 | } 113 | }); 114 | } 115 | } 116 | 117 | function writeRedirectFiles(buffer) { 118 | var fileRef; 119 | var files = [ 120 | { file: './dist/' + outputFile.REDIR }, 121 | { file: './dist/' + outputFile.DEBUG_REDIR} 122 | ]; 123 | 124 | for (let i = 0; i < files.length; i++) { 125 | fileRef = files[i].file; 126 | if (fs.existsSync(fileRef)) { 127 | fs.unlinkSync(fileRef); 128 | } 129 | } 130 | 131 | fs.writeFile('./dist/' + outputFile.REDIR, buffer, function (err, data) { 132 | if (err) { 133 | console.log(err); 134 | return; 135 | } 136 | }); 137 | 138 | var debugBuffer = buffer.replace(PROD_REDIR_SCRIPT_TAG, DEBUG_REDIR_SCRIPT_TAG); 139 | fs.writeFile('./dist/' + outputFile.DEBUG_REDIR, debugBuffer, function (err, data) { 140 | if (err) { 141 | console.log(err); 142 | return; 143 | } 144 | }); 145 | 146 | } 147 | 148 | 149 | /** 150 | * Format the source into the debug iFrame 151 | * @param {any} markup 152 | */ 153 | function formatDebugFile(markup, writeEmbed) { 154 | var result; 155 | if (writeEmbed) { 156 | result = markup.replace(replaceTokens.SCRIPTREF, DEBUG_SCRIPT_TAG).replace(replaceTokens.CONFIG_DEBUG, DEBUG_IDAPI_SETTING); 157 | } 158 | else { 159 | result = markup.replace(replaceTokens.SCRIPTREF, DEBUG_V1_SCRIPT_TAG).replace(replaceTokens.CONFIG_DEBUG, DEBUG_IDAPI_SETTING); 160 | } 161 | 162 | return result; 163 | } 164 | 165 | /** 166 | * Format the source into the debug iFrame 167 | * @param {any} markup 168 | */ 169 | function formatEmbedFile(markup, embedScript) { 170 | var result = markup.replace(replaceTokens.SCRIPTREF, "\n"); 171 | return result; 172 | } 173 | 174 | /** 175 | * Format the source into the prod iFrame 176 | * @param {any} markup 177 | */ 178 | function formatScriptRef(markup, scriptTag) { 179 | var result = markup.replace(replaceTokens.SCRIPTREF, scriptTag); 180 | return result; 181 | } 182 | 183 | function buildDebugFrameV1() { 184 | writeV1FrameFiles(); 185 | } 186 | 187 | 188 | module.exports = { 189 | buildDebugFrameV1: buildDebugFrameV1, 190 | buildEmbedAll: writeEmbedScriptAll 191 | }; 192 | 193 | -------------------------------------------------------------------------------- /src/tool_scripts/checkSourceForConsole.js: -------------------------------------------------------------------------------- 1 | 2 | var checkSource = require('./check_sourcecode'); 3 | 4 | checkSource.checkDisallowedCalls(); 5 | 6 | -------------------------------------------------------------------------------- /src/tool_scripts/check_sourcecode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks the source code for disallowed calls 3 | * */ 4 | 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | 8 | // Disallowed method calls 9 | var illegalCalls = [ 10 | 'console.' 11 | ]; 12 | 13 | 14 | 15 | 16 | function checkFileForDisallowedCalls(filename) { 17 | var i, loc, check, err; 18 | var sec, lineCnt; 19 | 20 | var buffer = fs.readFileSync(filename, 'utf8'); 21 | 22 | for (i = 0; i < illegalCalls.length; i++) { 23 | check = illegalCalls[i]; 24 | loc = buffer.indexOf(check); 25 | if (loc > -1) { 26 | sec = buffer.substr(0, loc); 27 | lineCnt = sec.split(/\n/).length; 28 | err = 'Found disallowed call in file ' + filename + ' at position ' + loc + ' line ' + lineCnt + '\n' 29 | + ' call to ' + check + '\n'; 30 | throw err; 31 | } 32 | } 33 | 34 | /* 35 | fs.readFile('filename', 'utf8', function (err, contents) { 36 | iframeBuffer = contents; 37 | checkComplete(scriptMinBuffer, scriptFullBuffer, iframeBuffer); 38 | }); 39 | 40 | fs.readFile('./pages/redirect.html', 'utf8', function (err, contents) { 41 | redirectBuffer = contents; 42 | writeRedirectFiles(redirectBuffer); 43 | }); 44 | */ 45 | } 46 | 47 | function walkContents(folder, foundFiles) { 48 | var files = fs.readdirSync(folder); 49 | files.forEach(function (file) { 50 | var filePath = path.join(folder, file); 51 | if (fs.statSync(filePath).isDirectory()) { 52 | walkContents(filePath, foundFiles); 53 | } 54 | else { 55 | foundFiles.push(filePath); 56 | } 57 | }) 58 | } 59 | 60 | 61 | function checkDisallowedCalls() { 62 | var fileList = []; 63 | walkContents('./src/modules', fileList); 64 | console.log('Checking source code for disallowed statements') 65 | 66 | fileList.forEach(function (file) { 67 | if (file.indexOf('.js') < file.length - 3) { 68 | return; 69 | } 70 | if (file.indexOf('logger.js') == -1) { 71 | checkFileForDisallowedCalls(file); 72 | } 73 | }) 74 | 75 | 76 | } 77 | 78 | module.exports = { 79 | checkDisallowedCalls: checkDisallowedCalls 80 | }; 81 | 82 | -------------------------------------------------------------------------------- /test/distsizes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11/28/2018 4 | 5 | dt.js: 161Kb 6 | dt.min.js: 40Kb 7 | dt.html: 6Kb 8 | 9 | 11/29/2018 10 | 11 | dt.js: 164Kb 12 | dt.min.js: 40Kb 13 | dt.html: 6Kb 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/integration/Readme.md: -------------------------------------------------------------------------------- 1 | == Integration Tets 2 | 3 | Integration tests are written in Selenium/Webdriver for Java. These tests may be found in the following location: 4 | 5 | ~/TestIntegration 6 | 7 | 8 | -- Setup 9 | TBD. 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/jest/communication.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Communication Test Spec 5 | * @module 6 | * Exercise the communication related components of digitrust. 7 | * */ 8 | 9 | 10 | var psFactory = require('../../src/modules/MinPubSub'); 11 | 12 | test('Should register and respond to a new message', function () { 13 | var pubsub = psFactory.createPubSub(); 14 | var callcount = 0; 15 | var t = 'mytest'; 16 | pubsub.subscribe(t, function () { 17 | callcount++; 18 | }); 19 | 20 | expect(callcount).toBe(0); 21 | pubsub.publish(t); 22 | expect(callcount).toBe(1); 23 | 24 | }); 25 | 26 | test('Should unregister listeners', function () { 27 | var pubsub = psFactory.createPubSub(); 28 | var callcount = 0; 29 | var t = 'mytest'; 30 | var fn = function () { 31 | callcount++; 32 | }; 33 | 34 | pubsub.subscribe(t, fn); 35 | 36 | expect(callcount).toBe(0); 37 | pubsub.publish(t); 38 | pubsub.publish(t); 39 | expect(callcount).toBe(2); 40 | pubsub.unsubscribe(t, fn); 41 | pubsub.publish(t); 42 | expect(callcount).toBe(2); 43 | }); 44 | 45 | test('Should recognize multiple listeners', function () { 46 | var pubsub = psFactory.createPubSub(); 47 | var callcount = 0; 48 | var t = 'mytest'; 49 | var fn = function () { 50 | callcount++; 51 | }; 52 | var fn2 = function () { 53 | callcount += 3; 54 | }; 55 | 56 | pubsub.subscribe(t, fn); 57 | expect(callcount).toBe(0); 58 | pubsub.publish(t); 59 | expect(callcount).toBe(1); 60 | 61 | pubsub.subscribe(t, fn2); 62 | pubsub.publish(t); 63 | 64 | expect(callcount).toBe(5); 65 | pubsub.unsubscribe(t, fn); 66 | pubsub.publish(t); 67 | expect(callcount).toBe(8); 68 | }); 69 | test('Should recognize different topics', function () { 70 | var pubsub = psFactory.createPubSub(); 71 | var callcount = 0; 72 | var t = 'mytest'; 73 | var t2 = 'foo' 74 | var fn = function () { 75 | callcount++; 76 | }; 77 | var fn2 = function () { 78 | callcount += 3; 79 | }; 80 | 81 | pubsub.subscribe(t, fn); 82 | expect(callcount).toBe(0); 83 | pubsub.publish(t); 84 | expect(callcount).toBe(1); 85 | 86 | pubsub.subscribe(t2, fn2); 87 | pubsub.publish(t2); 88 | 89 | expect(callcount).toBe(4); 90 | }); 91 | -------------------------------------------------------------------------------- /test/jest/configLoader.test.js: -------------------------------------------------------------------------------- 1 | const config = require('../../src/modules/ConfigLoader'); 2 | const generalConfig = require('../../src/config/GeneralConfig'); 3 | 4 | beforeEach(() => { 5 | config.reset(); 6 | }); 7 | 8 | test('config get a deep value', () => { 9 | let val = config.getValue("cookie.version"); 10 | expect(val).toBe(2); 11 | }); 12 | 13 | test('load-new-config', () => { 14 | config.reset(); 15 | var val = config.getValue("cookie.version"); 16 | expect(val).toBe(2); 17 | config.loadConfig({ 18 | cookie: { 19 | version: 5 20 | } 21 | }); 22 | 23 | val = config.getValue("cookie.version"); 24 | expect(val).toBe(5); 25 | 26 | }); 27 | 28 | 29 | test('version Calculations with base only', () => { 30 | var baseVersion = "1.5.31"; 31 | 32 | var result = generalConfig.computeVersions(baseVersion); 33 | 34 | expect(result.current).toBe(baseVersion); 35 | expect(result.prior).toBe("1.5.30"); 36 | 37 | }); 38 | 39 | -------------------------------------------------------------------------------- /test/jest/debugControl.test.js: -------------------------------------------------------------------------------- 1 | const digitrustRoot = require('../../src/modules/DigiTrust'); 2 | const debugCtrl = require('../../src/modules/DebugControl'); 3 | const helpers = require('../../src/modules/helpers'); 4 | 5 | beforeAll(() => { 6 | if (!window.DigiTrust) { 7 | window.DigiTrust = { isClient: true, version: '1.0.mock' }; 8 | } 9 | }); 10 | 11 | test('can create debugControl', () => { 12 | let mockDt = { 13 | util: helpers 14 | }; 15 | let target = debugCtrl.createDebugControl(mockDt); 16 | expect(target).not.toBeNull; 17 | expect(target.isDebug()).toBeFalsy; 18 | }); 19 | 20 | 21 | test('can toggle mock state', () => { 22 | let mockDt = { 23 | util: helpers 24 | }; 25 | let target = debugCtrl.createDebugControl(mockDt); 26 | expect(target.isDebug()).toBe(false); 27 | target.setDebug(true); 28 | expect(target.isDebug()).toBe(true); 29 | target.setDebug(false); 30 | expect(target.isDebug()).toBe(false); 31 | }); 32 | 33 | 34 | test('can toggle real obj state', () => { 35 | let target = debugCtrl.createDebugControl(digitrustRoot); 36 | expect(target.isDebug()).toBe(false); 37 | target.setDebug(true); 38 | expect(target.isDebug()).toBe(true); 39 | target.setDebug(false); 40 | expect(target.isDebug()).toBe(false); 41 | }); 42 | 43 | test('can dump log output', () => { 44 | let target = debugCtrl.createDebugControl(digitrustRoot); 45 | var log = target.dumpLogs(); 46 | expect(log.length).toBeGreaterThan(1); 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /test/jest/digitrustBase.test.js: -------------------------------------------------------------------------------- 1 | 2 | const DigiTrust = require('../../src/modules/DigiTrust'); 3 | const helpers = require('../../src/modules/helpers'); 4 | 5 | window.DigiTrust = DigiTrust; 6 | 7 | var originVal = "https://cdn.digitru.st"; 8 | var newVal = "https://foo.site.com"; 9 | var oldData = { 10 | iframe: { postMessageOrigin: originVal } 11 | }; 12 | var newData = { 13 | iframe: { postMessageOrigin: newVal } 14 | }; 15 | 16 | 17 | beforeEach(() => { 18 | DigiTrust._config.reload(); 19 | DigiTrust._config.getConfig().loadConfig(oldData); 20 | }) 21 | 22 | 23 | test('DigiTrust config loaded', () => { 24 | var originVal = "https://cdn.digitru.st"; 25 | var key = 'iframe.postMessageOrigin' 26 | expect(DigiTrust._config.getConfig().getValue(key)).toBe(originVal); 27 | }); 28 | 29 | 30 | test('DigiTrust config sets value', () => { 31 | var originVal = "https://cdn.digitru.st"; 32 | var newVal = "https://foo.site.com"; 33 | var key = 'iframe.postMessageOrigin' 34 | expect(DigiTrust._config.getConfig().getValue(key)).toBe(originVal); 35 | 36 | 37 | DigiTrust._config.getConfig().loadConfig(newData); 38 | 39 | expect(DigiTrust._config.getConfig().getValue(key)).toBe(newVal); 40 | }); 41 | 42 | 43 | test('helpers has same config sets value', () => { 44 | var key = 'iframe.postMessageOrigin' 45 | expect(DigiTrust._config.getConfig().getValue(key)).toBe(originVal); 46 | 47 | DigiTrust._config.getConfig().loadConfig(newData); 48 | 49 | expect(helpers.getConfig().getValue(key)).toBe(newVal); 50 | }); 51 | 52 | -------------------------------------------------------------------------------- /test/jest/digitrustClient.test.js: -------------------------------------------------------------------------------- 1 | 2 | const DigiTrust = require('../../src/modules/DigiTrust'); 3 | const config = require('../../src/modules/ConfigLoader'); 4 | 5 | window.DigiTrust = DigiTrust; 6 | 7 | // Commenting out failing tests to fix build and deploy temporarily. 8 | // I suspect there is a timing/retry issue in the code that must be fixed 9 | // as these tests fail sporatically. 10 | // These may also be caused by Chrome headless not working over non-ssl. 11 | 12 | beforeEach(() => { 13 | document.cookie = config.getValue('cookie.publisher.userObjectKey') 14 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 15 | document.cookie = config.getValue('cookie.digitrust.userObjectKey') 16 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 17 | 18 | }) 19 | 20 | /* 21 | 22 | //logging: { level: "DEBUG", enable: true }, 23 | environment: { 24 | redir: { 25 | exp: 2, 26 | experiod: 's' 27 | }, 28 | urls: { 29 | "digitrustIframe": "http://local.digitru.st/dist/dt_debug.html", 30 | "digitrustIdService": "http://local.digitru.st/misc/faked_id_service_v1.json" 31 | }, 32 | iframe: { 33 | postMessageOrigin: "http://local.digitru.st", 34 | timeoutDuration: (1000 * 60) 35 | } 36 | }, 37 | test('DigiTrust can init', done => { 38 | DigiTrust.initialize( 39 | { 40 | member: 'foo', 41 | site: 'example_site_id', 42 | consent: { 43 | requires: 'none' 44 | } 45 | }, 46 | function (identityResponse) { 47 | expect(DigiTrust.isClient).toBe(true); 48 | done(); 49 | } 50 | ) 51 | }); 52 | */ 53 | 54 | /* 55 | test('DigiTrust fails init with sample rate zero', done => { 56 | DigiTrust.initialize({ 57 | member: 'foo', 58 | sample: 0 59 | }, 60 | function (identityResponse) { 61 | var consentLinkId = "digitrust-optout"; 62 | 63 | expect(identityResponse.success).toBe(false); 64 | expect(document.getElementById(consentLinkId)).toBe(null); 65 | done(); 66 | }); 67 | }); 68 | */ 69 | 70 | test('DigiTrust invalid member fails', done => { 71 | DigiTrust.initialize({}, 72 | function (identityResponse) { 73 | expect(identityResponse.success).toBe(false); 74 | done(); 75 | } 76 | ) 77 | }); 78 | 79 | 80 | test('DigiTrust undefined callback does not throw', done => { 81 | DigiTrust.initialize({ 82 | member: 'foo', 83 | consent: { 84 | requires: 'none' 85 | } 86 | }); 87 | 88 | done(); 89 | }); 90 | 91 | /* 92 | test('DigiTrust getUser from callback', done => { 93 | DigiTrust.getUser({ member: "foo" }, function (rslt) { 94 | expect(rslt).not.toBeNull(); 95 | done(); 96 | }); 97 | 98 | }); 99 | */ 100 | 101 | test('DigiTrust getUser invalid member returns false', done => { 102 | DigiTrust.getUser({ member: null }, function (rslt) { 103 | expect(rslt).not.toBeNull(); 104 | expect(rslt.success).toBeFalsy(); 105 | done(); 106 | }); 107 | }); 108 | 109 | test('DigiTrust getUser null member returns false', done => { 110 | DigiTrust.getUser(null, function (rslt) { 111 | expect(rslt).not.toBeNull(); 112 | expect(rslt.success).toBeFalsy(); 113 | done(); 114 | }); 115 | 116 | }); 117 | 118 | test('DigiTrust getUser sync to not throw', done => { 119 | var rslt = DigiTrust.getUser({ member: "foo" }); 120 | expect(rslt).not.toBeNull(); 121 | done(); 122 | }); 123 | -------------------------------------------------------------------------------- /test/jest/helpers.test.js: -------------------------------------------------------------------------------- 1 | const helpers = require('../../src/modules/helpers'); 2 | 3 | beforeAll(() => { 4 | if (!window.DigiTrust) { 5 | window.DigiTrust = { isClient: true, version: '1.0.mock' }; 6 | } 7 | }); 8 | 9 | test('getAbsolutePath', () => { 10 | 11 | expect(helpers.getAbsolutePath('http://example.com')).toBe('http://example.com/'); 12 | expect(helpers.getAbsolutePath('https://www.exmaple.com')).toBe('https://www.exmaple.com/'); 13 | expect(helpers.getAbsolutePath('//cdn.example.com/lib.js')).toBe('http://cdn.example.com/lib.js'); 14 | 15 | expect(helpers.getAbsolutePath('/test')).toBe('http://localhost/test'); 16 | expect(helpers.getAbsolutePath('test')).toBe('http://localhost/test'); 17 | expect(helpers.getAbsolutePath('#test')).toBe('http://localhost/#test'); 18 | expect(helpers.getAbsolutePath('../test')).toBe('http://localhost/test'); 19 | 20 | }); 21 | 22 | test('urlParameter by name gets value', () => { 23 | var search = "?foo=bar&my=yours&a=b"; 24 | 25 | expect(helpers.getUrlParameterByName('foo', search)).toBe('bar'); 26 | expect(helpers.getUrlParameterByName('my', search)).toBe('yours'); 27 | expect(helpers.getUrlParameterByName('a', search)).toBe('b'); 28 | 29 | }); 30 | 31 | var testObj = { 32 | one: { 33 | two: { 34 | three: 3 35 | } 36 | } 37 | }; 38 | 39 | test('deepGet works happy path', () => { 40 | var obj = testObj; 41 | expect(helpers.deepGet(obj, "one.two.three")).toBe(3); 42 | }) 43 | test('deepGet works missing path', () => { 44 | var obj = testObj; 45 | expect(helpers.deepGet(obj, "one.four.three")).toBeUndefined(); //.toBe(null); 46 | }) 47 | 48 | test('debugModeTogglesState', () => { 49 | expect(helpers.isDebugEnabled()).toBeFalsy(); 50 | helpers.setDebug(true); 51 | expect(helpers.isDebugEnabled()).toBeTruthy(); 52 | helpers.setDebug(false); 53 | expect(helpers.isDebugEnabled()).toBeFalsy(); 54 | }) 55 | 56 | 57 | 58 | test('extend adds to literal object', () => { 59 | var objA = { 60 | foo: 'bar' 61 | } 62 | var objB = { 63 | beep: function () { return 'honk honk' } 64 | }; 65 | 66 | expect(objA.foo).toBe('bar'); 67 | expect(objA.beep).toBeUndefined(); 68 | expect(objB.beep()).toBe('honk honk'); 69 | 70 | helpers.extend(objA, objB); 71 | expect(objA.beep()).toBe('honk honk'); 72 | }) 73 | 74 | test('extend generates an object', () => { 75 | var objA; 76 | 77 | var objB = { 78 | beep: function () { return 'honk honk' } 79 | }; 80 | 81 | expect(objA).toBeUndefined(); 82 | 83 | objA = helpers.extend(objA, objB); 84 | expect(objA.beep()).toBe('honk honk'); 85 | }) 86 | 87 | test('isEmpty handles an object', () => { 88 | var val = new Object(); 89 | val.a = "b"; 90 | expect(helpers.isEmpty(val)).toBeFalsy(); 91 | }); 92 | 93 | test('isEmpty true for empty literal', () => { 94 | expect(helpers.isEmpty({})).toBeTruthy(); 95 | }); 96 | 97 | test('isEmpty true for empty Object', () => { 98 | expect(helpers.isEmpty(new Object())).toBeTruthy(); 99 | }); 100 | 101 | test('isEmpty true for null', () => { 102 | expect(helpers.isEmpty(null)).toBeTruthy(); 103 | }); 104 | 105 | test('isEmpty true for undefined', () => { 106 | var x; 107 | expect(helpers.isEmpty(x)).toBe(true); 108 | }); 109 | test('isEmpty true for array', () => { 110 | expect(helpers.isEmpty([])).toBe(true); 111 | }); 112 | test('isEmpty false for filled array', () => { 113 | expect(helpers.isEmpty(['b','a'])).toBe(false); 114 | }); 115 | 116 | test('validJson for invalid is false', () => { 117 | expect(helpers.isValidJSON('{"b": "a"')).toBe(false); 118 | }); 119 | 120 | test('validJson for array is true', () => { 121 | expect(helpers.isValidJSON('["b", "a"]')).toBe(true); 122 | }); 123 | 124 | test('validJson for object is true', () => { 125 | expect(helpers.isValidJSON('{"a": "b"}')).toBe(true); 126 | }); 127 | 128 | test('round trips string to arraybuffer and back', () => { 129 | var val = "HELLO WORLD! I love you." 130 | var ab = helpers.str2ab(val); 131 | expect(val).not.toEqual(ab); 132 | var result = helpers.ab2str(ab); 133 | 134 | expect(result).toEqual(val); 135 | }); 136 | 137 | // Browser sniffing 138 | var uagent = { 139 | mac_safari: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9", 140 | iphone: "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", 141 | chrome: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", 142 | android: "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36", 143 | windows_edge: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246", 144 | windows_edge2: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; ServiceUI 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362", 145 | windows_ie: "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", 146 | windows_ie2: "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; .NET4.0C; .NET4.0E; Tablet PC 2.0; wbx 1.0.0; rv:11.0) like Gecko" 147 | } 148 | 149 | test('finds IE but ignores Chrome', () => { 150 | expect(helpers.isIE(uagent.windows_ie)).toBe(true); 151 | expect(helpers.isIE(uagent.windows_ie2)).toBe(true); 152 | expect(helpers.isIE(uagent.chrome)).toBe(false); 153 | }); 154 | 155 | test('finds Safari but ignores Chrome and IE', () => { 156 | expect(helpers.isSafari(uagent.mac_safari)).toBe(true); 157 | expect(helpers.isSafari(uagent.chrome)).toBe(false); 158 | expect(helpers.isSafari(uagent.android)).toBe(false); 159 | expect(helpers.isSafari(uagent.windows_ie2)).toBe(false); 160 | }); 161 | 162 | test('finds iOS Safari', () => { 163 | expect(helpers.isSafari(uagent.iphone)).toBe(true); 164 | }); 165 | 166 | test('isChrome ignores IE', () => { 167 | expect(helpers.isChrome(uagent.windows_ie)).toBe(false); 168 | }); 169 | test('isChrome finds Chrome', () => { 170 | expect(helpers.isChrome(uagent.chrome)).toBe(true); 171 | }); 172 | -------------------------------------------------------------------------------- /test/jest/logger.test.js: -------------------------------------------------------------------------------- 1 | const logger = require('../../src/modules/logger'); 2 | 3 | beforeAll(() => { 4 | if (!window.DigiTrust) { 5 | window.DigiTrust = { isClient: true, version: '1.0.mock' }; 6 | } 7 | }); 8 | 9 | test('can create logger', () => { 10 | let log = logger.createLogger('testLogger'); 11 | let levels = log.getLevels(); 12 | expect(levels).toBeTruthy(); 13 | expect(levels['DEBUG'].val).toBe(0); 14 | expect(levels['INFO'].val).toBe(1); 15 | expect(levels['ERROR'].val).toBe(3); 16 | expect(levels['ERROR'].log).toBe('error'); 17 | expect(log.name).toBe('testLogger'); 18 | }); 19 | 20 | test('create logger has default name', () => { 21 | let log = logger.createLogger(); 22 | expect(log.name).toBe('Logger'); 23 | }); 24 | 25 | test('creates a named logger', () => { 26 | let log = logger.createLogger('FUBAR'); 27 | expect(log.name).toBe('FUBAR'); 28 | }); 29 | 30 | test('creates a named logger', () => { 31 | let log = logger.createLogger('FUBAR'); 32 | expect(log.name).toBe('FUBAR'); 33 | }); 34 | 35 | test('creates with an init object', () => { 36 | let log = logger.createLogger({ level: logger.INFO, name: 'FUBAR' }); 37 | expect(log.name).toBe('FUBAR'); 38 | }); 39 | 40 | test('allows custom logger console', () => { 41 | let cust = { 42 | log: function (msg) { 43 | return msg; 44 | } 45 | } 46 | 47 | let log = logger.createLogger({ level: logger.DEBUG, name: 'CUSTCON', console: cust }); 48 | 49 | expect(log.log('hello')).toBe('CUSTCON: hello'); 50 | }); 51 | 52 | test('does not fail on invalid logger', () => { 53 | let cust = {} 54 | 55 | let log = logger.createLogger({ level: logger.DEBUG, name: 'CUSTCON', console: cust }); 56 | 57 | expect(log.log('hello')).toBeUndefined; 58 | }); 59 | 60 | test('does not fail on null logger', () => { 61 | 62 | let log = logger.createLogger({ level: logger.DEBUG, name: 'CUSTCON', console: null }); 63 | 64 | expect(log.log('hello')).toBeUndefined; 65 | }); 66 | 67 | 68 | test('filters verbose logs', () => { 69 | let cust = { 70 | log: function (msg) { 71 | return msg; 72 | } 73 | } 74 | 75 | let log = logger.createLogger({ level: logger.WARN, name: 'CUSTCON', console: cust }); 76 | 77 | expect(log.warn('hello')).toBe('CUSTCON: hello'); 78 | expect(log.error('hello')).toBe('CUSTCON: hello'); 79 | expect(log.debug('hello')).toBeUndefined; 80 | expect(log.log('hello')).toBeUndefined; 81 | expect(log.info('hello')).toBeUndefined; 82 | 83 | }); 84 | 85 | test('creates a named logger', () => { 86 | let log = logger.createLogger('buffer'); 87 | expect(log.name).toBe('buffer'); 88 | log.warn('test 1'); 89 | log.log('test 2'); 90 | 91 | var result = log.getBuffer(); 92 | expect(result.length).toBe(2); 93 | }); 94 | 95 | 96 | -------------------------------------------------------------------------------- /test/s.binary.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IABTechLab/dt-cdn/a4369bd17e432b01a62cde1f7a98eea540c46128/test/s.binary.txt -------------------------------------------------------------------------------- /test/s.txt: -------------------------------------------------------------------------------- 1 | Hy5htKyjmazgrZZSTJHvMdY+tURmx83O2zxwT9Edz77f3MrwjJ5/iAJpUUNIvGY6ydUVS67D7f9mzEIT7sgOMZxgddH0anTrxeYOHp3Y2jWuW6xtnBGiMA3/pynm4+1q+vMaJDdDTwBLFoBTa7wiXMnUB6Q6ZsOtqPiNaFceItbpHxlXLmZiRvY833v/+esQ0TALWvvvXf5JMWMPpJYpXgcNe1ZETeBfwNSNXqGMIV9J7LXbrlnEoUhoikPwNtlDIU4yJrZG72rBwjFuy84tFkjd4jzcYDbFf/Bcnh/R464ItZly337kLhy385o+PoMY5C9UNeaqIuBh1HqbBV2Syg== 2 | digitrust-server.js:1185 Hy5htKyjmazgrZZSTJHvMdY+tURmx83O2zxwT9Edz77f3MrwjJ5/iAJpUUNIvGY6ydUVS67D7f9mzEIT7sgOMZxgddH0anTrxeYOHp3Y2jWuW6xtnBGiMA3/pynm4+1q+vMaJDdDTwBLFoBTa7wiXMnUB6Q6ZsOtqPiNaFceItbpHxlXLmZiRvY833v/+esQ0TALWvvvXf5JMWMPpJYpXgcNe1ZETeBfwNSNXqGMIV9J7LXbrlnEoUhoikPwNtlDIU4yJrZG72rBwjFuy84tFkjd4jzcYDbFf/Bcnh/R464ItZly337kLhy385o+PoMY5C9UNeaqIuBh1HqbBV2Syg== 3 | -------------------------------------------------------------------------------- /test/unit/communicationSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Communication Test Spec 5 | * @module 6 | * Exercise the communication related components of digitrust. 7 | * */ 8 | 9 | 10 | var psFactory = require('../../src/modules/MinPubSub'); 11 | var consts = require('../../src/config/constants.json'); 12 | 13 | 14 | 15 | describe('PubSub test', function () { 16 | it('Should register and respond to a new message', function () { 17 | var pubsub = psFactory.createPubSub(); 18 | var callcount = 0; 19 | var t = 'mytest'; 20 | pubsub.subscribe(t, function () { 21 | callcount++; 22 | }); 23 | 24 | expect(callcount).toBe(0); 25 | pubsub.publish(t); 26 | expect(callcount).toBe(1); 27 | 28 | }); 29 | 30 | it('Should unregister listeners', function () { 31 | var pubsub = psFactory.createPubSub(); 32 | var callcount = 0; 33 | var t = 'mytest'; 34 | var fn = function () { 35 | callcount++; 36 | }; 37 | 38 | pubsub.subscribe(t, fn); 39 | 40 | expect(callcount).toBe(0); 41 | pubsub.publish(t); 42 | pubsub.publish(t); 43 | expect(callcount).toBe(2); 44 | pubsub.unsubscribe(t, fn); 45 | pubsub.publish(t); 46 | expect(callcount).toBe(2); 47 | }); 48 | 49 | it('Should recognize multiple listeners', function () { 50 | var pubsub = psFactory.createPubSub(); 51 | var callcount = 0; 52 | var t = 'mytest'; 53 | var fn = function () { 54 | callcount++; 55 | }; 56 | var fn2 = function () { 57 | callcount += 3; 58 | }; 59 | 60 | pubsub.subscribe(t, fn); 61 | expect(callcount).toBe(0); 62 | pubsub.publish(t); 63 | expect(callcount).toBe(1); 64 | 65 | pubsub.subscribe(t, fn2); 66 | pubsub.publish(t); 67 | 68 | expect(callcount).toBe(5); 69 | pubsub.unsubscribe(t, fn); 70 | pubsub.publish(t); 71 | expect(callcount).toBe(8); 72 | }); 73 | it('Should recognize different topics', function () { 74 | var pubsub = psFactory.createPubSub(); 75 | var callcount = 0; 76 | var t = 'mytest'; 77 | var t2 = 'foo' 78 | var fn = function () { 79 | callcount++; 80 | }; 81 | var fn2 = function () { 82 | callcount += 3; 83 | }; 84 | 85 | pubsub.subscribe(t, fn); 86 | expect(callcount).toBe(0); 87 | pubsub.publish(t); 88 | expect(callcount).toBe(1); 89 | 90 | pubsub.subscribe(t2, fn2); 91 | pubsub.publish(t2); 92 | 93 | expect(callcount).toBe(4); 94 | }); 95 | }); 96 | -------------------------------------------------------------------------------- /test/unit/digitrustClientSpec.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var DigiTrust = require('../../src/modules/DigiTrust'); 4 | window.DigiTrust = DigiTrust; 5 | var helpers = require('../../src/modules/helpers'); 6 | var env = require('../../src/config/env.json').current; 7 | var configGeneral = require('../../src/config/general.json')[env]; 8 | var consts = require('../../src/config/constants.json'); 9 | 10 | 11 | // Commenting out failing tests to fix build and deploy temporarily. 12 | // I suspect there is a timing/retry issue in the code that must be fixed 13 | // as these tests fail sporatically 14 | describe('DigiTrust.getUser', function () { 15 | 16 | beforeAll(function (done) { 17 | document.cookie = configGeneral.cookie.publisher.userObjectKey 18 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 19 | document.cookie = configGeneral.cookie.digitrust.userObjectKey 20 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 21 | 22 | DigiTrust.initialize( 23 | { 24 | member: 'foo', 25 | consent: { 26 | requires: 'none' 27 | } 28 | }, 29 | function (identityResponse) { 30 | done(); 31 | } 32 | ) 33 | }); 34 | 35 | it('DigiTrust.getUser with Id', function (done) { 36 | expect(DigiTrust.isClient).toBe(true); 37 | 38 | DigiTrust.getUser({ 39 | member: 'foo' 40 | }, 41 | function (result) { 42 | console.log(result); 43 | expect(result.success).toBe(true); 44 | expect(result.identity).toBeDefined(); 45 | expect(result.identity.id).toBeDefined(); 46 | done(); 47 | } 48 | ); 49 | }); 50 | 51 | /* 52 | it('DigiTrust.getUser synchronous', function (done) { 53 | expect(DigiTrust.isClient).toBe(true); 54 | 55 | var result = DigiTrust.getUser({ 56 | member: 'foo' 57 | }); 58 | 59 | expect(result.identity).toBeDefined(); 60 | }); 61 | */ 62 | }); 63 | 64 | describe('DigiTrust.initialize() sample rate 0', function () { 65 | 66 | it('DigiTrust.initialize() fails immediately with sample rate of 0', function (done) { 67 | DigiTrust.initialize({ 68 | member: 'foo', 69 | sample: 0 70 | }, 71 | function (identityResponse) { 72 | expect(identityResponse.success).toBe(false); 73 | expect(document.getElementById(consts.consentLinkId)) 74 | .toBe(null); 75 | done(); 76 | }); 77 | }); 78 | }); 79 | 80 | describe('DigiTrust.initialize() undefined callback', function () { 81 | 82 | it('DigiTrust.initialize() with undefined callback', function (done) { 83 | DigiTrust.initialize({ 84 | member: 'foo' 85 | }); 86 | done(); 87 | }); 88 | }); 89 | 90 | -------------------------------------------------------------------------------- /test/unit/dtCookieSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Cookie Test Spec 5 | * @module 6 | * Exercise the cookie methods of digitrust. 7 | * */ 8 | 9 | var DigiTrustCookie = require('../../src/modules/DigiTrustCookie'); 10 | var dtCookie = require('../../src/modules/DigiTrustCookie'); 11 | var consts = require('../../src/config/constants.json'); 12 | var env = require('../../src/config/env.json').current; 13 | var configGeneral = require('../../src/config/general.json')[env]; 14 | 15 | 16 | describe('Cookie transform tests', function () { 17 | 18 | beforeAll(function (done) { 19 | document.cookie = configGeneral.cookie.publisher.userObjectKey 20 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 21 | document.cookie = configGeneral.cookie.digitrust.userObjectKey 22 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 23 | done(); 24 | }); 25 | 26 | 27 | it('Should encode and decode a cookie value', function () { 28 | var testval = "HELLO WORLddd"; 29 | // console.log(dtCookie); 30 | var obs = dtCookie.obfuscateCookieValue(testval); 31 | expect(obs == testval).toBeFalsy(); 32 | 33 | var back = dtCookie.unobfuscateCookieValue(obs); 34 | expect(back == testval).toBeTruthy(); 35 | }); 36 | 37 | it('DigiTrustCookie.unobfuscateCookieValue() on malformed data', function () { 38 | // set a bad identity cookie 39 | var cookieKey = configGeneral.cookie.digitrust.userObjectKey; 40 | var cookieExpires = new Date(); 41 | cookieExpires.setTime(cookieExpires.getTime() + 60000); 42 | document.cookie = cookieKey + '=foobared; expires=' + cookieExpires.toUTCString() + ';path=/;'; 43 | var user = dtCookie.getIdentityCookieJSON(cookieKey); 44 | // we should have generated a new value 45 | expect(user.id).not.toBe(null); 46 | expect(user.version).toBe(2); 47 | expect(user.producer).toBe(configGeneral.cookie.producer); 48 | expect(user.privacy.optout).toBe(false); 49 | }); 50 | it('DigiTrustCookie.optoutCookieValue()', function () { 51 | var identity = dtCookie.unobfuscateCookieValue 52 | ('eyJpZCI6bnVsbCwia2V5diI6MCwicHJpdmFjeSI6eyJvcHRvdXQiOnRydWV9fQ%3D%3D'); 53 | expect(identity).toEqual({ id: null, keyv: 0, privacy: { optout: true } }); 54 | }); 55 | it('DigiTrustCookie.verifyPublisherDomainCookie()', function () { 56 | expect(dtCookie.verifyPublisherDomainCookie({})).toBe(false); 57 | expect(dtCookie.verifyPublisherDomainCookie({ id: 'abc' })).toBe(false); 58 | expect(dtCookie.verifyPublisherDomainCookie({ 59 | id: 'abc', version: 2, 60 | privacy: { optout: false } 61 | })).toBe(false); 62 | expect(dtCookie.verifyPublisherDomainCookie({ 63 | id: 'abc', version: 2, 64 | keyv: 4, privacy: { optout: false } 65 | })).toBe(true); 66 | }); 67 | }); 68 | 69 | describe('DigiTrustCookie', function () { 70 | 71 | beforeAll(function (done) { 72 | document.cookie = configGeneral.cookie.publisher.userObjectKey 73 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 74 | document.cookie = configGeneral.cookie.digitrust.userObjectKey 75 | + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; 76 | 77 | DigiTrust.initialize( 78 | { 79 | member: 'foo', 80 | consent: { 81 | requires: 'none' 82 | } 83 | }, 84 | function (identityResponse) { 85 | done(); 86 | } 87 | ) 88 | }); 89 | 90 | 91 | it('DigiTrustCookie.createUserCookiesOnDigitrustDomain()', function () { 92 | var identity = DigiTrustCookie.createUserCookiesOnDigitrustDomain(); 93 | expect(identity.id).not.toBe(null); 94 | expect(identity.version).toBe(2); 95 | expect(identity.producer).toBe(configGeneral.cookie.producer); 96 | expect(identity.privacy.optout).toBe(false); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /test/unit/helpersSpec.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var DigiTrust = require('../../src/modules/DigiTrust'); 4 | window.DigiTrust = DigiTrust; 5 | var helpers = require('../../src/modules/helpers'); 6 | var env = require('../../src/config/env.json').current; 7 | 8 | 9 | describe('helpers', function () { 10 | 11 | it('getAbsolutePath', function () { 12 | 13 | /* 14 | Since this runs in phantom, the base url should be: http://localhost:9876/ 15 | The index page is: http://localhost:9876/context.html 16 | */ 17 | 18 | expect(helpers.getAbsolutePath('http://example.com')).toBe('http://example.com/'); 19 | expect(helpers.getAbsolutePath('https://www.exmaple.com')).toBe('https://www.exmaple.com/'); 20 | expect(helpers.getAbsolutePath('//cdn.example.com/lib.js')).toBe('http://cdn.example.com/lib.js'); 21 | expect(helpers.getAbsolutePath('/test')).toBe('http://localhost:9876/test'); 22 | expect(helpers.getAbsolutePath('test')).toBe('http://localhost:9876/test'); 23 | expect(helpers.getAbsolutePath('#test')).toBe('http://localhost:9876/context.html#test'); 24 | expect(helpers.getAbsolutePath('../test')).toBe('http://localhost:9876/test'); 25 | }); 26 | 27 | it('generateUserId', function () { 28 | // generate an id 29 | var id = helpers.generateUserId(); 30 | expect(id).toBeDefined(); 31 | var binaryId = helpers.base64StringToArrayBuffer(id); 32 | expect(binaryId).not.toBe(null); 33 | expect(binaryId.byteLength).toBe(8); 34 | var a = new Uint8Array(binaryId); 35 | expect(a.length).toBe(8); 36 | // don't blame me that reduce() is not available in PhantomJS 37 | var total = 0; 38 | for (var i = 0; i < a.length; ++i) { 39 | total += a[i]; 40 | } 41 | expect(total).not.toBe(0); 42 | // convert back to base64 string 43 | expect(id).toBe(helpers.arrayBufferToBase64String(binaryId)); 44 | }); 45 | }); 46 | --------------------------------------------------------------------------------