Skip to content

Commit 9a877cc

Browse files
create working example using js sdk on server
1 parent 027c048 commit 9a877cc

File tree

15 files changed

+760
-7
lines changed

15 files changed

+760
-7
lines changed

docker-compose.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ services:
2020
env_file:
2121
- .env
2222

23+
javascript-sdk-server-side:
24+
build:
25+
context: .
26+
dockerfile: web-integrations/javascript-sdk/server-side/Dockerfile
27+
ports:
28+
- "3034:3034"
29+
container_name: javascript-sdk-server-side
30+
env_file:
31+
- .env
32+
2333
# server-side integration (no SDK)
2434
server-side:
2535
build:
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Dependencies
2+
node_modules/
3+
package-lock.json
4+
5+
# Logs
6+
npm-debug.log*
7+
yarn-debug.log*
8+
yarn-error.log*
9+
10+
# Environment variables
11+
.env
12+
.env.local
13+
.env.*.local
14+
15+
# OS files
16+
.DS_Store
17+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM node:20.11.0-alpine3.18
2+
3+
WORKDIR /usr/src/app
4+
5+
# Copy package files first for better caching
6+
COPY web-integrations/javascript-sdk/server-side/package*.json ./
7+
RUN npm install
8+
9+
# Copy application files
10+
COPY web-integrations/javascript-sdk/server-side/server.js ./
11+
COPY web-integrations/javascript-sdk/server-side/public ./public/
12+
COPY web-integrations/javascript-sdk/server-side/views ./views/
13+
14+
ENV PORT=3034
15+
EXPOSE 3034
16+
CMD ["npm", "start"]
17+
Lines changed: 177 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,186 @@
1-
# UID2 JavaScript SDK Server-Side Integration Example
1+
# Server-Side UID2 or EUID Integration Example using JavaScript SDK
22

3-
This example demonstrates a server-side Node.js implementation using the UID2 JavaScript SDK.
3+
This example demonstrates how a content publisher can use either the UID2 or EUID services and the JavaScript SDK on the server side to implement the server-side integration workflow.
44

