@trimble-oss/trimble-id-react 1.0.1 → 1.0.2-rc1

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.
package/README.md CHANGED
@@ -67,7 +67,7 @@ process related to the authentication for you. Configure the SDK by wrapping you
67
67
 
68
68
  Here TIDProvider can take two parameters :
69
69
  * **tidClient** : TID client instance. You can send an instance of the TID Client if you want to handle the initialization yourself
70
- * **onRedirectCallback** - When the redirect callback occur this function will be call once the user is login using the TIDClient. This function receives an `authState` parameter that contains a `redirectTo` property with the user's original location before authentication, allowing you to redirect the user back to their intended destination after login.
70
+ * **onRedirectCallback** - When the redirect callback occur this function will be call once the user is login using the TIDClient. This function receives an `authState` parameter that contains a `returnTo` property with the user's original location before authentication, allowing you to redirect the user back to their intended destination after login.
71
71
 
72
72
 
73
73
  After wrapping your app with the TIDProvider, you have to configure the TID credentials registered in TrimbleCloud console. There are two ways of doing this:
@@ -103,9 +103,9 @@ After wrapping your app with the TIDProvider, you have to configure the TID cred
103
103
  ```
104
104
 
105
105
  ```tsx
106
- const handleRedirect = (authState) => {
107
- // Use redirectTo for automatic redirection to original location
108
- const redirectTo = authState.redirectTo || '/dashboard'
106
+ const handleRedirect = (authState: AuthState) => {
107
+ // Use returnTo for automatic redirection to original location
108
+ const redirectTo = authState.returnTo || '/dashboard'
109
109
  // Navigate to the intended destination
110
110
  navigate(redirectTo)
111
111
  }
@@ -150,8 +150,8 @@ const { handleCallback } = useAuth()
150
150
  // Handle callback and get redirect information
151
151
  const authState = await handleCallback()
152
152
 
153
- // Use redirectTo for automatic redirection to original location
154
- const redirectTo = authState.redirectTo || '/dashboard'
153
+ // Use returnTo for automatic redirection to original location
154
+ const redirectTo = authState.returnTo || '/dashboard'
155
155
  navigate(redirectTo)
156
156
  ```
157
157
 
@@ -90,11 +90,6 @@ export declare class TIDClient {
90
90
  * @type {string}
91
91
  */
92
92
  private readonly redirectUrl;
93
- /**
94
- * AnalyticsHttpClient for sending events
95
- * @type {AnalyticsHttpClient}
96
- */
97
- private readonly analyticshttpclient;
98
93
  /**
99
94
  * Create a TID client to handle manage all user authentication functions and information
100
95
  * @param {CacheManagerOptions} props - TID client configuration
@@ -51,6 +51,8 @@ export interface TIDUser {
51
51
  email?: string;
52
52
  /** True if the End-User's e-mail address has been verified; otherwise false. */
53
53
  email_verified?: boolean;
54
+ /** Account id of the user */
55
+ account_id?: string;
54
56
  }
55
57
  export interface TIDJWTUser {
56
58
  /**
@@ -172,6 +174,11 @@ export interface TIDJWTUser {
172
174
  * @type {string}
173
175
  */
174
176
  data_region: string;
177
+ /**
178
+ * Account id of the user
179
+ * @type {string}
180
+ */
181
+ account_id: string;
175
182
  }
176
183
  export interface AuthState {
177
184
  authState: any;
@@ -1,75 +1,70 @@
1
- var $ = Object.defineProperty;
2
- var B = (i, e, t) => e in i ? $(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
3
- var l = (i, e, t) => (B(i, typeof e != "symbol" ? e + "" : e, t), t);
4
- import { OpenIdEndpointProvider as J, AuthorizationCodeGrantTokenProvider as R, AnalyticsHttpClient as H, BearerTokenHttpClientProvider as Q } from "@trimble-oss/trimble-id";
5
- import * as T from "es-cookie";
6
- import X from "jwt-decode";
7
- import { createContext as q, useContext as L, useState as z, useReducer as Y, useRef as Z, useMemo as M, useEffect as N, useCallback as m } from "react";
8
- import { jsx as V, Fragment as j } from "react/jsx-runtime";
9
- class ee {
10
- constructor() {
11
- /**
12
- * This function generate a encapsulation function to store
13
- * the user and token information in a secure way disabled the
14
- * access from the outside
15
- * @see {https://medium.com/javascript-scene/encapsulation-in-javascript-26be60e325b4} Encapsulation
16
- * @return {CacheStorage} Key for the token
17
- */
18
- l(this, "generateCache", function() {
19
- const e = {
20
- token: void 0,
21
- user: void 0
22
- };
23
- return {
24
- /**
25
- * Get token store in cache
26
- * @return {Promise<TIDAuthToken | undefined>} Token store in memory
27
- */
28
- async getToken() {
29
- return e.token;
30
- },
31
- /**
32
- * Get user store in cache
33
- * @return {Promise<TIDUser | undefined>} User store in memory
34
- */
35
- async getUser() {
36
- return e.user;
37
- },
38
- /**
39
- * Store token in cache
40
- * @param {TIDAuthToken} token - Token that you want to store in cache
41
- * @return {Promise<void>} Empty promise
42
- */
43
- async storeToken(t) {
44
- e.token = t;
45
- },
46
- /**
47
- * Store user in cache
48
- * @param {TIDUser} user - User that you want to store in cache
49
- * @return {Promise<void>} Empty promise
50
- */
51
- async storeUser(t) {
52
- e.user = t;
53
- },
54
- /**
55
- * The clear the cache from the storage
56
- * @return {Promise<void>} Empty promise
57
- */
58
- clear() {
59
- return e.token = void 0, e.user = void 0, Promise.resolve(void 0);
60
- }
61
- };
62
- }());
63
- }
1
+ import { OpenIdEndpointProvider as $, AuthorizationCodeGrantTokenProvider as R, AnalyticsHttpClient as h, BearerTokenHttpClientProvider as B } from "@trimble-oss/trimble-id";
2
+ import * as m from "es-cookie";
3
+ import J from "jwt-decode";
4
+ import { createContext as H, useContext as L, useState as Q, useReducer as X, useRef as q, useMemo as M, useEffect as N, useCallback as y } from "react";
5
+ import { jsx as V, Fragment as z } from "react/jsx-runtime";
6
+ class Y {
7
+ /**
8
+ * This function generate a encapsulation function to store
9
+ * the user and token information in a secure way disabled the
10
+ * access from the outside
11
+ * @see {https://medium.com/javascript-scene/encapsulation-in-javascript-26be60e325b4} Encapsulation
12
+ * @return {CacheStorage} Key for the token
13
+ */
14
+ generateCache = /* @__PURE__ */ (function() {
15
+ const e = {
16
+ token: void 0,
17
+ user: void 0
18
+ };
19
+ return {
20
+ /**
21
+ * Get token store in cache
22
+ * @return {Promise<TIDAuthToken | undefined>} Token store in memory
23
+ */
24
+ async getToken() {
25
+ return e.token;
26
+ },
27
+ /**
28
+ * Get user store in cache
29
+ * @return {Promise<TIDUser | undefined>} User store in memory
30
+ */
31
+ async getUser() {
32
+ return e.user;
33
+ },
34
+ /**
35
+ * Store token in cache
36
+ * @param {TIDAuthToken} token - Token that you want to store in cache
37
+ * @return {Promise<void>} Empty promise
38
+ */
39
+ async storeToken(t) {
40
+ e.token = t;
41
+ },
42
+ /**
43
+ * Store user in cache
44
+ * @param {TIDUser} user - User that you want to store in cache
45
+ * @return {Promise<void>} Empty promise
46
+ */
47
+ async storeUser(t) {
48
+ e.user = t;
49
+ },
50
+ /**
51
+ * The clear the cache from the storage
52
+ * @return {Promise<void>} Empty promise
53
+ */
54
+ clear() {
55
+ return e.token = void 0, e.user = void 0, Promise.resolve(void 0);
56
+ }
57
+ };
58
+ })();
64
59
  }
65
- class te {
60
+ class Z {
61
+ /**
62
+ * Cache option selected
63
+ * @type {CacheStorage}
64
+ */
65
+ cacheStorage;
66
66
  constructor() {
67
- /**
68
- * Cache option selected
69
- * @type {CacheStorage}
70
- */
71
- l(this, "cacheStorage");
72
- this.cacheStorage = new ee().generateCache;
67
+ this.cacheStorage = new Y().generateCache;
73
68
  }
74
69
  /**
75
70
  * Store token in cache
@@ -109,41 +104,42 @@ class te {
109
104
  await this.cacheStorage.clear();
110
105
  }
111
106
  }
112
- const x = 5 * 6e4, ie = ["code", "state"], A = 10 * 60 * 1e3, U = (i) => i.split("?")[0], re = (i) => i.split("?")[1], b = (i) => {
113
- let e = i;
114
- if (!i.startsWith("?"))
107
+ const x = 5 * 6e4, j = ["code", "state"], A = 600 * 1e3, U = (o) => o.split("?")[0], ee = (o) => o.split("?")[1], b = (o) => {
108
+ let e = o;
109
+ if (!o.startsWith("?"))
115
110
  try {
116
- e = new URL(i).search;
111
+ e = new URL(o).search;
117
112
  } catch {
118
113
  }
119
114
  return new URLSearchParams(e);
120
- }, ne = (i = window.location.href, e) => {
115
+ }, te = (o = window.location.href, e) => {
121
116
  if (e != null) {
122
- const r = U(e), n = U(i ?? "");
117
+ const r = U(e), n = U(o ?? "");
123
118
  if (r !== n)
124
119
  return !1;
125
120
  }
126
- const t = b(i);
127
- for (const r of ie)
121
+ const t = b(o);
122
+ for (const r of j)
128
123
  if (!t.has(r))
129
124
  return !1;
130
125
  return !0;
131
- }, ae = (i) => ({
132
- id: i.sub,
133
- name: `${i.given_name} ${i.family_name}`,
134
- given_name: i.given_name,
135
- family_name: i.family_name,
136
- picture: i.picture,
137
- email: i.email,
138
- email_verified: i.email_verified
139
- }), oe = "@TID_COOKIE";
140
- class se {
126
+ }, oe = (o) => ({
127
+ id: o.sub,
128
+ name: `${o.given_name} ${o.family_name}`,
129
+ given_name: o.given_name,
130
+ family_name: o.family_name,
131
+ picture: o.picture,
132
+ email: o.email,
133
+ email_verified: o.email_verified,
134
+ ...o.account_id && { account_id: o.account_id }
135
+ }), re = "@TID_COOKIE";
136
+ class ne {
141
137
  /**
142
138
  * Retrieve a cookie from the browser
143
139
  * @param {string} key - Key to retrieve the cookies
144
140
  */
145
141
  get(e) {
146
- const t = T.get(e);
142
+ const t = m.get(e);
147
143
  if (t == null)
148
144
  throw new Error("Cookie not found");
149
145
  return JSON.parse(t);
@@ -163,7 +159,7 @@ class se {
163
159
  window.location.protocol === "https:" && (n = {
164
160
  secure: !0,
165
161
  sameSite: "none"
166
- }), r != null && r.expires && (n.expires = r.expires), r != null && r.domain && (n.domain = r.domain), T.set(e, JSON.stringify(t), n);
162
+ }), r?.expires && (n.expires = r.expires), r?.domain && (n.domain = r.domain), m.set(e, JSON.stringify(t), n);
167
163
  }
168
164
  /**
169
165
  * Remove a cookie from the browser
@@ -176,26 +172,26 @@ class se {
176
172
  */
177
173
  remove(e, t) {
178
174
  const r = {};
179
- t != null && t.domain && (r.domain = t.domain), T.remove(e, r);
175
+ t?.domain && (r.domain = t.domain), m.remove(e, r);
180
176
  }
181
177
  }
182
- class ce {
178
+ class ie {
179
+ /**
180
+ * Cookie full key to store and retrieve the information from cookies
181
+ * @type {string}
182
+ */
183
+ cookieKey;
184
+ /**
185
+ * Cookie storage. This object contain all functions necessary to retrieve and store tokens using cookies
186
+ * @type {CookiesStorage}
187
+ */
188
+ cookiesStorage;
183
189
  /**
184
190
  * Create a cookies manager to extract or save cookies in the browser
185
191
  * @param {CookiesManagerOptions} options - Configuration for the managing the cookies
186
192
  */
187
193
  constructor(e) {
188
- /**
189
- * Cookie full key to store and retrieve the information from cookies
190
- * @type {string}
191
- */
192
- l(this, "cookieKey");
193
- /**
194
- * Cookie storage. This object contain all functions necessary to retrieve and store tokens using cookies
195
- * @type {CookiesStorage}
196
- */
197
- l(this, "cookiesStorage");
198
- this.cookieKey = `${oe}.${e.clientId}`, this.cookiesStorage = new se();
194
+ this.cookieKey = `${re}.${e.clientId}`, this.cookiesStorage = new ne();
199
195
  }
200
196
  /**
201
197
  * Store cookies in the browser
@@ -212,8 +208,7 @@ class ce {
212
208
  * @return {string | undefined} - State payload from cookies
213
209
  */
214
210
  getStatePayload() {
215
- const e = this.get();
216
- return e == null ? void 0 : e.state_payload;
211
+ return this.get()?.state_payload;
217
212
  }
218
213
  /**
219
214
  * Clear state payload from cookies
@@ -244,66 +239,61 @@ class O extends Error {
244
239
  }
245
240
  class D extends Error {
246
241
  }
247
- class le extends Error {
242
+ class ae extends Error {
248
243
  }
249
- const u = "@trimble-oss/trimble-id-react", g = "1.0.1", de = {
244
+ const u = "@trimble-oss/trimble-id-react", g = "1.0.2-rc1", se = {
250
245
  configurationEndpoint: "",
251
246
  clientId: "",
252
247
  redirectUrl: "",
253
248
  logoutRedirectUrl: "",
254
249
  scopes: []
255
250
  };
256
- class he {
251
+ class ce {
252
+ /**
253
+ * Token provider SDK. This object handles all necessary communication with TID
254
+ * @type {AuthorizationCodeGrantTokenProvider}
255
+ */
256
+ tokenProvider;
257
+ /**
258
+ * This object manage all caching, and all configurations necessary
259
+ * @type {CacheManager}
260
+ */
261
+ cacheManager;
262
+ /**
263
+ * This object manage all cookies administration, and all configurations necessary
264
+ * @type {CookiesManager}
265
+ */
266
+ cookiesManager;
267
+ /**
268
+ * Client id of the application created in trimble developer console
269
+ * @type {string}
270
+ */
271
+ clientId;
272
+ /**
273
+ * Callback url to redirect the user after the authentication is successful
274
+ * @type {string}
275
+ */
276
+ redirectUrl;
257
277
  /**
258
278
  * Create a TID client to handle manage all user authentication functions and information
259
279
  * @param {CacheManagerOptions} props - TID client configuration
260
280
  */
261
281
  constructor(e) {
262
- /**
263
- * Token provider SDK. This object handles all necessary communication with TID
264
- * @type {AuthorizationCodeGrantTokenProvider}
265
- */
266
- l(this, "tokenProvider");
267
- /**
268
- * This object manage all caching, and all configurations necessary
269
- * @type {CacheManager}
270
- */
271
- l(this, "cacheManager");
272
- /**
273
- * This object manage all cookies administration, and all configurations necessary
274
- * @type {CookiesManager}
275
- */
276
- l(this, "cookiesManager");
277
- /**
278
- * Client id of the application created in trimble developer console
279
- * @type {string}
280
- */
281
- l(this, "clientId");
282
- /**
283
- * Callback url to redirect the user after the authentication is successful
284
- * @type {string}
285
- */
286
- l(this, "redirectUrl");
287
- /**
288
- * AnalyticsHttpClient for sending events
289
- * @type {AnalyticsHttpClient}
290
- */
291
- l(this, "analyticshttpclient");
292
- const { config: t = de } = e;
282
+ const { config: t = se } = e;
293
283
  if (this.redirectUrl = t.redirectUrl, t.configurationEndpoint == null || t.configurationEndpoint == "")
294
284
  throw new Error("Configuration endpoint not defined");
295
285
  if (t.clientId == null || t.clientId == "")
296
286
  throw new Error("Consumer key is not defined");
297
- this.cookiesManager = new ce({
287
+ this.cookiesManager = new ie({
298
288
  clientId: t.clientId
299
289
  });
300
- const r = this.cookiesManager.get(), n = new J(t.configurationEndpoint);
301
- let s = new R(
290
+ const r = this.cookiesManager.get(), n = new $(t.configurationEndpoint);
291
+ let i = new R(
302
292
  n,
303
293
  t.clientId,
304
294
  t.redirectUrl
305
295
  ).WithScopes(t.scopes);
306
- t.logoutRedirectUrl && (s = s.WithLogoutRedirect(t.logoutRedirectUrl)), (r == null ? void 0 : r.code_verifier) != null && (s = s.WithProofKeyForCodeExchange(r.code_verifier)), this.tokenProvider = s, this.cacheManager = new te(), this.clientId = t.clientId, this.analyticshttpclient = H, this.analyticshttpclient.sendInitEvent("TIDClient", this.clientId, u, g), this.cleanupExpiredState();
296
+ t.logoutRedirectUrl && (i = i.WithLogoutRedirect(t.logoutRedirectUrl)), r?.code_verifier != null && (i = i.WithProofKeyForCodeExchange(r.code_verifier)), this.tokenProvider = i, this.cacheManager = new Z(), this.clientId = t.clientId, h.sendInitEvent("TIDClient", this.clientId, u, g), this.cleanupExpiredState();
307
297
  }
308
298
  /**
309
299
  * Clean up expired state payloads to prevent storage bloat
@@ -333,11 +323,11 @@ class he {
333
323
  * // So it can be handled by the developer
334
324
  */
335
325
  async loginWithRedirect(e) {
336
- this.analyticshttpclient.sendMethodEvent(this.loginWithRedirect.name, this.clientId, u, g);
326
+ h.sendMethodEvent(this.loginWithRedirect.name, this.clientId, u, g);
337
327
  const { onRedirect: t } = e || {}, r = window.location.pathname + window.location.search, n = this.createStatePayload(r);
338
328
  this.cookiesManager.save({ state_payload: n });
339
- const s = R.GenerateCodeVerifier();
340
- this.cookiesManager.save({ code_verifier: s }), this.tokenProvider = this.tokenProvider.WithProofKeyForCodeExchange(s);
329
+ const i = R.GenerateCodeVerifier();
330
+ this.cookiesManager.save({ code_verifier: i }), this.tokenProvider = this.tokenProvider.WithProofKeyForCodeExchange(i);
341
331
  const c = await this.tokenProvider.GetOAuthRedirect(n);
342
332
  t != null ? t(c) : window.location.assign(c);
343
333
  }
@@ -356,12 +346,12 @@ class he {
356
346
  */
357
347
  async handleCallback(e = window.location.href) {
358
348
  const t = this.cookiesManager.get();
359
- if (t == null || (t == null ? void 0 : t.code_verifier) == null)
360
- throw new le("Code verifier not available");
361
- const r = re(e), n = b(e), s = n.get("identity_provider") ?? "", c = n.get("state") ?? "", d = this.validateStatePayload(c);
349
+ if (t == null || t?.code_verifier == null)
350
+ throw new ae("Code verifier not available");
351
+ const r = ee(e), n = b(e), i = n.get("identity_provider") ?? "", c = n.get("state") ?? "", d = this.validateStatePayload(c);
362
352
  if (!d.isValid)
363
353
  throw new Error(`State validation failed: ${d.error}`);
364
- return await this.tokenProvider.ValidateQuery(r), await this.generateToken(s), {
354
+ return await this.tokenProvider.ValidateQuery(r), await this.generateToken(i), {
365
355
  authState: c,
366
356
  returnTo: d.redirectTo
367
357
  };
@@ -372,10 +362,9 @@ class he {
372
362
  * @return {Promise<void>} Empty promise
373
363
  */
374
364
  async generateToken(e) {
375
- var a, k;
376
- const t = await this.tokenProvider.RetrieveToken(), r = await this.tokenProvider.RetrieveRefreshToken(), n = await this.tokenProvider.RetrieveIdToken(), s = await this.tokenProvider.RetrieveTokenExpiry(), d = new Date(s).getTime(), f = (k = (a = this.tokenProvider) == null ? void 0 : a._scopes) == null ? void 0 : k.join(" ");
365
+ const t = await this.tokenProvider.RetrieveToken(), r = await this.tokenProvider.RetrieveRefreshToken(), n = await this.tokenProvider.RetrieveIdToken(), i = await this.tokenProvider.RetrieveTokenExpiry(), d = new Date(i).getTime(), k = this.tokenProvider?._scopes?.join(" ");
377
366
  await this.cacheManager.setToken({
378
- scope: f,
367
+ scope: k,
379
368
  state: "",
380
369
  session_state: "",
381
370
  identity_provider: e,
@@ -385,7 +374,7 @@ class he {
385
374
  id_token: n,
386
375
  expires_at: d
387
376
  });
388
- const v = X(n), p = ae(v);
377
+ const v = J(n), p = oe(v);
389
378
  await this.cacheManager.setUser(p), await this.reloadCodeVerifier();
390
379
  }
391
380
  async reloadCodeVerifier() {
@@ -425,13 +414,16 @@ class he {
425
414
  const t = this.cookiesManager.getStatePayload();
426
415
  if (!t)
427
416
  return { isValid: !1, error: "No stored state found" };
428
- const r = atob(e), n = JSON.parse(r), s = atob(t), c = JSON.parse(s);
417
+ const r = atob(e), n = JSON.parse(r), i = atob(t), c = JSON.parse(i);
429
418
  if (!n.nonce || !n.timestamp || !n.redirectTo)
430
419
  return { isValid: !1, error: "Invalid state payload structure" };
431
420
  if (n.nonce !== c.nonce)
432
421
  return { isValid: !1, error: "State nonce mismatch" };
433
- const f = Date.now() - n.timestamp;
434
- return f > A ? { isValid: !1, error: "State expired - possible replay attack" } : f < 0 ? { isValid: !1, error: "State timestamp is in the future - possible replay attack" } : (this.cookiesManager.clearStatePayload(), {
422
+ const k = Date.now() - n.timestamp;
423
+ return k > A ? { isValid: !1, error: "State expired - possible replay attack" } : k < 0 ? {
424
+ isValid: !1,
425
+ error: "State timestamp is in the future - possible replay attack"
426
+ } : (this.cookiesManager.clearStatePayload(), {
435
427
  isValid: !0,
436
428
  redirectTo: n.redirectTo
437
429
  });
@@ -444,7 +436,7 @@ class he {
444
436
  * @return {Promise<TIDUser | undefined>} User in cache
445
437
  */
446
438
  async getUser() {
447
- return this.analyticshttpclient.sendMethodEvent(this.getUser.name, this.clientId, u, g), await this.cacheManager.getUser();
439
+ return h.sendMethodEvent(this.getUser.name, this.clientId, u, g), await this.cacheManager.getUser();
448
440
  }
449
441
  /**
450
442
  * Gets the access token from cache. If the token already expired,
@@ -454,46 +446,75 @@ class he {
454
446
  * @throws {TokenExpiredException} Will throw an exception if the user token expired
455
447
  */
456
448
  async getAccessTokenSilently() {
457
- this.analyticshttpclient.sendMethodEvent(this.getAccessTokenSilently.name, this.clientId, u, g);
449
+ h.sendMethodEvent(
450
+ this.getAccessTokenSilently.name,
451
+ this.clientId,
452
+ u,
453
+ g
454
+ );
458
455
  let e = await this.cacheManager.getToken();
459
456
  if (e == null)
460
- throw this.analyticshttpclient.sendExceptionEvent(this.getAccessTokenSilently.name, "No token available", this.clientId, u, g), new D("No token available");
457
+ throw h.sendExceptionEvent(
458
+ this.getAccessTokenSilently.name,
459
+ "No token available",
460
+ this.clientId,
461
+ u,
462
+ g
463
+ ), new D("No token available");
461
464
  const t = new Date((/* @__PURE__ */ new Date()).getTime() + x);
462
- if ((e == null ? void 0 : e.expires_at) == null || (e == null ? void 0 : e.expires_at) < t.getTime()) {
465
+ if (e?.expires_at == null || e?.expires_at < t.getTime()) {
463
466
  try {
464
467
  await this.tokenProvider.RetrieveToken();
465
468
  } catch (r) {
466
- throw this.analyticshttpclient.sendExceptionEvent(this.getAccessTokenSilently.name, r.message, this.clientId, u, g), new O(r.message);
469
+ throw h.sendExceptionEvent(
470
+ this.getAccessTokenSilently.name,
471
+ r.message,
472
+ this.clientId,
473
+ u,
474
+ g
475
+ ), new O(r.message);
467
476
  }
468
- await this.generateToken((e == null ? void 0 : e.identity_provider) ?? ""), e = await this.cacheManager.getToken();
477
+ await this.generateToken(e?.identity_provider ?? ""), e = await this.cacheManager.getToken();
469
478
  }
470
- return (e == null ? void 0 : e.access_token) || "";
479
+ return e?.access_token || "";
471
480
  }
472
481
  /**
473
482
  * Retrieves token details from the cache, including the access token, ID token, and expiration time.
474
- * If the token already expired, will try to refresh it using the refresh token.
483
+ * If the token already expired, will try to refresh it using the refresh token.
475
484
  * @return {Promise<TokenResponse>} Token response
476
485
  * @throws {TokenNotFoundException} Will throw an exception if there are no tokens in cache
477
486
  * @throws {TokenExpiredException} Will throw an exception if the user token expired
478
487
  */
479
488
  async getTokens() {
480
- this.analyticshttpclient.sendMethodEvent(this.getTokens.name, this.clientId, u, g);
489
+ h.sendMethodEvent(this.getTokens.name, this.clientId, u, g);
481
490
  let e = await this.cacheManager.getToken();
482
491
  if (e == null)
483
- throw this.analyticshttpclient.sendExceptionEvent(this.getTokens.name, "No token available", this.clientId, u, g), new D("No token available");
492
+ throw h.sendExceptionEvent(
493
+ this.getTokens.name,
494
+ "No token available",
495
+ this.clientId,
496
+ u,
497
+ g
498
+ ), new D("No token available");
484
499
  const t = new Date((/* @__PURE__ */ new Date()).getTime() + x);
485
- if ((e == null ? void 0 : e.expires_at) == null || (e == null ? void 0 : e.expires_at) < t.getTime()) {
500
+ if (e?.expires_at == null || e?.expires_at < t.getTime()) {
486
501
  try {
487
502
  await this.tokenProvider.RetrieveToken();
488
503
  } catch (r) {
489
- throw this.analyticshttpclient.sendExceptionEvent(this.getTokens.name, r.message, this.clientId, u, g), new O(r.message);
504
+ throw h.sendExceptionEvent(
505
+ this.getTokens.name,
506
+ r.message,
507
+ this.clientId,
508
+ u,
509
+ g
510
+ ), new O(r.message);
490
511
  }
491
- await this.generateToken((e == null ? void 0 : e.identity_provider) ?? ""), e = await this.cacheManager.getToken();
512
+ await this.generateToken(e?.identity_provider ?? ""), e = await this.cacheManager.getToken();
492
513
  }
493
514
  return {
494
- access_token: (e == null ? void 0 : e.access_token) || "",
495
- expires_at: (e == null ? void 0 : e.expires_at) || 0,
496
- id_token: (e == null ? void 0 : e.id_token) || ""
515
+ access_token: e?.access_token || "",
516
+ expires_at: e?.expires_at || 0,
517
+ id_token: e?.id_token || ""
497
518
  };
498
519
  }
499
520
  /**
@@ -509,7 +530,7 @@ class he {
509
530
  * // So it can be handled by the developer
510
531
  */
511
532
  async logout(e) {
512
- this.analyticshttpclient.sendMethodEvent(this.logout.name, this.clientId, u, g);
533
+ h.sendMethodEvent(this.logout.name, this.clientId, u, g);
513
534
  const { onRedirect: t, disabledAutoRedirect: r } = e || {};
514
535
  this.cacheManager && await this.cacheManager.clear(), this.cookiesManager && this.cookiesManager.clear();
515
536
  const n = await this.tokenProvider.GetOAuthLogoutRedirect("state");
@@ -544,15 +565,15 @@ class he {
544
565
  const e = await this.cacheManager.getToken();
545
566
  if (e == null)
546
567
  return;
547
- const t = e.access_token, r = e.refresh_token || "", n = e.id_token, s = e.expires_at;
548
- this.tokenProvider = this.tokenProvider.WithAccessToken(t, s).WithRefreshToken(r).WithIdToken(n);
568
+ const t = e.access_token, r = e.refresh_token || "", n = e.id_token, i = e.expires_at;
569
+ this.tokenProvider = this.tokenProvider.WithAccessToken(t, i).WithRefreshToken(r).WithIdToken(n);
549
570
  }
550
571
  /**
551
572
  * Get a http bearer token client to use it for another SDK (Ex: Processing framework)
552
573
  * @return {any} - BearerTokenHttpClientProvider
553
574
  */
554
575
  getBearerTokenHttpClient(e) {
555
- return new Q(this.tokenProvider, e);
576
+ return new B(this.tokenProvider, e);
556
577
  }
557
578
  /**
558
579
  * Get the redirect url to TID
@@ -562,11 +583,11 @@ class he {
562
583
  return this.redirectUrl;
563
584
  }
564
585
  }
565
- const w = q(null), K = () => L(w) ?? {}, ue = (i, e) => {
586
+ const T = H(null), K = () => L(T) ?? {}, de = (o, e) => {
566
587
  switch (e.type) {
567
588
  case "INIT":
568
589
  return {
569
- ...i,
590
+ ...o,
570
591
  isLoading: !1,
571
592
  isAuthenticated: e.user != null,
572
593
  user: e.user,
@@ -576,7 +597,7 @@ const w = q(null), K = () => L(w) ?? {}, ue = (i, e) => {
576
597
  case "HANDLE_CALLBACK_COMPLETE":
577
598
  case "GET_ACCESS_TOKEN_COMPLETE":
578
599
  return {
579
- ...i,
600
+ ...o,
580
601
  isLoading: !1,
581
602
  isAuthenticated: e.user != null,
582
603
  user: e.user,
@@ -584,134 +605,134 @@ const w = q(null), K = () => L(w) ?? {}, ue = (i, e) => {
584
605
  };
585
606
  case "LOGOUT":
586
607
  return {
587
- ...i,
608
+ ...o,
588
609
  isAuthenticated: !1,
589
610
  user: void 0
590
611
  };
591
612
  case "ERROR":
592
613
  return {
593
- ...i,
614
+ ...o,
594
615
  isLoading: !1,
595
616
  error: e.error
596
617
  };
597
618
  }
598
- }, ge = {
619
+ }, le = {
599
620
  isLoading: !0,
600
621
  isAuthenticated: !1
601
- }, fe = (i) => {
602
- if (i == null || Object.keys(i).length <= 0)
622
+ }, he = (o) => {
623
+ if (o == null || Object.keys(o).length <= 0)
603
624
  return !0;
604
- const e = Object.keys(i);
625
+ const e = Object.keys(o);
605
626
  for (const t of e)
606
- if (i[t] != null && i[t] !== "")
627
+ if (o[t] != null && o[t] !== "")
607
628
  return !1;
608
629
  return !0;
609
- }, ye = (i) => !fe(i.config), ke = (i) => {
630
+ }, ue = (o) => !he(o.config), ge = (o) => {
610
631
  const {
611
632
  children: e,
612
633
  configurationEndpoint: t,
613
634
  clientId: r,
614
635
  redirectUrl: n,
615
- logoutRedirectUrl: s,
636
+ logoutRedirectUrl: i,
616
637
  scopes: c,
617
638
  onRedirectCallback: d,
618
- checkRedirectUrlMatch: f
619
- } = i;
620
- if (L(w) != null)
639
+ checkRedirectUrlMatch: k
640
+ } = o;
641
+ if (L(T) != null)
621
642
  throw new Error("TID Provider already defined");
622
643
  const p = {
623
644
  config: {
624
645
  configurationEndpoint: t ?? "",
625
646
  clientId: r ?? "",
626
647
  redirectUrl: n ?? "",
627
- logoutRedirectUrl: s ?? "",
648
+ logoutRedirectUrl: i ?? "",
628
649
  scopes: c ?? [""]
629
650
  }
630
- }, [a] = z(i.tidClient ?? new he(p)), [k, y] = Y(ue, ge), E = Z(!1), W = M(
631
- () => f ? a.getRedirectUrl() : void 0,
632
- [f, a]
651
+ }, [a] = Q(o.tidClient ?? new ce(p)), [w, f] = X(de, le), E = q(!1), W = M(
652
+ () => k ? a.getRedirectUrl() : void 0,
653
+ [k, a]
633
654
  );
634
655
  N(() => {
635
- E.current || (i.tidClient != null && ye({
656
+ E.current || (o.tidClient != null && ue({
636
657
  config: {
637
658
  configurationEndpoint: t,
638
659
  clientId: r,
639
660
  redirectUrl: n,
640
- logoutRedirectUrl: s,
661
+ logoutRedirectUrl: i,
641
662
  scopes: c
642
663
  }
643
664
  }) && console.warn(
644
665
  "When TID client is pass as prop, any client configuration property sent directly to the TID Provider component will be ignored"
645
666
  ), E.current = !0, (async () => {
646
667
  try {
647
- let o;
648
- if (ne(void 0, W)) {
649
- const h = await a.handleCallback();
650
- o = await a.getUser(), d != null && d(h);
668
+ let s;
669
+ if (te(void 0, W)) {
670
+ const l = await a.handleCallback();
671
+ s = await a.getUser(), d?.(l);
651
672
  } else
652
- await a.loadUserSession(), o = await a.getUser();
653
- y({ type: "INIT", user: o });
654
- } catch (o) {
655
- let h = o;
656
- typeof o == "string" && (h = new Error(o)), y({ type: "ERROR", error: h });
673
+ await a.loadUserSession(), s = await a.getUser();
674
+ f({ type: "INIT", user: s });
675
+ } catch (s) {
676
+ let l = s;
677
+ typeof s == "string" && (l = new Error(s)), f({ type: "ERROR", error: l });
657
678
  }
658
679
  })());
659
680
  }, [a, d]);
660
- const S = m(async () => {
661
- const o = await a.getAccessTokenSilently(), h = await a.getUser();
662
- return y({
681
+ const S = y(async () => {
682
+ const s = await a.getAccessTokenSilently(), l = await a.getUser();
683
+ return f({
663
684
  type: "GET_ACCESS_TOKEN_COMPLETE",
664
- user: h
665
- }), o;
666
- }, [a]), P = m(async () => {
667
- const o = await a.getTokens(), h = await a.getUser();
668
- return y({
685
+ user: l
686
+ }), s;
687
+ }, [a]), _ = y(async () => {
688
+ const s = await a.getTokens(), l = await a.getUser();
689
+ return f({
669
690
  type: "GET_TOKENS_COMPLETE",
670
- user: h
671
- }), o;
672
- }, [a]), _ = m(
673
- async (o) => {
674
- await a.loginWithRedirect(o);
691
+ user: l
692
+ }), s;
693
+ }, [a]), P = y(
694
+ async (s) => {
695
+ await a.loginWithRedirect(s);
675
696
  },
676
697
  [a]
677
- ), C = m(
678
- async (o) => {
679
- await a.logout(o), (o == null ? void 0 : o.disabledAutoRedirect) != null && o.disabledAutoRedirect && y({
698
+ ), C = y(
699
+ async (s) => {
700
+ await a.logout(s), s?.disabledAutoRedirect != null && s.disabledAutoRedirect && f({
680
701
  type: "LOGOUT"
681
702
  });
682
703
  },
683
704
  [a]
684
- ), I = m(
685
- async (o) => {
686
- const h = await a.handleCallback(o), F = await a.getUser();
687
- return y({
705
+ ), I = y(
706
+ async (s) => {
707
+ const l = await a.handleCallback(s), F = await a.getUser();
708
+ return f({
688
709
  type: "HANDLE_CALLBACK_COMPLETE",
689
710
  user: F
690
- }), h;
711
+ }), l;
691
712
  },
692
713
  [a]
693
714
  ), G = M(
694
715
  () => ({
695
- ...k,
716
+ ...w,
696
717
  getAccessTokenSilently: S,
697
- getTokens: P,
698
- loginWithRedirect: _,
718
+ getTokens: _,
719
+ loginWithRedirect: P,
699
720
  handleCallback: I,
700
721
  logout: C
701
722
  }),
702
- [k, S, P, _, I, C]
723
+ [w, S, _, P, I, C]
703
724
  );
704
- return /* @__PURE__ */ V(w.Provider, { value: G, children: e });
705
- }, Ee = K, Se = ke, Pe = ({ renderComponent: i, loader: e }) => {
725
+ return /* @__PURE__ */ V(T.Provider, { value: G, children: e });
726
+ }, me = K, Te = ge, ve = ({ renderComponent: o, loader: e }) => {
706
727
  const { isAuthenticated: t, isLoading: r, loginWithRedirect: n } = K();
707
728
  return N(() => {
708
729
  !r && !t && (async () => await n())();
709
- }, [r, t, n]), t ? i : e || /* @__PURE__ */ V(j, {});
730
+ }, [r, t, n]), t ? o : e || /* @__PURE__ */ V(z, {});
710
731
  };
711
732
  export {
712
- Pe as AuthenticationGuard,
713
- he as TIDClient,
714
- w as TIDContext,
715
- Se as TIDProvider,
716
- Ee as useAuth
733
+ ve as AuthenticationGuard,
734
+ ce as TIDClient,
735
+ T as TIDContext,
736
+ Te as TIDProvider,
737
+ me as useAuth
717
738
  };
@@ -1 +1 @@
1
- (function(o,l){typeof exports=="object"&&typeof module<"u"?l(exports,require("@trimble-oss/trimble-id"),require("es-cookie"),require("jwt-decode"),require("react"),require("react/jsx-runtime")):typeof define=="function"&&define.amd?define(["exports","@trimble-oss/trimble-id","es-cookie","jwt-decode","react","react/jsx-runtime"],l):(o=typeof globalThis<"u"?globalThis:o||self,l(o.ReactTID={},o.trimbleId,o.esCookie,o.jwt_decode,o.React,o.jsxRuntime))})(this,function(o,l,p,W,d,E){"use strict";var de=Object.defineProperty;var he=(o,l,p)=>l in o?de(o,l,{enumerable:!0,configurable:!0,writable:!0,value:p}):o[l]=p;var u=(o,l,p)=>(he(o,typeof l!="symbol"?l+"":l,p),p);function G(i){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(i){for(const t in i)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(i,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>i[t]})}}return e.default=i,Object.freeze(e)}const S=G(p);class F{constructor(){u(this,"generateCache",function(){const e={token:void 0,user:void 0};return{async getToken(){return e.token},async getUser(){return e.user},async storeToken(t){e.token=t},async storeUser(t){e.user=t},clear(){return e.token=void 0,e.user=void 0,Promise.resolve(void 0)}}}())}}class j{constructor(){u(this,"cacheStorage");this.cacheStorage=new F().generateCache}async setToken(e){await this.cacheStorage.storeToken(e)}async setUser(e){await this.cacheStorage.storeUser(e)}async getUser(){return this.cacheStorage.getUser()}async getToken(){return this.cacheStorage.getToken()}async clear(){await this.cacheStorage.clear()}}const C=5*6e4,$=["code","state"],_=10*60*1e3,I=i=>i.split("?")[0],q=i=>i.split("?")[1],M=i=>{let e=i;if(!i.startsWith("?"))try{e=new URL(i).search}catch{}return new URLSearchParams(e)},B=(i=window.location.href,e)=>{if(e!=null){const n=I(e),r=I(i??"");if(n!==r)return!1}const t=M(i);for(const n of $)if(!t.has(n))return!1;return!0},J=i=>({id:i.sub,name:`${i.given_name} ${i.family_name}`,given_name:i.given_name,family_name:i.family_name,picture:i.picture,email:i.email,email_verified:i.email_verified}),H="@TID_COOKIE";class z{get(e){const t=S.get(e);if(t==null)throw new Error("Cookie not found");return JSON.parse(t)}set(e,t,n){let r={};window.location.protocol==="https:"&&(r={secure:!0,sameSite:"none"}),n!=null&&n.expires&&(r.expires=n.expires),n!=null&&n.domain&&(r.domain=n.domain),S.set(e,JSON.stringify(t),r)}remove(e,t){const n={};t!=null&&t.domain&&(n.domain=t.domain),S.remove(e,n)}}class Q{constructor(e){u(this,"cookieKey");u(this,"cookiesStorage");this.cookieKey=`${H}.${e.clientId}`,this.cookiesStorage=new z}save(e){const n={...this.get()||{},...e};this.cookiesStorage.set(this.cookieKey,n,{expires:1})}getStatePayload(){const e=this.get();return e==null?void 0:e.state_payload}clearStatePayload(){const e=this.get();e&&(delete e.state_payload,this.cookiesStorage.set(this.cookieKey,e,{expires:1}))}get(){try{return this.cookiesStorage.get(this.cookieKey)}catch{return}}clear(){this.cookiesStorage.remove(this.cookieKey)}}class R extends Error{}class x extends Error{}class X extends Error{}const g="@trimble-oss/trimble-id-react",f="1.0.1",Y={configurationEndpoint:"",clientId:"",redirectUrl:"",logoutRedirectUrl:"",scopes:[]};class A{constructor(e){u(this,"tokenProvider");u(this,"cacheManager");u(this,"cookiesManager");u(this,"clientId");u(this,"redirectUrl");u(this,"analyticshttpclient");const{config:t=Y}=e;if(this.redirectUrl=t.redirectUrl,t.configurationEndpoint==null||t.configurationEndpoint=="")throw new Error("Configuration endpoint not defined");if(t.clientId==null||t.clientId=="")throw new Error("Consumer key is not defined");this.cookiesManager=new Q({clientId:t.clientId});const n=this.cookiesManager.get(),r=new l.OpenIdEndpointProvider(t.configurationEndpoint);let c=new l.AuthorizationCodeGrantTokenProvider(r,t.clientId,t.redirectUrl).WithScopes(t.scopes);t.logoutRedirectUrl&&(c=c.WithLogoutRedirect(t.logoutRedirectUrl)),(n==null?void 0:n.code_verifier)!=null&&(c=c.WithProofKeyForCodeExchange(n.code_verifier)),this.tokenProvider=c,this.cacheManager=new j,this.clientId=t.clientId,this.analyticshttpclient=l.AnalyticsHttpClient,this.analyticshttpclient.sendInitEvent("TIDClient",this.clientId,g,f),this.cleanupExpiredState()}cleanupExpiredState(){try{const e=this.cookiesManager.getStatePayload();if(e){const t=atob(e),n=JSON.parse(t);Date.now()-n.timestamp>_&&this.cookiesManager.clearStatePayload()}}catch{this.cookiesManager.clearStatePayload()}}async loginWithRedirect(e){this.analyticshttpclient.sendMethodEvent(this.loginWithRedirect.name,this.clientId,g,f);const{onRedirect:t}=e||{},n=window.location.pathname+window.location.search,r=this.createStatePayload(n);this.cookiesManager.save({state_payload:r});const c=l.AuthorizationCodeGrantTokenProvider.GenerateCodeVerifier();this.cookiesManager.save({code_verifier:c}),this.tokenProvider=this.tokenProvider.WithProofKeyForCodeExchange(c);const h=await this.tokenProvider.GetOAuthRedirect(r);t!=null?t(h):window.location.assign(h)}async handleCallback(e=window.location.href){const t=this.cookiesManager.get();if(t==null||(t==null?void 0:t.code_verifier)==null)throw new X("Code verifier not available");const n=q(e),r=M(e),c=r.get("identity_provider")??"",h=r.get("state")??"",y=this.validateStatePayload(h);if(!y.isValid)throw new Error(`State validation failed: ${y.error}`);return await this.tokenProvider.ValidateQuery(n),await this.generateToken(c),{authState:h,returnTo:y.redirectTo}}async generateToken(e){var a,v;const t=await this.tokenProvider.RetrieveToken(),n=await this.tokenProvider.RetrieveRefreshToken(),r=await this.tokenProvider.RetrieveIdToken(),c=await this.tokenProvider.RetrieveTokenExpiry(),y=new Date(c).getTime(),T=(v=(a=this.tokenProvider)==null?void 0:a._scopes)==null?void 0:v.join(" ");await this.cacheManager.setToken({scope:T,state:"",session_state:"",identity_provider:e,token_type:"bearer",access_token:t,refresh_token:n,id_token:r,expires_at:y});const U=W(r),P=J(U);await this.cacheManager.setUser(P),await this.reloadCodeVerifier()}async reloadCodeVerifier(){const e=await this.tokenProvider.RetrieveCodeVerifier();this.cookiesManager.save({code_verifier:e}),this.tokenProvider=this.tokenProvider.WithProofKeyForCodeExchange(e)}createStatePayload(e){const t=this.generateNonce(),n=Date.now();return btoa(JSON.stringify({redirectTo:e,timestamp:n,nonce:t}))}generateNonce(){const e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}validateStatePayload(e){try{if(!e||e.trim()==="")return{isValid:!1,error:"Empty state parameter"};const t=this.cookiesManager.getStatePayload();if(!t)return{isValid:!1,error:"No stored state found"};const n=atob(e),r=JSON.parse(n),c=atob(t),h=JSON.parse(c);if(!r.nonce||!r.timestamp||!r.redirectTo)return{isValid:!1,error:"Invalid state payload structure"};if(r.nonce!==h.nonce)return{isValid:!1,error:"State nonce mismatch"};const T=Date.now()-r.timestamp;return T>_?{isValid:!1,error:"State expired - possible replay attack"}:T<0?{isValid:!1,error:"State timestamp is in the future - possible replay attack"}:(this.cookiesManager.clearStatePayload(),{isValid:!0,redirectTo:r.redirectTo})}catch{return{isValid:!1,error:"Invalid state format"}}}async getUser(){return this.analyticshttpclient.sendMethodEvent(this.getUser.name,this.clientId,g,f),await this.cacheManager.getUser()}async getAccessTokenSilently(){this.analyticshttpclient.sendMethodEvent(this.getAccessTokenSilently.name,this.clientId,g,f);let e=await this.cacheManager.getToken();if(e==null)throw this.analyticshttpclient.sendExceptionEvent(this.getAccessTokenSilently.name,"No token available",this.clientId,g,f),new x("No token available");const t=new Date(new Date().getTime()+C);if((e==null?void 0:e.expires_at)==null||(e==null?void 0:e.expires_at)<t.getTime()){try{await this.tokenProvider.RetrieveToken()}catch(n){throw this.analyticshttpclient.sendExceptionEvent(this.getAccessTokenSilently.name,n.message,this.clientId,g,f),new R(n.message)}await this.generateToken((e==null?void 0:e.identity_provider)??""),e=await this.cacheManager.getToken()}return(e==null?void 0:e.access_token)||""}async getTokens(){this.analyticshttpclient.sendMethodEvent(this.getTokens.name,this.clientId,g,f);let e=await this.cacheManager.getToken();if(e==null)throw this.analyticshttpclient.sendExceptionEvent(this.getTokens.name,"No token available",this.clientId,g,f),new x("No token available");const t=new Date(new Date().getTime()+C);if((e==null?void 0:e.expires_at)==null||(e==null?void 0:e.expires_at)<t.getTime()){try{await this.tokenProvider.RetrieveToken()}catch(n){throw this.analyticshttpclient.sendExceptionEvent(this.getTokens.name,n.message,this.clientId,g,f),new R(n.message)}await this.generateToken((e==null?void 0:e.identity_provider)??""),e=await this.cacheManager.getToken()}return{access_token:(e==null?void 0:e.access_token)||"",expires_at:(e==null?void 0:e.expires_at)||0,id_token:(e==null?void 0:e.id_token)||""}}async logout(e){this.analyticshttpclient.sendMethodEvent(this.logout.name,this.clientId,g,f);const{onRedirect:t,disabledAutoRedirect:n}=e||{};this.cacheManager&&await this.cacheManager.clear(),this.cookiesManager&&this.cookiesManager.clear();const r=await this.tokenProvider.GetOAuthLogoutRedirect("state");if(t!=null)return t(r);n||window.location.assign(r)}async checkSession(){try{await this.getAccessTokenSilently()}catch{return!1}return!0}async loadUserSession(){await this.loadCacheSessionIntoSDK(),await this.checkSession()||await this.cacheManager.clear()}async loadCacheSessionIntoSDK(){const e=await this.cacheManager.getToken();if(e==null)return;const t=e.access_token,n=e.refresh_token||"",r=e.id_token,c=e.expires_at;this.tokenProvider=this.tokenProvider.WithAccessToken(t,c).WithRefreshToken(n).WithIdToken(r)}getBearerTokenHttpClient(e){return new l.BearerTokenHttpClientProvider(this.tokenProvider,e)}getRedirectUrl(){return this.redirectUrl}}const w=d.createContext(null),O=()=>d.useContext(w)??{},Z=(i,e)=>{switch(e.type){case"INIT":return{...i,isLoading:!1,isAuthenticated:e.user!=null,user:e.user,error:void 0};case"GET_TOKENS_COMPLETE":case"HANDLE_CALLBACK_COMPLETE":case"GET_ACCESS_TOKEN_COMPLETE":return{...i,isLoading:!1,isAuthenticated:e.user!=null,user:e.user,error:void 0};case"LOGOUT":return{...i,isAuthenticated:!1,user:void 0};case"ERROR":return{...i,isLoading:!1,error:e.error}}},ee={isLoading:!0,isAuthenticated:!1},te=i=>{if(i==null||Object.keys(i).length<=0)return!0;const e=Object.keys(i);for(const t of e)if(i[t]!=null&&i[t]!=="")return!1;return!0},ie=i=>!te(i.config),ne=i=>{const{children:e,configurationEndpoint:t,clientId:n,redirectUrl:r,logoutRedirectUrl:c,scopes:h,onRedirectCallback:y,checkRedirectUrlMatch:T}=i;if(d.useContext(w)!=null)throw new Error("TID Provider already defined");const P={config:{configurationEndpoint:t??"",clientId:n??"",redirectUrl:r??"",logoutRedirectUrl:c??"",scopes:h??[""]}},[a]=d.useState(i.tidClient??new A(P)),[v,m]=d.useReducer(Z,ee),D=d.useRef(!1),se=d.useMemo(()=>T?a.getRedirectUrl():void 0,[T,a]);d.useEffect(()=>{D.current||(i.tidClient!=null&&ie({config:{configurationEndpoint:t,clientId:n,redirectUrl:r,logoutRedirectUrl:c,scopes:h}})&&console.warn("When TID client is pass as prop, any client configuration property sent directly to the TID Provider component will be ignored"),D.current=!0,(async()=>{try{let s;if(B(void 0,se)){const k=await a.handleCallback();s=await a.getUser(),y!=null&&y(k)}else await a.loadUserSession(),s=await a.getUser();m({type:"INIT",user:s})}catch(s){let k=s;typeof s=="string"&&(k=new Error(s)),m({type:"ERROR",error:k})}})())},[a,y]);const b=d.useCallback(async()=>{const s=await a.getAccessTokenSilently(),k=await a.getUser();return m({type:"GET_ACCESS_TOKEN_COMPLETE",user:k}),s},[a]),L=d.useCallback(async()=>{const s=await a.getTokens(),k=await a.getUser();return m({type:"GET_TOKENS_COMPLETE",user:k}),s},[a]),N=d.useCallback(async s=>{await a.loginWithRedirect(s)},[a]),V=d.useCallback(async s=>{await a.logout(s),(s==null?void 0:s.disabledAutoRedirect)!=null&&s.disabledAutoRedirect&&m({type:"LOGOUT"})},[a]),K=d.useCallback(async s=>{const k=await a.handleCallback(s),le=await a.getUser();return m({type:"HANDLE_CALLBACK_COMPLETE",user:le}),k},[a]),ce=d.useMemo(()=>({...v,getAccessTokenSilently:b,getTokens:L,loginWithRedirect:N,handleCallback:K,logout:V}),[v,b,L,N,K,V]);return E.jsx(w.Provider,{value:ce,children:e})},re=O,ae=ne,oe=({renderComponent:i,loader:e})=>{const{isAuthenticated:t,isLoading:n,loginWithRedirect:r}=O();return d.useEffect(()=>{!n&&!t&&(async()=>await r())()},[n,t,r]),t?i:e||E.jsx(E.Fragment,{})};o.AuthenticationGuard=oe,o.TIDClient=A,o.TIDContext=w,o.TIDProvider=ae,o.useAuth=re,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})});
1
+ (function(d,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("@trimble-oss/trimble-id"),require("es-cookie"),require("jwt-decode"),require("react"),require("react/jsx-runtime")):typeof define=="function"&&define.amd?define(["exports","@trimble-oss/trimble-id","es-cookie","jwt-decode","react","react/jsx-runtime"],c):(d=typeof globalThis<"u"?globalThis:d||self,c(d.ReactTID={},d.trimbleId,d.esCookie,d.jwt_decode,d.React,d.jsxRuntime))})(this,(function(d,c,b,K,l,m){"use strict";function W(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const i=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,i.get?i:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const v=W(b);class G{generateCache=(function(){const e={token:void 0,user:void 0};return{async getToken(){return e.token},async getUser(){return e.user},async storeToken(t){e.token=t},async storeUser(t){e.user=t},clear(){return e.token=void 0,e.user=void 0,Promise.resolve(void 0)}}})()}class H{cacheStorage;constructor(){this.cacheStorage=new G().generateCache}async setToken(e){await this.cacheStorage.storeToken(e)}async setUser(e){await this.cacheStorage.storeUser(e)}async getUser(){return this.cacheStorage.getUser()}async getToken(){return this.cacheStorage.getToken()}async clear(){await this.cacheStorage.clear()}}const E=5*6e4,F=["code","state"],S=600*1e3,C=n=>n.split("?")[0],$=n=>n.split("?")[1],P=n=>{let e=n;if(!n.startsWith("?"))try{e=new URL(n).search}catch{}return new URLSearchParams(e)},q=(n=window.location.href,e)=>{if(e!=null){const i=C(e),o=C(n??"");if(i!==o)return!1}const t=P(n);for(const i of F)if(!t.has(i))return!1;return!0},B=n=>({id:n.sub,name:`${n.given_name} ${n.family_name}`,given_name:n.given_name,family_name:n.family_name,picture:n.picture,email:n.email,email_verified:n.email_verified,...n.account_id&&{account_id:n.account_id}}),J="@TID_COOKIE";class j{get(e){const t=v.get(e);if(t==null)throw new Error("Cookie not found");return JSON.parse(t)}set(e,t,i){let o={};window.location.protocol==="https:"&&(o={secure:!0,sameSite:"none"}),i?.expires&&(o.expires=i.expires),i?.domain&&(o.domain=i.domain),v.set(e,JSON.stringify(t),o)}remove(e,t){const i={};t?.domain&&(i.domain=t.domain),v.remove(e,i)}}class z{cookieKey;cookiesStorage;constructor(e){this.cookieKey=`${J}.${e.clientId}`,this.cookiesStorage=new j}save(e){const i={...this.get()||{},...e};this.cookiesStorage.set(this.cookieKey,i,{expires:1})}getStatePayload(){return this.get()?.state_payload}clearStatePayload(){const e=this.get();e&&(delete e.state_payload,this.cookiesStorage.set(this.cookieKey,e,{expires:1}))}get(){try{return this.cookiesStorage.get(this.cookieKey)}catch{return}}clear(){this.cookiesStorage.remove(this.cookieKey)}}class _ extends Error{}class A extends Error{}class Q extends Error{}const h="@trimble-oss/trimble-id-react",g="1.0.2-rc1",X={configurationEndpoint:"",clientId:"",redirectUrl:"",logoutRedirectUrl:"",scopes:[]};class M{tokenProvider;cacheManager;cookiesManager;clientId;redirectUrl;constructor(e){const{config:t=X}=e;if(this.redirectUrl=t.redirectUrl,t.configurationEndpoint==null||t.configurationEndpoint=="")throw new Error("Configuration endpoint not defined");if(t.clientId==null||t.clientId=="")throw new Error("Consumer key is not defined");this.cookiesManager=new z({clientId:t.clientId});const i=this.cookiesManager.get(),o=new c.OpenIdEndpointProvider(t.configurationEndpoint);let r=new c.AuthorizationCodeGrantTokenProvider(o,t.clientId,t.redirectUrl).WithScopes(t.scopes);t.logoutRedirectUrl&&(r=r.WithLogoutRedirect(t.logoutRedirectUrl)),i?.code_verifier!=null&&(r=r.WithProofKeyForCodeExchange(i.code_verifier)),this.tokenProvider=r,this.cacheManager=new H,this.clientId=t.clientId,c.AnalyticsHttpClient.sendInitEvent("TIDClient",this.clientId,h,g),this.cleanupExpiredState()}cleanupExpiredState(){try{const e=this.cookiesManager.getStatePayload();if(e){const t=atob(e),i=JSON.parse(t);Date.now()-i.timestamp>S&&this.cookiesManager.clearStatePayload()}}catch{this.cookiesManager.clearStatePayload()}}async loginWithRedirect(e){c.AnalyticsHttpClient.sendMethodEvent(this.loginWithRedirect.name,this.clientId,h,g);const{onRedirect:t}=e||{},i=window.location.pathname+window.location.search,o=this.createStatePayload(i);this.cookiesManager.save({state_payload:o});const r=c.AuthorizationCodeGrantTokenProvider.GenerateCodeVerifier();this.cookiesManager.save({code_verifier:r}),this.tokenProvider=this.tokenProvider.WithProofKeyForCodeExchange(r);const u=await this.tokenProvider.GetOAuthRedirect(o);t!=null?t(u):window.location.assign(u)}async handleCallback(e=window.location.href){const t=this.cookiesManager.get();if(t==null||t?.code_verifier==null)throw new Q("Code verifier not available");const i=$(e),o=P(e),r=o.get("identity_provider")??"",u=o.get("state")??"",f=this.validateStatePayload(u);if(!f.isValid)throw new Error(`State validation failed: ${f.error}`);return await this.tokenProvider.ValidateQuery(i),await this.generateToken(r),{authState:u,returnTo:f.redirectTo}}async generateToken(e){const t=await this.tokenProvider.RetrieveToken(),i=await this.tokenProvider.RetrieveRefreshToken(),o=await this.tokenProvider.RetrieveIdToken(),r=await this.tokenProvider.RetrieveTokenExpiry(),f=new Date(r).getTime(),y=this.tokenProvider?._scopes?.join(" ");await this.cacheManager.setToken({scope:y,state:"",session_state:"",identity_provider:e,token_type:"bearer",access_token:t,refresh_token:i,id_token:o,expires_at:f});const I=K(o),w=B(I);await this.cacheManager.setUser(w),await this.reloadCodeVerifier()}async reloadCodeVerifier(){const e=await this.tokenProvider.RetrieveCodeVerifier();this.cookiesManager.save({code_verifier:e}),this.tokenProvider=this.tokenProvider.WithProofKeyForCodeExchange(e)}createStatePayload(e){const t=this.generateNonce(),i=Date.now();return btoa(JSON.stringify({redirectTo:e,timestamp:i,nonce:t}))}generateNonce(){const e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}validateStatePayload(e){try{if(!e||e.trim()==="")return{isValid:!1,error:"Empty state parameter"};const t=this.cookiesManager.getStatePayload();if(!t)return{isValid:!1,error:"No stored state found"};const i=atob(e),o=JSON.parse(i),r=atob(t),u=JSON.parse(r);if(!o.nonce||!o.timestamp||!o.redirectTo)return{isValid:!1,error:"Invalid state payload structure"};if(o.nonce!==u.nonce)return{isValid:!1,error:"State nonce mismatch"};const y=Date.now()-o.timestamp;return y>S?{isValid:!1,error:"State expired - possible replay attack"}:y<0?{isValid:!1,error:"State timestamp is in the future - possible replay attack"}:(this.cookiesManager.clearStatePayload(),{isValid:!0,redirectTo:o.redirectTo})}catch{return{isValid:!1,error:"Invalid state format"}}}async getUser(){return c.AnalyticsHttpClient.sendMethodEvent(this.getUser.name,this.clientId,h,g),await this.cacheManager.getUser()}async getAccessTokenSilently(){c.AnalyticsHttpClient.sendMethodEvent(this.getAccessTokenSilently.name,this.clientId,h,g);let e=await this.cacheManager.getToken();if(e==null)throw c.AnalyticsHttpClient.sendExceptionEvent(this.getAccessTokenSilently.name,"No token available",this.clientId,h,g),new A("No token available");const t=new Date(new Date().getTime()+E);if(e?.expires_at==null||e?.expires_at<t.getTime()){try{await this.tokenProvider.RetrieveToken()}catch(i){throw c.AnalyticsHttpClient.sendExceptionEvent(this.getAccessTokenSilently.name,i.message,this.clientId,h,g),new _(i.message)}await this.generateToken(e?.identity_provider??""),e=await this.cacheManager.getToken()}return e?.access_token||""}async getTokens(){c.AnalyticsHttpClient.sendMethodEvent(this.getTokens.name,this.clientId,h,g);let e=await this.cacheManager.getToken();if(e==null)throw c.AnalyticsHttpClient.sendExceptionEvent(this.getTokens.name,"No token available",this.clientId,h,g),new A("No token available");const t=new Date(new Date().getTime()+E);if(e?.expires_at==null||e?.expires_at<t.getTime()){try{await this.tokenProvider.RetrieveToken()}catch(i){throw c.AnalyticsHttpClient.sendExceptionEvent(this.getTokens.name,i.message,this.clientId,h,g),new _(i.message)}await this.generateToken(e?.identity_provider??""),e=await this.cacheManager.getToken()}return{access_token:e?.access_token||"",expires_at:e?.expires_at||0,id_token:e?.id_token||""}}async logout(e){c.AnalyticsHttpClient.sendMethodEvent(this.logout.name,this.clientId,h,g);const{onRedirect:t,disabledAutoRedirect:i}=e||{};this.cacheManager&&await this.cacheManager.clear(),this.cookiesManager&&this.cookiesManager.clear();const o=await this.tokenProvider.GetOAuthLogoutRedirect("state");if(t!=null)return t(o);i||window.location.assign(o)}async checkSession(){try{await this.getAccessTokenSilently()}catch{return!1}return!0}async loadUserSession(){await this.loadCacheSessionIntoSDK(),await this.checkSession()||await this.cacheManager.clear()}async loadCacheSessionIntoSDK(){const e=await this.cacheManager.getToken();if(e==null)return;const t=e.access_token,i=e.refresh_token||"",o=e.id_token,r=e.expires_at;this.tokenProvider=this.tokenProvider.WithAccessToken(t,r).WithRefreshToken(i).WithIdToken(o)}getBearerTokenHttpClient(e){return new c.BearerTokenHttpClientProvider(this.tokenProvider,e)}getRedirectUrl(){return this.redirectUrl}}const T=l.createContext(null),R=()=>l.useContext(T)??{},Y=(n,e)=>{switch(e.type){case"INIT":return{...n,isLoading:!1,isAuthenticated:e.user!=null,user:e.user,error:void 0};case"GET_TOKENS_COMPLETE":case"HANDLE_CALLBACK_COMPLETE":case"GET_ACCESS_TOKEN_COMPLETE":return{...n,isLoading:!1,isAuthenticated:e.user!=null,user:e.user,error:void 0};case"LOGOUT":return{...n,isAuthenticated:!1,user:void 0};case"ERROR":return{...n,isLoading:!1,error:e.error}}},Z={isLoading:!0,isAuthenticated:!1},ee=n=>{if(n==null||Object.keys(n).length<=0)return!0;const e=Object.keys(n);for(const t of e)if(n[t]!=null&&n[t]!=="")return!1;return!0},te=n=>!ee(n.config),ne=n=>{const{children:e,configurationEndpoint:t,clientId:i,redirectUrl:o,logoutRedirectUrl:r,scopes:u,onRedirectCallback:f,checkRedirectUrlMatch:y}=n;if(l.useContext(T)!=null)throw new Error("TID Provider already defined");const w={config:{configurationEndpoint:t??"",clientId:i??"",redirectUrl:o??"",logoutRedirectUrl:r??"",scopes:u??[""]}},[a]=l.useState(n.tidClient??new M(w)),[x,p]=l.useReducer(Y,Z),O=l.useRef(!1),ae=l.useMemo(()=>y?a.getRedirectUrl():void 0,[y,a]);l.useEffect(()=>{O.current||(n.tidClient!=null&&te({config:{configurationEndpoint:t,clientId:i,redirectUrl:o,logoutRedirectUrl:r,scopes:u}})&&console.warn("When TID client is pass as prop, any client configuration property sent directly to the TID Provider component will be ignored"),O.current=!0,(async()=>{try{let s;if(q(void 0,ae)){const k=await a.handleCallback();s=await a.getUser(),f?.(k)}else await a.loadUserSession(),s=await a.getUser();p({type:"INIT",user:s})}catch(s){let k=s;typeof s=="string"&&(k=new Error(s)),p({type:"ERROR",error:k})}})())},[a,f]);const D=l.useCallback(async()=>{const s=await a.getAccessTokenSilently(),k=await a.getUser();return p({type:"GET_ACCESS_TOKEN_COMPLETE",user:k}),s},[a]),U=l.useCallback(async()=>{const s=await a.getTokens(),k=await a.getUser();return p({type:"GET_TOKENS_COMPLETE",user:k}),s},[a]),L=l.useCallback(async s=>{await a.loginWithRedirect(s)},[a]),N=l.useCallback(async s=>{await a.logout(s),s?.disabledAutoRedirect!=null&&s.disabledAutoRedirect&&p({type:"LOGOUT"})},[a]),V=l.useCallback(async s=>{const k=await a.handleCallback(s),ce=await a.getUser();return p({type:"HANDLE_CALLBACK_COMPLETE",user:ce}),k},[a]),se=l.useMemo(()=>({...x,getAccessTokenSilently:D,getTokens:U,loginWithRedirect:L,handleCallback:V,logout:N}),[x,D,U,L,V,N]);return m.jsx(T.Provider,{value:se,children:e})},ie=R,oe=ne,re=({renderComponent:n,loader:e})=>{const{isAuthenticated:t,isLoading:i,loginWithRedirect:o}=R();return l.useEffect(()=>{!i&&!t&&(async()=>await o())()},[i,t,o]),t?n:e||m.jsx(m.Fragment,{})};d.AuthenticationGuard=re,d.TIDClient=M,d.TIDContext=T,d.TIDProvider=oe,d.useAuth=ie,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@trimble-oss/trimble-id-react",
3
3
  "private": false,
4
- "version": "1.0.1",
4
+ "version": "1.0.2-rc1",
5
5
  "homepage": "https://github.com/trimble-oss/trimble-id-sdk-docs-for-react",
6
6
  "author": "Trimble developers <developers@trimble.com>",
7
7
  "license": "MIT",
@@ -14,8 +14,8 @@
14
14
  "build": "tsc && vite build",
15
15
  "test": "jest --coverage",
16
16
  "docs": "typedoc --out ./docs/documentation ./src/ --tsconfig ./tsconfig.json",
17
- "lint": "eslint --ext ts,tsx --report-unused-disable-directives",
18
- "lint:fix": "eslint --fix 'src/**/*.{jsx,ts,tsx}'",
17
+ "lint": "eslint src/",
18
+ "lint:fix": "eslint --fix src/",
19
19
  "format": "prettier --write src//**/*.{ts,tsx,css} --config ./.prettierrc",
20
20
  "prepare": "husky install"
21
21
  },
@@ -31,7 +31,7 @@
31
31
  "module": "./dist/trimble-id-react.es.js",
32
32
  "types": "./dist/index.d.ts",
33
33
  "dependencies": {
34
- "@trimble-oss/trimble-id": "^0.0.7",
34
+ "@trimble-oss/trimble-id": "^1.0.0",
35
35
  "es-cookie": "^1.4.0",
36
36
  "husky": "^8.0.3",
37
37
  "jwt-decode": "^3.1.2"
@@ -42,29 +42,30 @@
42
42
  },
43
43
  "devDependencies": {
44
44
  "@babel/preset-env": "^7.22.20",
45
+ "@eslint/js": "^9.37.0",
45
46
  "@testing-library/react": "^14.0.0",
46
47
  "@types/jest": "^29.5.3",
47
48
  "@types/react": "^18.2.15",
48
49
  "@types/react-dom": "^18.2.7",
49
- "@typescript-eslint/eslint-plugin": "^6.2.0",
50
- "@typescript-eslint/parser": "^6.2.0",
51
- "@vitejs/plugin-react": "^4.0.3",
50
+ "@vitejs/plugin-react": "^5.1.2",
52
51
  "babel-jest": "^29.7.0",
53
- "eslint": "^8.45.0",
54
- "eslint-config-prettier": "^8.9.0",
55
- "eslint-plugin-prettier": "^5.0.0",
56
- "eslint-plugin-react": "^7.33.0",
57
- "eslint-plugin-react-hooks": "^4.6.0",
58
- "eslint-plugin-react-refresh": "^0.4.3",
59
- "gts": "^5.0.0",
52
+ "eslint": "^9.37.0",
53
+ "eslint-config-prettier": "^10.1.8",
54
+ "eslint-plugin-prettier": "^5.5.4",
55
+ "eslint-plugin-react": "^7.37.5",
56
+ "eslint-plugin-react-hooks": "^5.2.0",
57
+ "eslint-plugin-react-refresh": "^0.4.26",
58
+ "globals": "^16.2.0",
59
+ "gts": "^7.0.0",
60
+ "typescript-eslint": "^8.46.0",
60
61
  "jest": "^29.6.2",
61
62
  "jest-environment-jsdom": "^29.6.2",
62
- "lint-staged": "^13.2.3",
63
+ "lint-staged": "^16.2.7",
63
64
  "prettier": "^3.0.0",
64
65
  "ts-jest": "^29.1.1",
65
66
  "typedoc": "^0.25.2",
66
67
  "typescript": "^5.0.2",
67
- "vite": "^4.4.5",
68
+ "vite": "^7.3.0",
68
69
  "vite-plugin-dts": "^1.4.1",
69
70
  "vite-plugin-linter": "^1.2.0",
70
71
  "vite-tsconfig-paths": "^3.5.0"