Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype: Get ECID from kndctr cookie #1171

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions kndctr.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// From https://git.corp.adobe.com/pages/experience-edge/konductor/#/api/identifying-visitors?id=device-identifiers

syntax = "proto3";

// Device-level identity for Experience Edge
message Identity {
// The Experience Cloud ID value
string ecid = 1;

IdentityMetadata metadata = 10;

// Used only in the 3rd party domain context.
// It stores the UNIX timestamp and some metadata about the last identity sync triggered by Experience Edge.
int64 last_sync = 20;
int64 sync_hash = 21;
int32 id_sync_container_id = 22;

// UNIX timestamp when the Identity was last returned in a `state:store` instruction.
// The Identity is written at most once every 24h with a large TTL, to ensure it does not expire.
int64 write_time = 30;
}

message IdentityMetadata {
// UNIX timestamp when this identity was minted.
int64 created_at = 1;

// Whether or not the identity is random (new) or based on an existing seed.
bool is_new = 2;

// Type of device for which the identity was generated.
// 0 = UNKNOWN, 1 = BROWSER, 2 = MOBILE
int32 device_type = 3;

// The Experience Edge region in which the identity was minted.
string region = 5;

// More details on the source of the ECID identity.
// Invariant: when `is_new` = true, the source must be set to `RANDOM`.
// 0 = RANDOM, 1 = THIRD_PARTY_ID, 2 = FIRST_PARTY_ID, 3 = RECEIVED_IN_REQUEST
int32 source = 6;
}
83 changes: 83 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"inquirer": "^10.1.8",
"js-cookie": "3.0.5",
"parse-uri": "^1.0.9",
"protobufjs": "^7.3.3",
"rollup": "^4.21.0",
"rollup-plugin-license": "^3.5.2",
"uuid": "^10.0.0"
Expand Down
6 changes: 6 additions & 0 deletions src/components/Identity/createComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default ({
setLegacyEcid,
handleResponseForIdSyncs,
getEcidFromResponse,
getEcidFromCookie,
getIdentity,
consent,
appendIdentityToUrl,
Expand Down Expand Up @@ -71,6 +72,11 @@ export default ({
});
},
},
getEcidFromCookie: {
run() {
return getEcidFromCookie();
},
},
appendIdentityToUrl: {
optionsValidator: appendIdentityToUrlOptionsValidator,
run: (options) => {
Expand Down
42 changes: 42 additions & 0 deletions src/components/Identity/createGetEcidFromCookie.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright 2024 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import { Identity } from "../../utils/identityProtobuf.js";
import { getNamespacedCookieName } from "../../utils/index.js";

const base64ToBytes = (base64) => {
const binString = atob(base64);
return Uint8Array.from(binString, (m) => m.codePointAt(0));
};

export default ({ config, cookieJar }) => {
const { orgId } = config;
const kndctrCookieName = getNamespacedCookieName(orgId, "kndctr");
/**
* Returns the ECID from the kndctr cookie.
* @returns {string|null}
*/
return () => {
const cookie = cookieJar.get(kndctrCookieName);
if (!cookie) {
return null;
}
const decodedCookie = decodeURIComponent(cookie)
.replace(/_/g, "/")
.replace(/-/g, "+");
// cookie is a base64 encoded byte representation of a Identity protobuf message
// and we need to get it to a Uint8Array in order to decode it

const cookieBytes = base64ToBytes(decodedCookie);
const message = Identity.decode(cookieBytes);
return message.ecid;
};
};
6 changes: 6 additions & 0 deletions src/components/Identity/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import createGetIdentity from "./getIdentity/createGetIdentity.js";
import createIdentityRequest from "./getIdentity/createIdentityRequest.js";
import createIdentityRequestPayload from "./getIdentity/createIdentityRequestPayload.js";
import injectAppendIdentityToUrl from "./appendIdentityToUrl/injectAppendIdentityToUrl.js";
import createGetEcidFromCookie from "./createGetEcidFromCookie.js";

const createIdentity = ({
config,
Expand Down Expand Up @@ -65,6 +66,10 @@ const createIdentity = ({
cookieJar: loggingCookieJar,
isPageSsl: window.location.protocol === "https:",
});
const getEcidFromCookie = createGetEcidFromCookie({
config,
cookieJar,
});
const doesIdentityCookieExist = injectDoesIdentityCookieExist({ orgId });
const getIdentity = createGetIdentity({
sendEdgeNetworkRequest,
Expand Down Expand Up @@ -118,6 +123,7 @@ const createIdentity = ({
return createComponent({
addEcidQueryToPayload,
addQueryStringIdentityToPayload,
getEcidFromCookie,
ensureSingleIdentity,
setLegacyEcid: legacyIdentity.setEcid,
handleResponseForIdSyncs,
Expand Down
Loading
Loading