├── .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 | Opt me OUT
7 | Opt me IN
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 | Opt me OUT
7 | Opt me IN
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 |
--------------------------------------------------------------------------------