5-
## Overview
5+
- For UID2: [UID2 services](https://unifiedid.com/docs/intro), [server-side UID2 integration workflow](https://unifiedid.com/docs/guides/integration-publisher-server-side)
6+
- For EUID: [EUID services](https://euid.eu/docs/intro), [server-side EUID integration workflow](https://euid.eu/docs/guides/integration-publisher-server-side)
67

7-
Coming soon...
8+
This example can be configured for either UID2 or EUID — the behavior is determined by your environment variable configuration. You cannot use both simultaneously.
9+
10+
## Key Difference from Other Examples
11+
12+
This example proves that the UID2/EUID **JavaScript SDK works in Node.js** server environments. It uses the same `setIdentityFromEmail` method that runs in browsers, but executes it on the server.
13+
14+
**Important:** This uses **public credentials** (Subscription ID + Server Public Key) which are the same credentials used for client-side integrations. This demonstrates that the client-side SDK is fully compatible with Node.js.
15+
16+
### Comparison with Other Examples
17+
18+
| Example | Environment | Credentials | SDK Usage | Notes |
19+
|---------|-------------|-------------|-----------|-------|
20+
| [server-side](../../server-side/) | Server only | API Key + Secret | No SDK | Manual encryption/decryption |
21+
| [client-server](../client-server/) | Hybrid | API Key + Secret (server)<br/>None (client) | Client SDK only | Server generates, client maintains |
22+
| [client-side](../client-side/) | Client only | Public Key + Subscription ID | Client SDK | Fully client-side |
23+
| **This example** | **Server only** | **Public Key + Subscription ID** | **Client SDK on server** | **Proves SDK works in Node.js** |
24+
25+
> **Note:** While the server side of the example application is implemented in JavaScript using Node.js, it is not a requirement. You can use any technology of your choice and refer to the example application for illustration of the functionality that needs to be implemented.
826
927
## Prerequisites
1028

11-
Coming soon...
29+
- Node.js 20.x or higher
30+
- UID2/EUID API Key and Client Secret (for server-side integration)
31+
- Access to UID2 or EUID integration environment
32+
33+
## Build and Run the Example Application
34+
35+
### Using Docker Compose (Recommended)
36+
37+
From the repository root directory:
38+
39+
```bash
40+
# Start the service
41+
docker compose up javascript-sdk-server-side
42+
```
43+
44+
The application will be available at http://localhost:3034
45+
46+
To view logs or stop the service:
47+
48+
```bash
49+
# View logs (in another terminal)
50+
docker compose logs javascript-sdk-server-side
51+
52+
# Stop the service
53+
docker compose stop javascript-sdk-server-side
54+
```
55+
56+
### Using Docker Build
57+
58+
```bash
59+
# Build the image
60+
docker build -f web-integrations/javascript-sdk/server-side/Dockerfile -t javascript-sdk-server-side .
61+
62+
# Run the container
63+
docker run -it --rm -p 3034:3034 --env-file .env javascript-sdk-server-side
64+
```
65+
66+
### Using npm (Local Development)
67+
68+
```bash
69+
# Navigate to this directory
70+
cd web-integrations/javascript-sdk/server-side
71+
72+
# Install dependencies
73+
npm install
74+
75+
# Start the server (requires .env file in repository root)
76+
npm start
77+
```
78+
79+
## Configuration
80+
81+
The following table lists the environment variables that you must specify to start the application.
82+
83+
### Core Configuration
84+
85+
| Variable | Description | Example Values |
86+
|:---------|:------------|:---------------|
87+
| `UID_SERVER_BASE_URL` | The base URL of the UID2/EUID service. For details, see [Environments](https://unifiedid.com/docs/getting-started/gs-environments) (UID2) or [Environments](https://euid.eu/docs/getting-started/gs-environments) (EUID). | UID2: `https://operator-integ.uidapi.com`<br/>EUID: `https://integ.euid.eu/v2` |
88+
| `UID_CSTG_SUBSCRIPTION_ID` | Your UID2/EUID subscription ID for Client-Side Token Generation. **These are public credentials.** | Your assigned subscription ID (e.g., `DMr7uHxqLU`) |
89+
| `UID_CSTG_SERVER_PUBLIC_KEY` | Your UID2/EUID server public key for Client-Side Token Generation. **These are public credentials.** | Your assigned public key |
90+
| `SESSION_KEY` | The key to encrypt session data stored in the application session cookie. This can be any arbitrary string. | Any secure random string |
91+
92+
### Display/UI Configuration
93+
94+
| Variable | Description | Example Values |
95+
|:---------|:------------|:---------------|
96+
| `IDENTITY_NAME` | Identity name for UI display | UID2: `UID2`<br/>EUID: `EUID` |
97+
| `DOCS_BASE_URL` | Documentation base URL | UID2: `https://unifiedid.com/docs`<br/>EUID: `https://euid.eu/docs` |
98+
99+
After you see output similar to the following, the example application is up and running:
100+
101+
```
102+
Server-Side UID2/EUID Integration Example using JavaScript SDK
103+
Listening at http://localhost:3034
104+
105+
Note: SDK integration is not yet complete.
106+
TODO: Add UID2/EUID JavaScript SDK package and implement token generation/refresh.
107+
```
108+
109+
If needed, to close the application, terminate the docker container or use the `Ctrl+C` keyboard shortcut.
110+
111+
## Test the Example Application
112+
113+
The example application illustrates the steps documented in the server-side integration guides:
114+
- UID2: [Server-Side Integration Guide](https://unifiedid.com/docs/guides/integration-publisher-server-side)
115+
- EUID: [Server-Side Integration Guide](https://euid.eu/docs/guides/integration-publisher-server-side)
116+
117+
**Note:** For API endpoint documentation, see the UID2 or EUID docs based on your configuration.
118+
119+
The application provides three main pages: index (main), example content 1, and example content 2. Access to these pages is possible only after the user completes the login process. If the user is not logged in, they will be redirected to the login page.
120+
121+
Submitting the login form simulates logging in to a publisher's application in the real world. Normally the login would require checking the user's secure credentials (for example, a password), but for demonstration purposes this step is omitted, and the login process focuses on integration with the UID2/EUID services using the JavaScript SDK on the server.
122+
123+
The following table outlines and annotates the steps you may take to test and explore the example application.
124+
125+
| Step | Description | Comments |
126+
|:----:|:------------|:---------|
127+
| 1 | In your browser, navigate to the application main page at `http://localhost:3034`. | The displayed main (index) page of the example application provides a [login form](views/login.html) for the user to complete the UID2/EUID login process.</br>IMPORTANT: A real-life application must also display a form for the user to express their consent to targeted advertising. |
128+
| 2 | Enter the user email address that you want to use for testing and click **Log In**. | This is a call to the `/login` endpoint ([server.js](server.js)). The login initiated on the server side uses the JavaScript SDK's `setIdentityFromEmail` method to generate a token and processes the received response. The SDK handles all encryption/decryption automatically, just as it does in the browser. |
129+
| | The main page is updated to display links to the two pages with protected content and the established identity information. | The displayed identity information is the `body` property of the response from the SDK's `setIdentityFromEmail` call. If the response is successful, the returned identity is saved to a session cookie (a real-world application would use a different way to store session data) and the protected index page is rendered. |
130+
| 3 | Click either of the two sample content pages. | When the user requests the index or content pages, the server reads the user session and extracts the current identity ([server.js](server.js)). The `advertising_token` on the identity can be used for targeted advertising. |
131+
| 4 | Click the **Back to the main page** link. | Note that the identity contains several timestamps that determine when the advertising token becomes invalid (`identity_expires`) and when the server should attempt to refresh it (`refresh_from`). Every time a protected page is requested, the `verifyIdentity` function ([server.js](server.js)) uses the SDK to refresh the token as needed.<br/>The user is automatically logged out in the following cases:<br/>- If the identity expires without being refreshed and refresh attempt fails.<br/>- If the refresh token expires.<br/>- If the refresh attempt indicates that the user has opted out. |
132+
| 5 | To exit the application, click **Log Out**. | This calls the `/logout` endpoint on the server ([server.js](server.js)), which clears the session and the first-party cookie and presents the user with the login form again.<br/> NOTE: The page displays the **Log Out** button as long as the user is logged in. |
133+
134+
## Implementation Status
135+
136+
> **⚠️ Important:** This example is currently in initial development. The JavaScript SDK integration is not yet complete.
137+
138+
### TODO
139+
140+
- [ ] Identify the correct way to import/use the JavaScript SDK in Node.js (it's designed for browsers but should work with proper setup)
141+
- [ ] Implement `setIdentityFromEmail` call in the `/login` endpoint using public credentials
142+
- [ ] Handle SDK callbacks/promises properly in the Node.js environment
143+
- [ ] Add error handling for SDK operations
144+
- [ ] Test that the generated identity matches what the client-side example produces
145+
- [ ] Update documentation with actual SDK API usage once working
146+
- [ ] Add to docker-compose.yml in repository root
147+
148+
## Development Notes
149+
150+
This example demonstrates that the browser-based JavaScript SDK can run in Node.js. It uses the same public credentials and methods as the client-side example:
151+
152+
**Client-Side (Browser):**
153+
```javascript
154+
// In browser
155+
const sdk = window.__uid2;
156+
await sdk.setIdentityFromEmail(email, {
157+
subscriptionId: 'DMr7uHxqLU',
158+
serverPublicKey: 'UID2-X-I-MFk...'
159+
});
160+
```
161+
162+
**This Example (Node.js Server):**
163+
```javascript
164+
// Same code, but running on Node.js server
165+
const sdk = getUid2Sdk(); // Need to figure out proper import
166+
await sdk.setIdentityFromEmail(email, {
167+
subscriptionId: process.env.UID_CSTG_SUBSCRIPTION_ID,
168+
serverPublicKey: process.env.UID_CSTG_SERVER_PUBLIC_KEY
169+
});
170+
```
171+
172+
The key challenge is figuring out how to properly import/initialize the SDK in a Node.js environment since it's primarily designed for browsers.
173+
174+
## Contributing
175+
176+
When implementing the SDK integration, ensure:
12177

13-
## Running the Example
178+
1. The SDK is properly initialized with API key and client secret
179+
2. Error handling matches the existing server-side example behavior
180+
3. Session management remains unchanged
181+
4. The user experience is identical to the manual crypto version
182+
5. All environment variables are properly documented
14183

15-
Coming soon...
184+
## License
16185

186+
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "uid2-javascript-sdk-server-side",
3+
"version": "1.0.0",
4+
"description": "Server-Side UID2/EUID Integration Example using JavaScript SDK",
5+
"main": "server.js",
6+
"scripts": {
7+
"start": "node server.js",
8+
"dev": "nodemon server.js"
9+
},
10+
"keywords": [
11+
"uid2",
12+
"euid",
13+
"identity",
14+
"server-side"
15+
],
16+
"author": "",
17+
"license": "Apache-2.0",
18+
"dependencies": {
19+
"axios": "^1.6.0",
20+
"cookie-session": "^2.0.0",
21+
"dotenv": "^16.0.3",
22+
"ejs": "^3.1.9",
23+
"express": "^4.18.2",
24+
"jsdom": "^23.0.0",
25+
"nocache": "^4.0.0"
26+
},
27+
"devDependencies": {
28+
"nodemon": "^3.0.1"
29+
}
30+
}
31+
1.93 KB
Loading
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
body {
2+
padding: 50px;
3+
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
4+
}
5+
6+
a {
7+
color: #00B7FF;
8+
}
9+
10+
.button {
11+
border-style: none;
12+
cursor: pointer;
13+
align-items: center;
14+
height: 40px;
15+
width: 401px;
16+
text-align: center;
17+
position: absolute;
18+
letter-spacing: 0.28px;
19+
box-sizing: border-box;
20+
color: white;
21+
font-family: 'Raleway', Helvetica, Arial, serif;
22+
font-size: 14px;
23+
font-style: normal;
24+
font-weight: 700;
25+
text-transform: none;
26+
text-indent: 0px;
27+
text-shadow: none;
28+
margin: 0em;
29+
padding: 1px 6px;
30+
background-color: rgba(2,10,64,1.0);
31+
border-image: initial
32+
}
33+
34+
.form {
35+
margin-top: 40px;
36+
}
37+
38+
.email_prompt {
39+
align-items: center;
40+
align-self: center;
41+
background-color: white;
42+
border: 1px solid rgba(2,10,64,1.0);
43+
border-radius: 2px;
44+
box-sizing: border-box;
45+
display: inline-flex;
46+
flex-direction: row;
47+
flex-shrink: 0;
48+
height: 40px;
49+
justify-content: flex-start;
50+
margin-right: 1.0px;
51+
margin-bottom: 20px;
52+
min-width: 399px;
53+
padding: 0 16.0px;
54+
position: relative;
55+
width: auto;
56+
}
57+
58+
#email {
59+
background-color: white;
60+
flex-shrink: 0;
61+
height: auto;
62+
letter-spacing: 0.12px;
63+
line-height: 16px;
64+
min-height: 16px;
65+
position: relative;
66+
text-align: left;
67+
white-space: nowrap;
68+
width: 351px;
69+
color: rgba(2,10,64,1.0);
70+
font-family: 'Raleway', Helvetica, Arial, serif;
71+
font-size: 12px;
72+
font-style: normal;
73+
font-weight: 500;
74+
padding: 1px 2px;
75+
outline: none;
76+
}
77+
78+
h1 {
79+
padding-bottom: 20px;
80+
}
81+
82+
#uid2_state .label {
83+
white-space: nowrap;
84+
padding-right: 20px;
85+
}
86+
#uid2_state tr {
87+
margin-top: 10px;
88+
}
89+
90+
.message {
91+
color: green;
92+
padding: 20px;
93+
margin-left: -22px;
94+
font-size: 16px;
95+
font-weight: 500;
96+
border: 2px solid green;
97+
border-radius: 5px;
98+
}
99+

0 commit comments

Comments
 (0)