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

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.
@@ -114,13 +114,13 @@ const x = 5 * 6e4, j = ["code", "state"], A = 600 * 1e3, U = (o) => o.split("?")
114
114
  return new URLSearchParams(e);
115
115
  }, te = (o = window.location.href, e) => {
116
116
  if (e != null) {
117
- const r = U(e), n = U(o ?? "");
118
- if (r !== n)
117
+ const n = U(e), r = U(o ?? "");
118
+ if (n !== r)
119
119
  return !1;
120
120
  }
121
121
  const t = b(o);
122
- for (const r of j)
123
- if (!t.has(r))
122
+ for (const n of j)
123
+ if (!t.has(n))
124
124
  return !1;
125
125
  return !0;
126
126
  }, oe = (o) => ({
@@ -132,8 +132,8 @@ const x = 5 * 6e4, j = ["code", "state"], A = 600 * 1e3, U = (o) => o.split("?")
132
132
  email: o.email,
133
133
  email_verified: o.email_verified,
134
134
  ...o.account_id && { account_id: o.account_id }
135
- }), re = "@TID_COOKIE";
136
- class ne {
135
+ }), ne = "@TID_COOKIE";
136
+ class re {
137
137
  /**
138
138
  * Retrieve a cookie from the browser
139
139
  * @param {string} key - Key to retrieve the cookies
@@ -154,12 +154,12 @@ class ne {
154
154
  * @example Save cookies with a custom domain
155
155
  * cookiesStorage.set('key',{data:{...}},{domain:'https://example.com/subpath'})
156
156
  */
157
- set(e, t, r) {
158
- let n = {};
159
- window.location.protocol === "https:" && (n = {
157
+ set(e, t, n) {
158
+ let r = {};
159
+ window.location.protocol === "https:" && (r = {
160
160
  secure: !0,
161
161
  sameSite: "none"
162
- }), r?.expires && (n.expires = r.expires), r?.domain && (n.domain = r.domain), m.set(e, JSON.stringify(t), n);
162
+ }), n?.expires && (r.expires = n.expires), n?.domain && (r.domain = n.domain), m.set(e, JSON.stringify(t), r);
163
163
  }
164
164
  /**
165
165
  * Remove a cookie from the browser
@@ -171,8 +171,8 @@ class ne {
171
171
  * cookiesStorage.remove('key',{domain:'https://example.com/subpath'})
172
172
  */
173
173
  remove(e, t) {
174
- const r = {};
175
- t?.domain && (r.domain = t.domain), m.remove(e, r);
174
+ const n = {};
175
+ t?.domain && (n.domain = t.domain), m.remove(e, n);
176
176
  }
177
177
  }
178
178
  class ie {
@@ -191,15 +191,15 @@ class ie {
191
191
  * @param {CookiesManagerOptions} options - Configuration for the managing the cookies
192
192
  */
193
193
  constructor(e) {
194
- this.cookieKey = `${re}.${e.clientId}`, this.cookiesStorage = new ne();
194
+ this.cookieKey = `${ne}.${e.clientId}`, this.cookiesStorage = new re();
195
195
  }
196
196
  /**
197
197
  * Store cookies in the browser
198
198
  * @param {Partial<CookieValue>} value - information to store
199
199
  */
200
200
  save(e) {
201
- const r = { ...this.get() || {}, ...e };
202
- this.cookiesStorage.set(this.cookieKey, r, {
201
+ const n = { ...this.get() || {}, ...e };
202
+ this.cookiesStorage.set(this.cookieKey, n, {
203
203
  expires: 1
204
204
  });
205
205
  }
@@ -241,7 +241,7 @@ class D extends Error {
241
241
  }
242
242
  class ae extends Error {
243
243
  }
244
- const u = "@trimble-oss/trimble-id-react", g = "1.0.2-rc1", se = {
244
+ const u = "@trimble-oss/trimble-id-react", g = "1.0.2", se = {
245
245
  configurationEndpoint: "",
246
246
  clientId: "",
247
247
  redirectUrl: "",
@@ -287,13 +287,13 @@ class ce {
287
287
  this.cookiesManager = new ie({
288
288
  clientId: t.clientId
289
289
  });
290
- const r = this.cookiesManager.get(), n = new $(t.configurationEndpoint);
290
+ const n = this.cookiesManager.get(), r = new $(t.configurationEndpoint);
291
291
  let i = new R(
292
- n,
292
+ r,
293
293
  t.clientId,
294
294
  t.redirectUrl
295
295
  ).WithScopes(t.scopes);
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();
296
+ t.logoutRedirectUrl && (i = i.WithLogoutRedirect(t.logoutRedirectUrl)), n?.code_verifier != null && (i = i.WithProofKeyForCodeExchange(n.code_verifier)), this.tokenProvider = i, this.cacheManager = new Z(), this.clientId = t.clientId, h.sendInitEvent("TIDClient", this.clientId, u, g), this.cleanupExpiredState();
297
297
  }
298
298
  /**
299
299
  * Clean up expired state payloads to prevent storage bloat
@@ -302,8 +302,8 @@ class ce {
302
302
  try {
303
303
  const e = this.cookiesManager.getStatePayload();
304
304
  if (e) {
305
- const t = atob(e), r = JSON.parse(t);
306
- Date.now() - r.timestamp > A && this.cookiesManager.clearStatePayload();
305
+ const t = atob(e), n = JSON.parse(t);
306
+ Date.now() - n.timestamp > A && this.cookiesManager.clearStatePayload();
307
307
  }
308
308
  } catch {
309
309
  this.cookiesManager.clearStatePayload();
@@ -324,11 +324,11 @@ class ce {
324
324
  */
325
325
  async loginWithRedirect(e) {
326
326
  h.sendMethodEvent(this.loginWithRedirect.name, this.clientId, u, g);
327
- const { onRedirect: t } = e || {}, r = window.location.pathname + window.location.search, n = this.createStatePayload(r);
328
- this.cookiesManager.save({ state_payload: n });
327
+ const { onRedirect: t } = e || {}, n = window.location.pathname + window.location.search, r = this.createStatePayload(n);
328
+ this.cookiesManager.save({ state_payload: r });
329
329
  const i = R.GenerateCodeVerifier();
330
330
  this.cookiesManager.save({ code_verifier: i }), this.tokenProvider = this.tokenProvider.WithProofKeyForCodeExchange(i);
331
- const c = await this.tokenProvider.GetOAuthRedirect(n);
331
+ const c = await this.tokenProvider.GetOAuthRedirect(r);
332
332
  t != null ? t(c) : window.location.assign(c);
333
333
  }
334
334
  /**
@@ -348,10 +348,10 @@ class ce {
348
348
  const t = this.cookiesManager.get();
349
349
  if (t == null || t?.code_verifier == null)
350
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);
351
+ const n = ee(e), r = b(e), i = r.get("identity_provider") ?? "", c = r.get("state") ?? "", d = this.validateStatePayload(c);
352
352
  if (!d.isValid)
353
353
  throw new Error(`State validation failed: ${d.error}`);
354
- return await this.tokenProvider.ValidateQuery(r), await this.generateToken(i), {
354
+ return await this.tokenProvider.ValidateQuery(n), await this.generateToken(i), {
355
355
  authState: c,
356
356
  returnTo: d.redirectTo
357
357
  };
@@ -362,7 +362,7 @@ class ce {
362
362
  * @return {Promise<void>} Empty promise
363
363
  */
364
364
  async generateToken(e) {
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(" ");
365
+ const t = await this.tokenProvider.RetrieveToken(), n = await this.tokenProvider.RetrieveRefreshToken(), r = await this.tokenProvider.RetrieveIdToken(), i = await this.tokenProvider.RetrieveTokenExpiry(), d = new Date(i).getTime(), k = this.tokenProvider?._scopes?.join(" ");
366
366
  await this.cacheManager.setToken({
367
367
  scope: k,
368
368
  state: "",
@@ -370,11 +370,11 @@ class ce {
370
370
  identity_provider: e,
371
371
  token_type: "bearer",
372
372
  access_token: t,
373
- refresh_token: r,
374
- id_token: n,
373
+ refresh_token: n,
374
+ id_token: r,
375
375
  expires_at: d
376
376
  });
377
- const v = J(n), p = oe(v);
377
+ const v = J(r), p = oe(v);
378
378
  await this.cacheManager.setUser(p), await this.reloadCodeVerifier();
379
379
  }
380
380
  async reloadCodeVerifier() {
@@ -387,10 +387,10 @@ class ce {
387
387
  * @return {string} - Base64 encoded state payload
388
388
  */
389
389
  createStatePayload(e) {
390
- const t = this.generateNonce(), r = Date.now();
390
+ const t = this.generateNonce(), n = Date.now();
391
391
  return btoa(JSON.stringify({
392
392
  redirectTo: e,
393
- timestamp: r,
393
+ timestamp: n,
394
394
  nonce: t
395
395
  }));
396
396
  }
@@ -414,18 +414,18 @@ class ce {
414
414
  const t = this.cookiesManager.getStatePayload();
415
415
  if (!t)
416
416
  return { isValid: !1, error: "No stored state found" };
417
- const r = atob(e), n = JSON.parse(r), i = atob(t), c = JSON.parse(i);
418
- if (!n.nonce || !n.timestamp || !n.redirectTo)
417
+ const n = atob(e), r = JSON.parse(n), i = atob(t), c = JSON.parse(i);
418
+ if (!r.nonce || !r.timestamp || !r.redirectTo)
419
419
  return { isValid: !1, error: "Invalid state payload structure" };
420
- if (n.nonce !== c.nonce)
420
+ if (r.nonce !== c.nonce)
421
421
  return { isValid: !1, error: "State nonce mismatch" };
422
- const k = Date.now() - n.timestamp;
422
+ const k = Date.now() - r.timestamp;
423
423
  return k > A ? { isValid: !1, error: "State expired - possible replay attack" } : k < 0 ? {
424
424
  isValid: !1,
425
425
  error: "State timestamp is in the future - possible replay attack"
426
426
  } : (this.cookiesManager.clearStatePayload(), {
427
427
  isValid: !0,
428
- redirectTo: n.redirectTo
428
+ redirectTo: r.redirectTo
429
429
  });
430
430
  } catch {
431
431
  return { isValid: !1, error: "Invalid state format" };
@@ -465,14 +465,14 @@ class ce {
465
465
  if (e?.expires_at == null || e?.expires_at < t.getTime()) {
466
466
  try {
467
467
  await this.tokenProvider.RetrieveToken();
468
- } catch (r) {
468
+ } catch (n) {
469
469
  throw h.sendExceptionEvent(
470
470
  this.getAccessTokenSilently.name,
471
- r.message,
471
+ n.message,
472
472
  this.clientId,
473
473
  u,
474
474
  g
475
- ), new O(r.message);
475
+ ), new O(n.message);
476
476
  }
477
477
  await this.generateToken(e?.identity_provider ?? ""), e = await this.cacheManager.getToken();
478
478
  }
@@ -500,14 +500,14 @@ class ce {
500
500
  if (e?.expires_at == null || e?.expires_at < t.getTime()) {
501
501
  try {
502
502
  await this.tokenProvider.RetrieveToken();
503
- } catch (r) {
503
+ } catch (n) {
504
504
  throw h.sendExceptionEvent(
505
505
  this.getTokens.name,
506
- r.message,
506
+ n.message,
507
507
  this.clientId,
508
508
  u,
509
509
  g
510
- ), new O(r.message);
510
+ ), new O(n.message);
511
511
  }
512
512
  await this.generateToken(e?.identity_provider ?? ""), e = await this.cacheManager.getToken();
513
513
  }
@@ -531,12 +531,12 @@ class ce {
531
531
  */
532
532
  async logout(e) {
533
533
  h.sendMethodEvent(this.logout.name, this.clientId, u, g);
534
- const { onRedirect: t, disabledAutoRedirect: r } = e || {};
534
+ const { onRedirect: t, disabledAutoRedirect: n } = e || {};
535
535
  this.cacheManager && await this.cacheManager.clear(), this.cookiesManager && this.cookiesManager.clear();
536
- const n = await this.tokenProvider.GetOAuthLogoutRedirect("state");
536
+ const r = await this.tokenProvider.GetOAuthLogoutRedirect("state");
537
537
  if (t != null)
538
- return t(n);
539
- r || window.location.assign(n);
538
+ return t(r);
539
+ n || window.location.assign(r);
540
540
  }
541
541
  /**
542
542
  * Check if the user still has a valid session
@@ -565,8 +565,8 @@ class ce {
565
565
  const e = await this.cacheManager.getToken();
566
566
  if (e == null)
567
567
  return;
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);
568
+ const t = e.access_token, n = e.refresh_token || "", r = e.id_token, i = e.expires_at;
569
+ this.tokenProvider = this.tokenProvider.WithAccessToken(t, i).WithRefreshToken(n).WithIdToken(r);
570
570
  }
571
571
  /**
572
572
  * Get a http bearer token client to use it for another SDK (Ex: Processing framework)
@@ -631,8 +631,8 @@ const T = H(null), K = () => L(T) ?? {}, de = (o, e) => {
631
631
  const {
632
632
  children: e,
633
633
  configurationEndpoint: t,
634
- clientId: r,
635
- redirectUrl: n,
634
+ clientId: n,
635
+ redirectUrl: r,
636
636
  logoutRedirectUrl: i,
637
637
  scopes: c,
638
638
  onRedirectCallback: d,
@@ -643,8 +643,8 @@ const T = H(null), K = () => L(T) ?? {}, de = (o, e) => {
643
643
  const p = {
644
644
  config: {
645
645
  configurationEndpoint: t ?? "",
646
- clientId: r ?? "",
647
- redirectUrl: n ?? "",
646
+ clientId: n ?? "",
647
+ redirectUrl: r ?? "",
648
648
  logoutRedirectUrl: i ?? "",
649
649
  scopes: c ?? [""]
650
650
  }
@@ -656,8 +656,8 @@ const T = H(null), K = () => L(T) ?? {}, de = (o, e) => {
656
656
  E.current || (o.tidClient != null && ue({
657
657
  config: {
658
658
  configurationEndpoint: t,
659
- clientId: r,
660
- redirectUrl: n,
659
+ clientId: n,
660
+ redirectUrl: r,
661
661
  logoutRedirectUrl: i,
662
662
  scopes: c
663
663
  }
@@ -724,10 +724,10 @@ const T = H(null), K = () => L(T) ?? {}, de = (o, e) => {
724
724
  );
725
725
  return /* @__PURE__ */ V(T.Provider, { value: G, children: e });
726
726
  }, me = K, Te = ge, ve = ({ renderComponent: o, loader: e }) => {
727
- const { isAuthenticated: t, isLoading: r, loginWithRedirect: n } = K();
727
+ const { isAuthenticated: t, isLoading: n, loginWithRedirect: r } = K();
728
728
  return N(() => {
729
- !r && !t && (async () => await n())();
730
- }, [r, t, n]), t ? o : e || /* @__PURE__ */ V(z, {});
729
+ !n && !t && (async () => await r())();
730
+ }, [n, t, r]), t ? o : e || /* @__PURE__ */ V(z, {});
731
731
  };
732
732
  export {
733
733
  ve as AuthenticationGuard,
@@ -1 +1 @@
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"})}));
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",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.2-rc1",
4
+ "version": "1.0.2",
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",