@phygitallabs/phygital-consent 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,29 +1,33 @@
1
1
  /**
2
2
  * Hash user_id or device_id with SHA-256 for the two POST consent hooks
3
3
  * (createUserConsent, createDeviceCookieConsent).
4
+ * Input: string, encoded as UTF-8 before hashing.
5
+ * Output: lowercase hex string.
4
6
  * Uses Web Crypto when available; falls back to pure-JS SHA-256 for old devices.
5
- * Returns lowercase hex string.
6
7
  */
7
8
 
9
+ /** Encode hash digest bytes as lowercase hex string. */
8
10
  function arrayBufferToHex(buffer: ArrayBuffer): string {
9
11
  return Array.from(new Uint8Array(buffer))
10
12
  .map((b) => b.toString(16).padStart(2, "0"))
11
- .join("");
13
+ .join("")
14
+ .toLowerCase();
12
15
  }
13
16
 
14
17
  /**
15
18
  * SHA-256 via Web Crypto (modern browsers, Node 19+).
19
+ * Input encoded as UTF-8; output lowercase hex.
16
20
  */
17
21
  async function sha256WebCrypto(value: string): Promise<string> {
18
- const buffer = new TextEncoder().encode(value);
19
- const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
22
+ const utf8 = new TextEncoder().encode(value);
23
+ const hashBuffer = await crypto.subtle.digest("SHA-256", utf8);
20
24
  return arrayBufferToHex(hashBuffer);
21
25
  }
22
26
 
23
27
  /**
24
28
  * Pure-JS SHA-256 fallback for environments without crypto.subtle
25
29
  * (e.g. old browsers, insecure context, Node < 19).
26
- * UTF-8 input, hex output.
30
+ * Input encoded as UTF-8; output lowercase hex.
27
31
  */
28
32
  function sha256Fallback(value: string): string {
29
33
  const bytes = utf8Encode(value);
@@ -94,13 +98,14 @@ function sha256Fallback(value: string): string {
94
98
  ((v >>> 4) & 0xf).toString(16) +
95
99
  (v & 0xf).toString(16);
96
100
  }
97
- return out;
101
+ return out.toLowerCase();
98
102
  }
99
103
 
100
104
  function rotr(n: number, b: number): number {
101
105
  return (n >>> b) | (n << (32 - b));
102
106
  }
103
107
 
108
+ /** Encode string to UTF-8 bytes (with SHA-256 padding for block processing). */
104
109
  function utf8Encode(s: string): Uint8Array {
105
110
  const n = s.length;
106
111
  const bytes: number[] = [];
@@ -155,7 +160,8 @@ function hasWebCrypto(): boolean {
155
160
  }
156
161
 
157
162
  /**
158
- * Hash a string with SHA-256. Returns lowercase hex string.
163
+ * Hash a string with SHA-256.
164
+ * Input: encoded as UTF-8. Output: lowercase hex string.
159
165
  * Use for user_id and device_id before calling createUserConsent / createDeviceCookieConsent.
160
166
  * Uses Web Crypto when available; falls back to pure-JS for old devices (no crypto.subtle).
161
167
  */
@@ -5,6 +5,7 @@ import { getConsentPreferenceCookie } from "../helpers/cookie";
5
5
  import { ConsentServiceProvider, ConsentServiceProviderProps } from "./ConsentServiceProvider";
6
6
 
7
7
  export interface PhygitalConsentContextValue {
8
+ deviceId: string;
8
9
  /** True when cookie phygital_cookie_consent exists and has valid deviceId + selected_preferences. Use to show/hide cookie banner. */
9
10
  hasConsentPreference: boolean;
10
11
  /** Re-read cookie and update hasConsentPreference. Call after storing preference (e.g. from CookieConsentBanner onSuccess). */
@@ -14,6 +15,7 @@ export interface PhygitalConsentContextValue {
14
15
  const PhygitalConsentContext = createContext<PhygitalConsentContextValue | undefined>(undefined);
15
16
 
16
17
  export interface PhygitalConsentProviderProps extends ConsentServiceProviderProps {
18
+ deviceId: string;
17
19
  children: React.ReactNode;
18
20
  }
19
21
 
@@ -23,7 +25,7 @@ export interface PhygitalConsentProviderProps extends ConsentServiceProviderProp
23
25
  * the cookie banner based on whether the user has already chosen a preference.
24
26
  */
25
27
  export function PhygitalConsentProvider(props: PhygitalConsentProviderProps) {
26
- const { children, ...consentServiceProps } = props;
28
+ const { children, deviceId, ...consentServiceProps } = props;
27
29
  const [hasConsentPreference, setHasConsentPreference] = useState(false);
28
30
 
29
31
  const refreshConsentPreference = useCallback(() => {
@@ -34,8 +36,9 @@ export function PhygitalConsentProvider(props: PhygitalConsentProviderProps) {
34
36
  useEffect(() => {
35
37
  refreshConsentPreference();
36
38
  }, [refreshConsentPreference]);
37
-
39
+
38
40
  const value: PhygitalConsentContextValue = {
41
+ deviceId,
39
42
  hasConsentPreference,
40
43
  refreshConsentPreference,
41
44
  };