@osdk/oauth 1.1.0-beta.7 → 1.1.0-beta.8

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/browser/common.d.ts +4 -3
  3. package/build/browser/common.d.ts.map +1 -1
  4. package/build/browser/common.js +13 -9
  5. package/build/browser/common.js.map +1 -1
  6. package/build/browser/common.test.d.ts +2 -0
  7. package/build/browser/common.test.d.ts.map +1 -0
  8. package/build/browser/common.test.js +64 -0
  9. package/build/browser/common.test.js.map +1 -0
  10. package/build/browser/createConfidentialOauthClient.d.ts.map +1 -1
  11. package/build/browser/createConfidentialOauthClient.js +1 -1
  12. package/build/browser/createConfidentialOauthClient.js.map +1 -1
  13. package/build/browser/createPublicOauthClient.d.ts +4 -0
  14. package/build/browser/createPublicOauthClient.d.ts.map +1 -1
  15. package/build/browser/createPublicOauthClient.js +7 -4
  16. package/build/browser/createPublicOauthClient.js.map +1 -1
  17. package/build/browser/publicOauth.test.js +79 -21
  18. package/build/browser/publicOauth.test.js.map +1 -1
  19. package/build/browser/utils.d.ts +4 -2
  20. package/build/browser/utils.d.ts.map +1 -1
  21. package/build/browser/utils.js +2 -1
  22. package/build/browser/utils.js.map +1 -1
  23. package/build/esm/common.d.ts +4 -3
  24. package/build/esm/common.d.ts.map +1 -1
  25. package/build/esm/common.js +13 -9
  26. package/build/esm/common.js.map +1 -1
  27. package/build/esm/common.test.d.ts +2 -0
  28. package/build/esm/common.test.d.ts.map +1 -0
  29. package/build/esm/common.test.js +64 -0
  30. package/build/esm/common.test.js.map +1 -0
  31. package/build/esm/createConfidentialOauthClient.d.ts.map +1 -1
  32. package/build/esm/createConfidentialOauthClient.js +1 -1
  33. package/build/esm/createConfidentialOauthClient.js.map +1 -1
  34. package/build/esm/createPublicOauthClient.d.ts +4 -0
  35. package/build/esm/createPublicOauthClient.d.ts.map +1 -1
  36. package/build/esm/createPublicOauthClient.js +7 -4
  37. package/build/esm/createPublicOauthClient.js.map +1 -1
  38. package/build/esm/publicOauth.test.js +79 -21
  39. package/build/esm/publicOauth.test.js.map +1 -1
  40. package/build/esm/utils.d.ts +4 -2
  41. package/build/esm/utils.d.ts.map +1 -1
  42. package/build/esm/utils.js +2 -1
  43. package/build/esm/utils.js.map +1 -1
  44. package/package.json +4 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @osdk/oauth
2
2
 
3
+ ## 1.1.0-beta.8
4
+
5
+ ### Minor Changes
6
+
7
+ - 02685ab: Adding return types to functions.
8
+ - 696c59c: Enables additional metadata to be required to match a refresh token in local storage
9
+
3
10
  ## 1.1.0-beta.7
4
11
 
5
12
  ### Minor Changes
@@ -1,9 +1,10 @@
1
1
  import type { AuthorizationServer, Client, HttpRequestOptions, OAuth2TokenEndpointResponse } from "oauth4webapi";
2
2
  import type { BaseOauthClient, Events } from "./BaseOauthClient.js";
3
3
  import type { Token } from "./Token.js";
4
- export type LocalStorageState = {
4
+ export interface LocalStorageState {
5
5
  refresh_token?: string;
6
- };
6
+ refreshTokenMarker?: string;
7
+ }
7
8
  export type SessionStorageState = {
8
9
  codeVerifier?: never;
9
10
  state?: never;
@@ -23,7 +24,7 @@ export declare function readLocal(client: Client): LocalStorageState;
23
24
  export declare function saveSession(client: Client, x: SessionStorageState): void;
24
25
  export declare function removeSession(client: Client): void;
25
26
  export declare function readSession(client: Client): SessionStorageState;
26
- export declare function common<R extends undefined | (() => Promise<Token | undefined>)>(client: Client, as: AuthorizationServer, _signIn: () => Promise<Token>, oauthHttpOptions: HttpRequestOptions, refresh: R): {
27
+ export declare function common<R extends undefined | (() => Promise<Token | undefined>)>(client: Client, as: AuthorizationServer, _signIn: () => Promise<Token>, oauthHttpOptions: HttpRequestOptions, refresh: R, refreshTokenMarker: string | undefined): {
27
28
  getToken: BaseOauthClient<keyof Events & string> & {
28
29
  refresh: R;
29
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/common.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EACN,kBAAkB,EAClB,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAwBxC,MAAM,MAAM,iBAAiB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,MAAM,mBAAmB,GAE3B;IACA,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB,CAAC;AAEJ,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAMpE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAQ3D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,mBAAmB,QAMjE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,QAK3C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAQ/D;AAED,wBAAgB,MAAM,CACpB,CAAC,SAAS,SAAS,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,EAExD,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,mBAAmB,EACvB,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EAC7B,gBAAgB,EAAE,kBAAkB,EACpC,OAAO,EAAE,CAAC,GACT;IACD,QAAQ,EAAE,eAAe,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC,CAAA;KAAE,CAAC;IAClE,uBAAuB,EAAE,CACvB,IAAI,EAAE,2BAA2B,EACjC,IAAI,EAAE,QAAQ,GAAG,SAAS,KACvB,KAAK,CAAC;CACZ,CA0GA;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,QAAQ,CACT,IAAI,CACF,mBAAmB,EACjB,QAAQ,GACR,gBAAgB,GAChB,wBAAwB,GACxB,qBAAqB,CACxB,CACF,CAQA"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/common.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EACN,kBAAkB,EAClB,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAwBxC,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,mBAAmB,GAE3B;IACA,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB,CAAC;AAMJ,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAMpE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAQ3D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAMxE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKlD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAQ/D;AAED,wBAAgB,MAAM,CACpB,CAAC,SAAS,SAAS,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,EAExD,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,mBAAmB,EACvB,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,EAC7B,gBAAgB,EAAE,kBAAkB,EACpC,OAAO,EAAE,CAAC,EACV,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC;IACD,QAAQ,EAAE,eAAe,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC,CAAA;KAAE,CAAC;IAClE,uBAAuB,EAAE,CACvB,IAAI,EAAE,2BAA2B,EACjC,IAAI,EAAE,QAAQ,GAAG,SAAS,KACvB,KAAK,CAAC;CACZ,CA6GA;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,QAAQ,CACT,IAAI,CACF,mBAAmB,EACjB,QAAQ,GACR,gBAAgB,GAChB,wBAAwB,GACxB,qBAAqB,CACxB,CACF,CAQA"}
@@ -20,33 +20,36 @@ import { throwIfError } from "./throwIfError.js";
20
20
  // Node 18 is supposed to have a `CustomEvent` but it is not exposed on `globalThis`
21
21
  // which creates a problem for making a single codebase for node and browser. This polyfill works around it
22
22
  const CustomEvent = globalThis.CustomEvent;
23
+ function localStorageKey(client) {
24
+ return `@osdk/oauth : refresh : ${client.client_id}`;
25
+ }
23
26
  export function saveLocal(client, x) {
24
27
  // MUST `localStorage?` as nodejs does not have localStorage
25
- globalThis.localStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));
28
+ globalThis.localStorage?.setItem(localStorageKey(client), JSON.stringify(x));
26
29
  }
27
30
  export function removeLocal(client) {
28
31
  // MUST `localStorage?` as nodejs does not have localStorage
29
- globalThis.localStorage?.removeItem(`@osdk/oauth : refresh : ${client.client_id}`);
32
+ globalThis.localStorage?.removeItem(localStorageKey(client));
30
33
  }
31
34
  export function readLocal(client) {
32
35
  return JSON.parse(
33
36
  // MUST `localStorage?` as nodejs does not have localStorage
34
- globalThis.localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? "{}");
37
+ globalThis.localStorage?.getItem(localStorageKey(client)) ?? "{}");
35
38
  }
36
39
  export function saveSession(client, x) {
37
40
  // MUST `sessionStorage?` as nodejs does not have sessionStorage
38
- globalThis.sessionStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));
41
+ globalThis.sessionStorage?.setItem(localStorageKey(client), JSON.stringify(x));
39
42
  }
40
43
  export function removeSession(client) {
41
44
  // MUST `sessionStorage?` as nodejs does not have sessionStorage
42
- globalThis.sessionStorage?.removeItem(`@osdk/oauth : refresh : ${client.client_id}`);
45
+ globalThis.sessionStorage?.removeItem(localStorageKey(client));
43
46
  }
44
47
  export function readSession(client) {
45
48
  return JSON.parse(
46
49
  // MUST `sessionStorage?` as nodejs does not have sessionStorage
47
- globalThis.sessionStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? "{}");
50
+ globalThis.sessionStorage?.getItem(localStorageKey(client)) ?? "{}");
48
51
  }
49
- export function common(client, as, _signIn, oauthHttpOptions, refresh) {
52
+ export function common(client, as, _signIn, oauthHttpOptions, refresh, refreshTokenMarker) {
50
53
  let token;
51
54
  const eventTarget = new TypedEventTarget();
52
55
  function makeTokenAndSaveRefresh(resp, type) {
@@ -57,7 +60,8 @@ export function common(client, as, _signIn, oauthHttpOptions, refresh) {
57
60
  } = resp;
58
61
  !(expires_in != null) ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0;
59
62
  saveLocal(client, {
60
- refresh_token
63
+ refresh_token,
64
+ refreshTokenMarker
61
65
  });
62
66
  token = {
63
67
  refresh_token,
@@ -129,7 +133,7 @@ export function common(client, as, _signIn, oauthHttpOptions, refresh) {
129
133
  };
130
134
  }
131
135
  export function createAuthorizationServer(ctxPath, url) {
132
- const issuer = `${new URL(ctxPath, url)}`;
136
+ const issuer = `${new URL(ctxPath, url + "/")}`;
133
137
  return {
134
138
  token_endpoint: `${issuer}/api/oauth2/token`,
135
139
  authorization_endpoint: `${issuer}/api/oauth2/authorize`,
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["processRevocationResponse","revocationRequest","invariant","TypedEventTarget","throwIfError","CustomEvent","globalThis","saveLocal","client","x","localStorage","setItem","client_id","JSON","stringify","removeLocal","removeItem","readLocal","parse","getItem","saveSession","sessionStorage","removeSession","readSession","common","as","_signIn","oauthHttpOptions","refresh","token","eventTarget","makeTokenAndSaveRefresh","resp","type","refresh_token","expires_in","access_token","process","env","NODE_ENV","expires_at","Date","now","dispatchTypedEvent","detail","refreshTimeout","rmTimeout","clearTimeout","restartRefreshTimer","evt","setTimeout","pendingSignIn","signIn","undefined","addEventListener","getTokenOrUndefined","getToken","Object","assign","signOut","result","Event","bind","removeEventListener","createAuthorizationServer","ctxPath","url","issuer","URL","token_endpoint","authorization_endpoint","revocation_endpoint"],"sources":["common.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { processRevocationResponse, revocationRequest } from \"oauth4webapi\";\nimport invariant from \"tiny-invariant\";\nimport { TypedEventTarget } from \"typescript-event-target\";\nimport { throwIfError } from \"./throwIfError.js\";\n// Node 18 is supposed to have a `CustomEvent` but it is not exposed on `globalThis`\n// which creates a problem for making a single codebase for node and browser. This polyfill works around it\nconst CustomEvent = process.env.TARGET === \"browser\"\n ? globalThis.CustomEvent\n : globalThis.CustomEvent\n ?? class CustomEvent extends Event {\n #detail;\n constructor(type, options) {\n super(type, options);\n this.#detail = options?.detail ?? null;\n }\n get detail() {\n return this.#detail;\n }\n };\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));\n}\nexport function removeLocal(client) {\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.removeItem(`@osdk/oauth : refresh : ${client.client_id}`);\n}\nexport function readLocal(client) {\n return JSON.parse(\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`)\n ?? \"{}\");\n}\nexport function saveSession(client, x) {\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));\n}\nexport function removeSession(client) {\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.removeItem(`@osdk/oauth : refresh : ${client.client_id}`);\n}\nexport function readSession(client) {\n return JSON.parse(\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`)\n ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const { refresh_token, expires_in, access_token } = resp;\n invariant(expires_in != null);\n saveLocal(client, { refresh_token });\n token = {\n refresh_token,\n expires_in,\n access_token,\n expires_at: Date.now() + expires_in * 1000,\n };\n eventTarget.dispatchTypedEvent(type, new CustomEvent(type, { detail: token }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout)\n clearTimeout(refreshTimeout);\n }\n function restartRefreshTimer(evt) {\n if (refresh) {\n rmTimeout();\n refreshTimeout = setTimeout(refresh, evt.detail.expires_in * 1000 - 60 * 1000);\n }\n }\n async function signOut() {\n invariant(token, \"not signed in\");\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n // Clean up\n removeLocal(client);\n token = undefined;\n throwIfError(result);\n eventTarget.dispatchTypedEvent(\"signOut\", new Event(\"signOut\"));\n }\n let pendingSignIn;\n async function signIn() {\n if (pendingSignIn) {\n return pendingSignIn;\n }\n try {\n pendingSignIn = _signIn();\n return await pendingSignIn;\n }\n finally {\n pendingSignIn = undefined;\n }\n }\n eventTarget.addEventListener(\"signIn\", restartRefreshTimer);\n eventTarget.addEventListener(\"refresh\", restartRefreshTimer);\n function getTokenOrUndefined() {\n if (!token || Date.now() >= token.expires_at) {\n return undefined;\n }\n return token?.access_token;\n }\n const getToken = Object.assign(async function getToken() {\n if (!token || Date.now() >= token.expires_at) {\n token = await signIn();\n }\n return token?.access_token;\n }, {\n signIn,\n refresh,\n signOut,\n rmTimeout,\n getTokenOrUndefined,\n addEventListener: eventTarget.addEventListener.bind(eventTarget),\n removeEventListener: eventTarget.removeEventListener.bind(eventTarget),\n });\n return { getToken, makeTokenAndSaveRefresh };\n}\nexport function createAuthorizationServer(ctxPath, url) {\n const issuer = `${new URL(ctxPath, url)}`;\n return {\n token_endpoint: `${issuer}/api/oauth2/token`,\n authorization_endpoint: `${issuer}/api/oauth2/authorize`,\n revocation_endpoint: `${issuer}/api/oauth2/revoke_token`,\n issuer,\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"common.js","names":["processRevocationResponse","revocationRequest","invariant","TypedEventTarget","throwIfError","CustomEvent","globalThis","localStorageKey","client","client_id","saveLocal","x","localStorage","setItem","JSON","stringify","removeLocal","removeItem","readLocal","parse","getItem","saveSession","sessionStorage","removeSession","readSession","common","as","_signIn","oauthHttpOptions","refresh","refreshTokenMarker","token","eventTarget","makeTokenAndSaveRefresh","resp","type","refresh_token","expires_in","access_token","process","env","NODE_ENV","expires_at","Date","now","dispatchTypedEvent","detail","refreshTimeout","rmTimeout","clearTimeout","restartRefreshTimer","evt","setTimeout","pendingSignIn","signIn","undefined","addEventListener","getTokenOrUndefined","getToken","Object","assign","signOut","result","Event","bind","removeEventListener","createAuthorizationServer","ctxPath","url","issuer","URL","token_endpoint","authorization_endpoint","revocation_endpoint"],"sources":["common.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { processRevocationResponse, revocationRequest } from \"oauth4webapi\";\nimport invariant from \"tiny-invariant\";\nimport { TypedEventTarget } from \"typescript-event-target\";\nimport { throwIfError } from \"./throwIfError.js\";\n// Node 18 is supposed to have a `CustomEvent` but it is not exposed on `globalThis`\n// which creates a problem for making a single codebase for node and browser. This polyfill works around it\nconst CustomEvent = process.env.TARGET === \"browser\"\n ? globalThis.CustomEvent\n : globalThis.CustomEvent\n ?? class CustomEvent extends Event {\n #detail;\n constructor(type, options) {\n super(type, options);\n this.#detail = options?.detail ?? null;\n }\n get detail() {\n return this.#detail;\n }\n };\nfunction localStorageKey(client) {\n return `@osdk/oauth : refresh : ${client.client_id}`;\n}\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.setItem(localStorageKey(client), JSON.stringify(x));\n}\nexport function removeLocal(client) {\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.removeItem(localStorageKey(client));\n}\nexport function readLocal(client) {\n return JSON.parse(\n // MUST `localStorage?` as nodejs does not have localStorage\n globalThis.localStorage?.getItem(localStorageKey(client))\n ?? \"{}\");\n}\nexport function saveSession(client, x) {\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.setItem(localStorageKey(client), JSON.stringify(x));\n}\nexport function removeSession(client) {\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.removeItem(localStorageKey(client));\n}\nexport function readSession(client) {\n return JSON.parse(\n // MUST `sessionStorage?` as nodejs does not have sessionStorage\n globalThis.sessionStorage?.getItem(localStorageKey(client))\n ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh, refreshTokenMarker) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const { refresh_token, expires_in, access_token } = resp;\n invariant(expires_in != null);\n saveLocal(client, {\n refresh_token,\n refreshTokenMarker,\n });\n token = {\n refresh_token,\n expires_in,\n access_token,\n expires_at: Date.now() + expires_in * 1000,\n };\n eventTarget.dispatchTypedEvent(type, new CustomEvent(type, { detail: token }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout)\n clearTimeout(refreshTimeout);\n }\n function restartRefreshTimer(evt) {\n if (refresh) {\n rmTimeout();\n refreshTimeout = setTimeout(refresh, evt.detail.expires_in * 1000 - 60 * 1000);\n }\n }\n async function signOut() {\n invariant(token, \"not signed in\");\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n // Clean up\n removeLocal(client);\n token = undefined;\n throwIfError(result);\n eventTarget.dispatchTypedEvent(\"signOut\", new Event(\"signOut\"));\n }\n let pendingSignIn;\n async function signIn() {\n if (pendingSignIn) {\n return pendingSignIn;\n }\n try {\n pendingSignIn = _signIn();\n return await pendingSignIn;\n }\n finally {\n pendingSignIn = undefined;\n }\n }\n eventTarget.addEventListener(\"signIn\", restartRefreshTimer);\n eventTarget.addEventListener(\"refresh\", restartRefreshTimer);\n function getTokenOrUndefined() {\n if (!token || Date.now() >= token.expires_at) {\n return undefined;\n }\n return token?.access_token;\n }\n const getToken = Object.assign(async function getToken() {\n if (!token || Date.now() >= token.expires_at) {\n token = await signIn();\n }\n return token?.access_token;\n }, {\n signIn,\n refresh,\n signOut,\n rmTimeout,\n getTokenOrUndefined,\n addEventListener: eventTarget.addEventListener.bind(eventTarget),\n removeEventListener: eventTarget.removeEventListener.bind(eventTarget),\n });\n return { getToken, makeTokenAndSaveRefresh };\n}\nexport function createAuthorizationServer(ctxPath, url) {\n const issuer = `${new URL(ctxPath, url + \"/\")}`;\n return {\n token_endpoint: `${issuer}/api/oauth2/token`,\n authorization_endpoint: `${issuer}/api/oauth2/authorize`,\n revocation_endpoint: `${issuer}/api/oauth2/revoke_token`,\n issuer,\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=common.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.test.d.ts","sourceRoot":"","sources":["../../src/common.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Copyright 2025 Palantir Technologies, Inc. All rights reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
17
+ import { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from "./common.js";
18
+ describe("local functions", () => {
19
+ beforeEach(() => {
20
+ vi.stubGlobal("localStorage", {
21
+ setItem: vi.fn(),
22
+ removeItem: vi.fn(),
23
+ getItem: vi.fn()
24
+ });
25
+ });
26
+ afterEach(() => {
27
+ vi.unstubAllGlobals();
28
+ });
29
+ it("should use the old style keys when there is no refresh token marker", () => {
30
+ const client = {
31
+ client_id: "hi_mom",
32
+ $refreshTokenMarker: undefined
33
+ };
34
+ const oldLocalStorageKey = `@osdk/oauth : refresh : ${client.client_id}`;
35
+ readLocal(client);
36
+ removeLocal(client);
37
+ saveLocal(client, {});
38
+ expect(vi.mocked(globalThis.localStorage.getItem)).toBeCalledWith(oldLocalStorageKey);
39
+ expect(vi.mocked(globalThis.localStorage.setItem)).toBeCalledWith(oldLocalStorageKey, expect.anything());
40
+ expect(vi.mocked(globalThis.localStorage.removeItem)).toBeCalledWith(oldLocalStorageKey);
41
+ });
42
+ it("should save the refreshTokenMaker if it exists", () => {
43
+ const client = {
44
+ client_id: "hi_mom"
45
+ };
46
+ const signIn = vi.fn();
47
+ const refresh = vi.fn();
48
+ const authServer = createAuthorizationServer("multipass", "https://stack.palantir.com");
49
+ const {
50
+ makeTokenAndSaveRefresh
51
+ } = common(client, authServer, signIn, {}, refresh, "marker marker");
52
+ makeTokenAndSaveRefresh({
53
+ refresh_token: "refresh",
54
+ access_token: "access",
55
+ token_type: "idk",
56
+ expires_in: 10_000
57
+ }, "signIn");
58
+ expect(globalThis.localStorage.setItem).toBeCalledWith(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify({
59
+ refresh_token: "refresh",
60
+ refreshTokenMarker: "marker marker"
61
+ }));
62
+ });
63
+ });
64
+ //# sourceMappingURL=common.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.test.js","names":["afterEach","beforeEach","describe","expect","it","vi","common","createAuthorizationServer","readLocal","removeLocal","saveLocal","stubGlobal","setItem","fn","removeItem","getItem","unstubAllGlobals","client","client_id","$refreshTokenMarker","undefined","oldLocalStorageKey","mocked","globalThis","localStorage","toBeCalledWith","anything","signIn","refresh","authServer","makeTokenAndSaveRefresh","refresh_token","access_token","token_type","expires_in","JSON","stringify","refreshTokenMarker"],"sources":["common.test.js"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal, } from \"./common.js\";\ndescribe(\"local functions\", () => {\n beforeEach(() => {\n vi.stubGlobal(\"localStorage\", {\n setItem: vi.fn(),\n removeItem: vi.fn(),\n getItem: vi.fn(),\n });\n });\n afterEach(() => {\n vi.unstubAllGlobals();\n });\n it(\"should use the old style keys when there is no refresh token marker\", () => {\n const client = {\n client_id: \"hi_mom\",\n $refreshTokenMarker: undefined,\n };\n const oldLocalStorageKey = `@osdk/oauth : refresh : ${client.client_id}`;\n readLocal(client);\n removeLocal(client);\n saveLocal(client, {});\n expect(vi.mocked(globalThis.localStorage.getItem)).toBeCalledWith(oldLocalStorageKey);\n expect(vi.mocked(globalThis.localStorage.setItem)).toBeCalledWith(oldLocalStorageKey, expect.anything());\n expect(vi.mocked(globalThis.localStorage.removeItem)).toBeCalledWith(oldLocalStorageKey);\n });\n it(\"should save the refreshTokenMaker if it exists\", () => {\n const client = {\n client_id: \"hi_mom\",\n };\n const signIn = vi.fn();\n const refresh = vi.fn();\n const authServer = createAuthorizationServer(\"multipass\", \"https://stack.palantir.com\");\n const { makeTokenAndSaveRefresh } = common(client, authServer, signIn, {}, refresh, \"marker marker\");\n makeTokenAndSaveRefresh({\n refresh_token: \"refresh\",\n access_token: \"access\",\n token_type: \"idk\",\n expires_in: 10_000,\n }, \"signIn\");\n expect(globalThis.localStorage.setItem).toBeCalledWith(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify({\n refresh_token: \"refresh\",\n refreshTokenMarker: \"marker marker\",\n }));\n });\n});\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,QAAQ;AACxE,SAASC,MAAM,EAAEC,yBAAyB,EAAEC,SAAS,EAAEC,WAAW,EAAEC,SAAS,QAAS,aAAa;AACnGR,QAAQ,CAAC,iBAAiB,EAAE,MAAM;EAC9BD,UAAU,CAAC,MAAM;IACbI,EAAE,CAACM,UAAU,CAAC,cAAc,EAAE;MAC1BC,OAAO,EAAEP,EAAE,CAACQ,EAAE,CAAC,CAAC;MAChBC,UAAU,EAAET,EAAE,CAACQ,EAAE,CAAC,CAAC;MACnBE,OAAO,EAAEV,EAAE,CAACQ,EAAE,CAAC;IACnB,CAAC,CAAC;EACN,CAAC,CAAC;EACFb,SAAS,CAAC,MAAM;IACZK,EAAE,CAACW,gBAAgB,CAAC,CAAC;EACzB,CAAC,CAAC;EACFZ,EAAE,CAAC,qEAAqE,EAAE,MAAM;IAC5E,MAAMa,MAAM,GAAG;MACXC,SAAS,EAAE,QAAQ;MACnBC,mBAAmB,EAAEC;IACzB,CAAC;IACD,MAAMC,kBAAkB,GAAG,2BAA2BJ,MAAM,CAACC,SAAS,EAAE;IACxEV,SAAS,CAACS,MAAM,CAAC;IACjBR,WAAW,CAACQ,MAAM,CAAC;IACnBP,SAAS,CAACO,MAAM,EAAE,CAAC,CAAC,CAAC;IACrBd,MAAM,CAACE,EAAE,CAACiB,MAAM,CAACC,UAAU,CAACC,YAAY,CAACT,OAAO,CAAC,CAAC,CAACU,cAAc,CAACJ,kBAAkB,CAAC;IACrFlB,MAAM,CAACE,EAAE,CAACiB,MAAM,CAACC,UAAU,CAACC,YAAY,CAACZ,OAAO,CAAC,CAAC,CAACa,cAAc,CAACJ,kBAAkB,EAAElB,MAAM,CAACuB,QAAQ,CAAC,CAAC,CAAC;IACxGvB,MAAM,CAACE,EAAE,CAACiB,MAAM,CAACC,UAAU,CAACC,YAAY,CAACV,UAAU,CAAC,CAAC,CAACW,cAAc,CAACJ,kBAAkB,CAAC;EAC5F,CAAC,CAAC;EACFjB,EAAE,CAAC,gDAAgD,EAAE,MAAM;IACvD,MAAMa,MAAM,GAAG;MACXC,SAAS,EAAE;IACf,CAAC;IACD,MAAMS,MAAM,GAAGtB,EAAE,CAACQ,EAAE,CAAC,CAAC;IACtB,MAAMe,OAAO,GAAGvB,EAAE,CAACQ,EAAE,CAAC,CAAC;IACvB,MAAMgB,UAAU,GAAGtB,yBAAyB,CAAC,WAAW,EAAE,4BAA4B,CAAC;IACvF,MAAM;MAAEuB;IAAwB,CAAC,GAAGxB,MAAM,CAACW,MAAM,EAAEY,UAAU,EAAEF,MAAM,EAAE,CAAC,CAAC,EAAEC,OAAO,EAAE,eAAe,CAAC;IACpGE,uBAAuB,CAAC;MACpBC,aAAa,EAAE,SAAS;MACxBC,YAAY,EAAE,QAAQ;MACtBC,UAAU,EAAE,KAAK;MACjBC,UAAU,EAAE;IAChB,CAAC,EAAE,QAAQ,CAAC;IACZ/B,MAAM,CAACoB,UAAU,CAACC,YAAY,CAACZ,OAAO,CAAC,CAACa,cAAc,CAAC,2BAA2BR,MAAM,CAACC,SAAS,EAAE,EAAEiB,IAAI,CAACC,SAAS,CAAC;MACjHL,aAAa,EAAE,SAAS;MACxBM,kBAAkB,EAAE;IACxB,CAAC,CAAC,CAAC;EACP,CAAC,CAAC;AACN,CAAC,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"createConfidentialOauthClient.d.ts","sourceRoot":"","sources":["../../src/createConfidentialOauthClient.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAG5E;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,EAAwC,EACtD,OAAO,GAAE,OAAO,UAAU,CAAC,KAAwB,EACnD,OAAO,GAAE,MAAoB,GAC5B,uBAAuB,CAgCzB"}
1
+ {"version":3,"file":"createConfidentialOauthClient.d.ts","sourceRoot":"","sources":["../../src/createConfidentialOauthClient.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAG5E;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,EAAwC,EACtD,OAAO,GAAE,OAAO,UAAU,CAAC,KAAwB,EACnD,OAAO,GAAE,MAAoB,GAC5B,uBAAuB,CAiCzB"}
@@ -41,7 +41,7 @@ export function createConfidentialOauthClient(client_id, client_secret, url, sco
41
41
  return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({
42
42
  scope: scopes.join(" ")
43
43
  }), oauthHttpOptions))), "signIn");
44
- }, oauthHttpOptions, undefined);
44
+ }, oauthHttpOptions, undefined, undefined);
45
45
  return getToken;
46
46
  }
47
47
  //# sourceMappingURL=createConfidentialOauthClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createConfidentialOauthClient.js","names":["clientCredentialsGrantRequest","customFetch","processClientCredentialsResponse","common","createAuthorizationServer","throwIfError","createConfidentialOauthClient","client_id","client_secret","url","scopes","fetchFn","globalThis","fetch","ctxPath","client","authServer","oauthHttpOptions","getToken","makeTokenAndSaveRefresh","URLSearchParams","scope","join","undefined"],"sources":["createConfidentialOauthClient.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse, } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param client_secret\n * @param url the base url of your foundry server\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns which can be used as a token provider\n */\nexport function createConfidentialOauthClient(client_id, client_secret, url, scopes = [\"api:read-data\", \"api:write-data\"], fetchFn = globalThis.fetch, ctxPath = \"multipass\") {\n const client = { client_id, client_secret };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = { [customFetch]: fetchFn };\n const { getToken, makeTokenAndSaveRefresh } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({ scope: scopes.join(\" \") }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,6BAA6B,EAAEC,WAAW,EAAEC,gCAAgC,QAAS,cAAc;AAC5G,SAASC,MAAM,EAAEC,yBAAyB,QAAQ,aAAa;AAC/D,SAASC,YAAY,QAAQ,mBAAmB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,6BAA6BA,CAACC,SAAS,EAAEC,aAAa,EAAEC,GAAG,EAAEC,MAAM,GAAG,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAEC,OAAO,GAAGC,UAAU,CAACC,KAAK,EAAEC,OAAO,GAAG,WAAW,EAAE;EAC1K,MAAMC,MAAM,GAAG;IAAER,SAAS;IAAEC;EAAc,CAAC;EAC3C,MAAMQ,UAAU,GAAGZ,yBAAyB,CAACU,OAAO,EAAEL,GAAG,CAAC;EAC1D,MAAMQ,gBAAgB,GAAG;IAAE,CAAChB,WAAW,GAAGU;EAAQ,CAAC;EACnD,MAAM;IAAEO,QAAQ;IAAEC;EAAwB,CAAC,GAAGhB,MAAM,CAACY,MAAM,EAAEC,UAAU,EACvE,kBAAyB;IACrB,OAAOG,uBAAuB,CAACd,YAAY,CAAC,MAAMH,gCAAgC,CAACc,UAAU,EAAED,MAAM,EAAE,MAAMf,6BAA6B,CAACgB,UAAU,EAAED,MAAM,EAAE,IAAIK,eAAe,CAAC;MAAEC,KAAK,EAAEX,MAAM,CAACY,IAAI,CAAC,GAAG;IAAE,CAAC,CAAC,EAAEL,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;EACnP,CAAC,EAHiFA,gBAAgB,EAAEM,SAAS,CAAC;EAI9G,OAAOL,QAAQ;AACnB","ignoreList":[]}
1
+ {"version":3,"file":"createConfidentialOauthClient.js","names":["clientCredentialsGrantRequest","customFetch","processClientCredentialsResponse","common","createAuthorizationServer","throwIfError","createConfidentialOauthClient","client_id","client_secret","url","scopes","fetchFn","globalThis","fetch","ctxPath","client","authServer","oauthHttpOptions","getToken","makeTokenAndSaveRefresh","URLSearchParams","scope","join","undefined"],"sources":["createConfidentialOauthClient.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse, } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param client_secret\n * @param url the base url of your foundry server\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns which can be used as a token provider\n */\nexport function createConfidentialOauthClient(client_id, client_secret, url, scopes = [\"api:read-data\", \"api:write-data\"], fetchFn = globalThis.fetch, ctxPath = \"multipass\") {\n const client = { client_id, client_secret };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = { [customFetch]: fetchFn };\n const { getToken, makeTokenAndSaveRefresh } = common(client, authServer, _signIn, oauthHttpOptions, undefined, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({ scope: scopes.join(\" \") }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,6BAA6B,EAAEC,WAAW,EAAEC,gCAAgC,QAAS,cAAc;AAC5G,SAASC,MAAM,EAAEC,yBAAyB,QAAQ,aAAa;AAC/D,SAASC,YAAY,QAAQ,mBAAmB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,6BAA6BA,CAACC,SAAS,EAAEC,aAAa,EAAEC,GAAG,EAAEC,MAAM,GAAG,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAEC,OAAO,GAAGC,UAAU,CAACC,KAAK,EAAEC,OAAO,GAAG,WAAW,EAAE;EAC1K,MAAMC,MAAM,GAAG;IAAER,SAAS;IAAEC;EAAc,CAAC;EAC3C,MAAMQ,UAAU,GAAGZ,yBAAyB,CAACU,OAAO,EAAEL,GAAG,CAAC;EAC1D,MAAMQ,gBAAgB,GAAG;IAAE,CAAChB,WAAW,GAAGU;EAAQ,CAAC;EACnD,MAAM;IAAEO,QAAQ;IAAEC;EAAwB,CAAC,GAAGhB,MAAM,CAACY,MAAM,EAAEC,UAAU,EACvE,kBAAyB;IACrB,OAAOG,uBAAuB,CAACd,YAAY,CAAC,MAAMH,gCAAgC,CAACc,UAAU,EAAED,MAAM,EAAE,MAAMf,6BAA6B,CAACgB,UAAU,EAAED,MAAM,EAAE,IAAIK,eAAe,CAAC;MAAEC,KAAK,EAAEX,MAAM,CAACY,IAAI,CAAC,GAAG;IAAE,CAAC,CAAC,EAAEL,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;EACnP,CAAC,EAHiFA,gBAAgB,EAAEM,SAAS,EAAEA,SAAS,CAAC;EAIzH,OAAOL,QAAQ;AACnB","ignoreList":[]}
@@ -24,6 +24,10 @@ export interface PublicOauthClientOptions {
24
24
  * Context path for the authorization server (defaults to "multipass")
25
25
  */
26
26
  ctxPath?: string;
27
+ /**
28
+ * Allows for an additional value to be appended to the local storage key for the refresh token.
29
+ */
30
+ refreshTokenMarker?: string;
27
31
  }
28
32
  /**
29
33
  * Creates a PublicOauthClient for authentication.
@@ -1 +1 @@
1
- {"version":3,"file":"createPublicOauthClient.d.ts","sourceRoot":"","sources":["../../src/createPublicOauthClient.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAYhE,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAElC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,wBAAwB,GACjC,iBAAiB,CAAC;AAErB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,OAAO,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,EACjC,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAAC"}
1
+ {"version":3,"file":"createPublicOauthClient.d.ts","sourceRoot":"","sources":["../../src/createPublicOauthClient.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAYhE,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAElC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,wBAAwB,GACjC,iBAAiB,CAAC;AAErB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,OAAO,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,EACjC,OAAO,CAAC,EAAE,MAAM,GACf,iBAAiB,CAAC"}
@@ -19,13 +19,15 @@ import { common, createAuthorizationServer, readLocal, readSession, removeLocal,
19
19
  import { throwIfError } from "./throwIfError.js";
20
20
  import { processOptionsAndAssignDefaults } from "./utils.js";
21
21
  export function createPublicOauthClient(client_id, url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath) {
22
+ let refreshTokenMarker;
22
23
  ({
23
24
  useHistory,
24
25
  loginPage,
25
26
  postLoginPage,
26
27
  scopes,
27
28
  fetchFn,
28
- ctxPath
29
+ ctxPath,
30
+ refreshTokenMarker
29
31
  } = processOptionsAndAssignDefaults(url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath));
30
32
  const client = {
31
33
  client_id,
@@ -46,7 +48,7 @@ export function createPublicOauthClient(client_id, url, redirect_uri, useHistory
46
48
  ) ?? (await maybeHandleAuthReturn())
47
49
  // 3. If we haven't been able to load the token from one of the two above ways, we need to make the initial auth request
48
50
  ?? (await initiateLoginRedirect());
49
- }, oauthHttpOptions, maybeRefresh.bind(globalThis, true));
51
+ }, oauthHttpOptions, maybeRefresh.bind(globalThis, true), refreshTokenMarker);
50
52
  // as an arrow function, `useHistory` is known to be a boolean
51
53
  const go = async x => {
52
54
  if (useHistory) {
@@ -58,9 +60,10 @@ export function createPublicOauthClient(client_id, url, redirect_uri, useHistory
58
60
  };
59
61
  async function maybeRefresh(expectRefreshToken) {
60
62
  const {
61
- refresh_token
63
+ refresh_token,
64
+ refreshTokenMarker: lastRefreshTokenMarker
62
65
  } = readLocal(client);
63
- if (!refresh_token) {
66
+ if (!refresh_token || lastRefreshTokenMarker !== refreshTokenMarker) {
64
67
  if (expectRefreshToken) throw new Error("No refresh token found");
65
68
  return;
66
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createPublicOauthClient.js","names":["delay","authorizationCodeGrantRequest","calculatePKCECodeChallenge","customFetch","generateRandomCodeVerifier","generateRandomState","processAuthorizationCodeOAuth2Response","refreshTokenGrantRequest","validateAuthResponse","common","createAuthorizationServer","readLocal","readSession","removeLocal","removeSession","saveLocal","saveSession","throwIfError","processOptionsAndAssignDefaults","createPublicOauthClient","client_id","url","redirect_uri","useHistory","loginPage","postLoginPage","scopes","fetchFn","ctxPath","client","token_endpoint_auth_method","authServer","oauthHttpOptions","makeTokenAndSaveRefresh","getToken","_signIn","maybeRefresh","maybeHandleAuthReturn","initiateLoginRedirect","bind","globalThis","go","x","window","history","replaceState","location","assign","Error","expectRefreshToken","refresh_token","result","pathname","URL","oldUrl","e","process","env","NODE_ENV","console","warn","state","codeVerifier","ret","href","toString","authorization_endpoint","URLSearchParams","response_type","code_challenge","code_challenge_method","scope","join"],"sources":["createPublicOauthClient.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse, } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, readSession, removeLocal, removeSession, saveLocal, saveSession, } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\nimport { processOptionsAndAssignDefaults } from \"./utils.js\";\nexport function createPublicOauthClient(client_id, url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath) {\n ({\n useHistory,\n loginPage,\n postLoginPage,\n scopes,\n fetchFn,\n ctxPath,\n } = processOptionsAndAssignDefaults(url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath));\n const client = { client_id, token_endpoint_auth_method: \"none\" };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = { [customFetch]: fetchFn };\n const { makeTokenAndSaveRefresh, getToken } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n // as an arrow function, `useHistory` is known to be a boolean\n const go = async (x) => {\n if (useHistory) {\n window.history.replaceState({}, \"\", x);\n return;\n }\n else\n window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n };\n async function maybeRefresh(expectRefreshToken) {\n const { refresh_token } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken)\n throw new Error(\"No refresh token found\");\n return;\n }\n try {\n // note, we don't use processRefreshTokenResponse because the mp oauth implementation\n // doesn't do refresh tokens quite right and this lets us skip the id check\n const result = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), \"refresh\");\n if (result && window.location.pathname === new URL(redirect_uri).pathname) {\n const { oldUrl } = readSession(client);\n // don't block on the redirect\n void go(oldUrl ?? \"/\");\n }\n return result;\n }\n catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n // eslint-disable-next-line no-console\n console.warn(\"Failed to get OAuth2 refresh token. Removing refresh token\", e);\n }\n removeLocal(client);\n if (expectRefreshToken) {\n throw new Error(\"Could not refresh token\");\n }\n }\n }\n async function maybeHandleAuthReturn() {\n const { state, oldUrl, codeVerifier } = readSession(client);\n if (!codeVerifier)\n return;\n try {\n const ret = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await authorizationCodeGrantRequest(authServer, client, throwIfError(validateAuthResponse(authServer, client, new URL(window.location.href), state)), redirect_uri, codeVerifier, oauthHttpOptions))), \"signIn\");\n void go(oldUrl);\n return ret;\n }\n catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n // eslint-disable-next-line no-console\n console.warn(\"Failed to get OAuth2 token using PKCE, removing PKCE and starting a new auth flow\", e);\n }\n removeLocal(client);\n removeSession(client);\n throw e;\n }\n }\n // As an arrow function, `scopes` and `postLoginPage` are known at compile time\n const initiateLoginRedirect = async () => {\n if (loginPage\n && window.location.href !== loginPage\n && window.location.pathname !== loginPage) {\n saveLocal(client, {});\n saveSession(client, { oldUrl: postLoginPage });\n await go(loginPage);\n return;\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readSession(client).oldUrl ?? window.location.toString();\n saveLocal(client, {});\n saveSession(client, { codeVerifier, state, oldUrl });\n window.location.assign(`${authServer\n .authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \"),\n })}`);\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n };\n /** Will throw if there is no token! */\n async function _signIn() {\n // 1. Check if we have a refresh token in local storage\n return await maybeRefresh()\n // 2. If there is no refresh token we are likely trying to perform the callback\n ?? await maybeHandleAuthReturn()\n // 3. If we haven't been able to load the token from one of the two above ways, we need to make the initial auth request\n ?? await initiateLoginRedirect();\n }\n return getToken;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"createPublicOauthClient.js","names":["delay","authorizationCodeGrantRequest","calculatePKCECodeChallenge","customFetch","generateRandomCodeVerifier","generateRandomState","processAuthorizationCodeOAuth2Response","refreshTokenGrantRequest","validateAuthResponse","common","createAuthorizationServer","readLocal","readSession","removeLocal","removeSession","saveLocal","saveSession","throwIfError","processOptionsAndAssignDefaults","createPublicOauthClient","client_id","url","redirect_uri","useHistory","loginPage","postLoginPage","scopes","fetchFn","ctxPath","refreshTokenMarker","client","token_endpoint_auth_method","authServer","oauthHttpOptions","makeTokenAndSaveRefresh","getToken","_signIn","maybeRefresh","maybeHandleAuthReturn","initiateLoginRedirect","bind","globalThis","go","x","window","history","replaceState","location","assign","Error","expectRefreshToken","refresh_token","lastRefreshTokenMarker","result","pathname","URL","oldUrl","e","process","env","NODE_ENV","console","warn","state","codeVerifier","ret","href","toString","authorization_endpoint","URLSearchParams","response_type","code_challenge","code_challenge_method","scope","join"],"sources":["createPublicOauthClient.js"],"sourcesContent":["/*\n * Copyright 2024 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse, } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, readSession, removeLocal, removeSession, saveLocal, saveSession, } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\nimport { processOptionsAndAssignDefaults } from \"./utils.js\";\nexport function createPublicOauthClient(client_id, url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath) {\n let refreshTokenMarker;\n ({\n useHistory,\n loginPage,\n postLoginPage,\n scopes,\n fetchFn,\n ctxPath,\n refreshTokenMarker,\n } = processOptionsAndAssignDefaults(url, redirect_uri, useHistory, loginPage, postLoginPage, scopes, fetchFn, ctxPath));\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\",\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = { [customFetch]: fetchFn };\n const { makeTokenAndSaveRefresh, getToken } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true), refreshTokenMarker);\n // as an arrow function, `useHistory` is known to be a boolean\n const go = async (x) => {\n if (useHistory) {\n window.history.replaceState({}, \"\", x);\n return;\n }\n else\n window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n };\n async function maybeRefresh(expectRefreshToken) {\n const { refresh_token, refreshTokenMarker: lastRefreshTokenMarker } = readLocal(client);\n if (!refresh_token || lastRefreshTokenMarker !== refreshTokenMarker) {\n if (expectRefreshToken)\n throw new Error(\"No refresh token found\");\n return;\n }\n try {\n // note, we don't use processRefreshTokenResponse because the mp oauth implementation\n // doesn't do refresh tokens quite right and this lets us skip the id check\n const result = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), \"refresh\");\n if (result && window.location.pathname === new URL(redirect_uri).pathname) {\n const { oldUrl } = readSession(client);\n // don't block on the redirect\n void go(oldUrl ?? \"/\");\n }\n return result;\n }\n catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n // eslint-disable-next-line no-console\n console.warn(\"Failed to get OAuth2 refresh token. Removing refresh token\", e);\n }\n removeLocal(client);\n if (expectRefreshToken) {\n throw new Error(\"Could not refresh token\");\n }\n }\n }\n async function maybeHandleAuthReturn() {\n const { state, oldUrl, codeVerifier } = readSession(client);\n if (!codeVerifier)\n return;\n try {\n const ret = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await authorizationCodeGrantRequest(authServer, client, throwIfError(validateAuthResponse(authServer, client, new URL(window.location.href), state)), redirect_uri, codeVerifier, oauthHttpOptions))), \"signIn\");\n void go(oldUrl);\n return ret;\n }\n catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n // eslint-disable-next-line no-console\n console.warn(\"Failed to get OAuth2 token using PKCE, removing PKCE and starting a new auth flow\", e);\n }\n removeLocal(client);\n removeSession(client);\n throw e;\n }\n }\n // As an arrow function, `scopes` and `postLoginPage` are known at compile time\n const initiateLoginRedirect = async () => {\n if (loginPage\n && window.location.href !== loginPage\n && window.location.pathname !== loginPage) {\n saveLocal(client, {});\n saveSession(client, { oldUrl: postLoginPage });\n await go(loginPage);\n return;\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readSession(client).oldUrl ?? window.location.toString();\n saveLocal(client, {});\n saveSession(client, { codeVerifier, state, oldUrl });\n window.location.assign(`${authServer\n .authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \"),\n })}`);\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n };\n /** Will throw if there is no token! */\n async function _signIn() {\n // 1. Check if we have a refresh token in local storage\n return await maybeRefresh()\n // 2. If there is no refresh token we are likely trying to perform the callback\n ?? await maybeHandleAuthReturn()\n // 3. If we haven't been able to load the token from one of the two above ways, we need to make the initial auth request\n ?? await initiateLoginRedirect();\n }\n return getToken;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,6BAA6B,EAAEC,0BAA0B,EAAEC,WAAW,EAAEC,0BAA0B,EAAEC,mBAAmB,EAAEC,sCAAsC,EAAEC,wBAAwB,EAAEC,oBAAoB,QAAS,cAAc;AAC/O,SAASC,MAAM,EAAEC,yBAAyB,EAAEC,SAAS,EAAEC,WAAW,EAAEC,WAAW,EAAEC,aAAa,EAAEC,SAAS,EAAEC,WAAW,QAAS,aAAa;AAC5I,SAASC,YAAY,QAAQ,mBAAmB;AAChD,SAASC,+BAA+B,QAAQ,YAAY;AAC5D,OAAO,SAASC,uBAAuBA,CAACC,SAAS,EAAEC,GAAG,EAAEC,YAAY,EAAEC,UAAU,EAAEC,SAAS,EAAEC,aAAa,EAAEC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAE;EAClI,IAAIC,kBAAkB;EACtB,CAAC;IACGN,UAAU;IACVC,SAAS;IACTC,aAAa;IACbC,MAAM;IACNC,OAAO;IACPC,OAAO;IACPC;EACJ,CAAC,GAAGX,+BAA+B,CAACG,GAAG,EAAEC,YAAY,EAAEC,UAAU,EAAEC,SAAS,EAAEC,aAAa,EAAEC,MAAM,EAAEC,OAAO,EAAEC,OAAO,CAAC;EACtH,MAAME,MAAM,GAAG;IACXV,SAAS;IACTW,0BAA0B,EAAE;EAChC,CAAC;EACD,MAAMC,UAAU,GAAGtB,yBAAyB,CAACkB,OAAO,EAAEP,GAAG,CAAC;EAC1D,MAAMY,gBAAgB,GAAG;IAAE,CAAC9B,WAAW,GAAGwB;EAAQ,CAAC;EACnD,MAAM;IAAEO,uBAAuB;IAAEC;EAAS,CAAC,GAAG1B,MAAM,CAACqB,MAAM,EAAEE,UAAU,EAyFvE;EACA,eAAeI,OAAOA,CAAA,EAAG;IACrB;IACA,OAAO,OAAMC,YAAY,CAAC;IACtB;IAAA,MACG,MAAMC,qBAAqB,CAAC,CAAC;IAChC;IAAA,IACG,MAAMC,qBAAqB,CAAC,CAAC;EACxC,CAAC,EAjGiFN,gBAAgB,EAAEI,YAAY,CAACG,IAAI,CAACC,UAAU,EAAE,IAAI,CAAC,EAAEZ,kBAAkB,CAAC;EAC5J;EACA,MAAMa,EAAE,GAAG,MAAOC,CAAC,IAAK;IACpB,IAAIpB,UAAU,EAAE;MACZqB,MAAM,CAACC,OAAO,CAACC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EAAEH,CAAC,CAAC;MACtC;IACJ,CAAC,MAEGC,MAAM,CAACG,QAAQ,CAACC,MAAM,CAACL,CAAC,CAAC;IAC7B,MAAM3C,KAAK,CAAC,IAAI,CAAC;IACjB,MAAM,IAAIiD,KAAK,CAAC,oBAAoB,CAAC;EACzC,CAAC;EACD,eAAeZ,YAAYA,CAACa,kBAAkB,EAAE;IAC5C,MAAM;MAAEC,aAAa;MAAEtB,kBAAkB,EAAEuB;IAAuB,CAAC,GAAGzC,SAAS,CAACmB,MAAM,CAAC;IACvF,IAAI,CAACqB,aAAa,IAAIC,sBAAsB,KAAKvB,kBAAkB,EAAE;MACjE,IAAIqB,kBAAkB,EAClB,MAAM,IAAID,KAAK,CAAC,wBAAwB,CAAC;MAC7C;IACJ;IACA,IAAI;MACA;MACA;MACA,MAAMI,MAAM,GAAGnB,uBAAuB,CAACjB,YAAY,CAAC,MAAMX,sCAAsC,CAAC0B,UAAU,EAAEF,MAAM,EAAE,MAAMvB,wBAAwB,CAACyB,UAAU,EAAEF,MAAM,EAAEqB,aAAa,EAAElB,gBAAgB,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;MACtN,IAAIoB,MAAM,IAAIT,MAAM,CAACG,QAAQ,CAACO,QAAQ,KAAK,IAAIC,GAAG,CAACjC,YAAY,CAAC,CAACgC,QAAQ,EAAE;QACvE,MAAM;UAAEE;QAAO,CAAC,GAAG5C,WAAW,CAACkB,MAAM,CAAC;QACtC;QACA,KAAKY,EAAE,CAACc,MAAM,IAAI,GAAG,CAAC;MAC1B;MACA,OAAOH,MAAM;IACjB,CAAC,CACD,OAAOI,CAAC,EAAE;MACN,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACvC;QACAC,OAAO,CAACC,IAAI,CAAC,4DAA4D,EAAEL,CAAC,CAAC;MACjF;MACA5C,WAAW,CAACiB,MAAM,CAAC;MACnB,IAAIoB,kBAAkB,EAAE;QACpB,MAAM,IAAID,KAAK,CAAC,yBAAyB,CAAC;MAC9C;IACJ;EACJ;EACA,eAAeX,qBAAqBA,CAAA,EAAG;IACnC,MAAM;MAAEyB,KAAK;MAAEP,MAAM;MAAEQ;IAAa,CAAC,GAAGpD,WAAW,CAACkB,MAAM,CAAC;IAC3D,IAAI,CAACkC,YAAY,EACb;IACJ,IAAI;MACA,MAAMC,GAAG,GAAG/B,uBAAuB,CAACjB,YAAY,CAAC,MAAMX,sCAAsC,CAAC0B,UAAU,EAAEF,MAAM,EAAE,MAAM7B,6BAA6B,CAAC+B,UAAU,EAAEF,MAAM,EAAEb,YAAY,CAACT,oBAAoB,CAACwB,UAAU,EAAEF,MAAM,EAAE,IAAIyB,GAAG,CAACX,MAAM,CAACG,QAAQ,CAACmB,IAAI,CAAC,EAAEH,KAAK,CAAC,CAAC,EAAEzC,YAAY,EAAE0C,YAAY,EAAE/B,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;MAClU,KAAKS,EAAE,CAACc,MAAM,CAAC;MACf,OAAOS,GAAG;IACd,CAAC,CACD,OAAOR,CAAC,EAAE;MACN,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;QACvC;QACAC,OAAO,CAACC,IAAI,CAAC,mFAAmF,EAAEL,CAAC,CAAC;MACxG;MACA5C,WAAW,CAACiB,MAAM,CAAC;MACnBhB,aAAa,CAACgB,MAAM,CAAC;MACrB,MAAM2B,CAAC;IACX;EACJ;EACA;EACA,MAAMlB,qBAAqB,GAAG,MAAAA,CAAA,KAAY;IACtC,IAAIf,SAAS,IACNoB,MAAM,CAACG,QAAQ,CAACmB,IAAI,KAAK1C,SAAS,IAClCoB,MAAM,CAACG,QAAQ,CAACO,QAAQ,KAAK9B,SAAS,EAAE;MAC3CT,SAAS,CAACe,MAAM,EAAE,CAAC,CAAC,CAAC;MACrBd,WAAW,CAACc,MAAM,EAAE;QAAE0B,MAAM,EAAE/B;MAAc,CAAC,CAAC;MAC9C,MAAMiB,EAAE,CAAClB,SAAS,CAAC;MACnB;IACJ;IACA,MAAMuC,KAAK,GAAG1D,mBAAmB,CAAC,CAAC;IACnC,MAAM2D,YAAY,GAAG5D,0BAA0B,CAAC,CAAC;IACjD,MAAMoD,MAAM,GAAG5C,WAAW,CAACkB,MAAM,CAAC,CAAC0B,MAAM,IAAIZ,MAAM,CAACG,QAAQ,CAACoB,QAAQ,CAAC,CAAC;IACvEpD,SAAS,CAACe,MAAM,EAAE,CAAC,CAAC,CAAC;IACrBd,WAAW,CAACc,MAAM,EAAE;MAAEkC,YAAY;MAAED,KAAK;MAAEP;IAAO,CAAC,CAAC;IACpDZ,MAAM,CAACG,QAAQ,CAACC,MAAM,CAAC,GAAGhB,UAAU,CAC/BoC,sBAAsB,IAAI,IAAIC,eAAe,CAAC;MAC/CjD,SAAS;MACTkD,aAAa,EAAE,MAAM;MACrBP,KAAK;MACLzC,YAAY;MACZiD,cAAc,EAAE,MAAMrE,0BAA0B,CAAC8D,YAAY,CAAC;MAC9DQ,qBAAqB,EAAE,MAAM;MAC7BC,KAAK,EAAE,CAAC,gBAAgB,EAAE,GAAG/C,MAAM,CAAC,CAACgD,IAAI,CAAC,GAAG;IACjD,CAAC,CAAC,EAAE,CAAC;IACL;IACA,MAAM1E,KAAK,CAAC,IAAI,CAAC;IACjB,MAAM,IAAIiD,KAAK,CAAC,oBAAoB,CAAC;EACzC,CAAC;EAUD,OAAOd,QAAQ;AACnB","ignoreList":[]}
@@ -95,6 +95,81 @@ describe(createPublicOauthClient, () => {
95
95
  fetchFn
96
96
  };
97
97
  const fullLoginUrl = new URL("/loginPage", DEFAULT_CUR_URL);
98
+ function setupWindowLocation(currentUrl) {
99
+ mockWindow.location.href = new URL(currentUrl).href;
100
+ mockWindow.location.pathname = new URL(currentUrl).pathname;
101
+ }
102
+ function setupLocalState(initialLocalState) {
103
+ vi.mocked(commonJs.readLocal).mockImplementation(() => initialLocalState);
104
+ }
105
+ let client;
106
+ let clientArgs;
107
+ function setupClient(clientArgs_) {
108
+ clientArgs = clientArgs_;
109
+ if (clientArgs.refreshTokenMarker) {
110
+ client = createPublicOauthClient(clientArgs.clientId, clientArgs.foundryUrl, clientArgs.redirectUrl, clientArgs);
111
+ } else {
112
+ client = createPublicOauthClient(clientArgs.clientId, clientArgs.foundryUrl, clientArgs.redirectUrl, clientArgs.useHistory, clientArgs.loginPage, clientArgs.postLoginPage, clientArgs.scopes, clientArgs.fetchFn, clientArgs.ctxPath);
113
+ }
114
+ }
115
+ beforeEach(() => {
116
+ // prevents mistakes like forgetting to initialize the client with an
117
+ // old value around
118
+ client = undefined;
119
+ clientArgs = undefined;
120
+ });
121
+ async function expectRedirectToMultipass(tokenPromise) {
122
+ // we assume window.location.assign will take you away therefore we
123
+ // also have to expect in this scenario that the thrown error happens
124
+ await expect(tokenPromise).rejects.toThrowError(new Error("Unable to redirect"));
125
+ expect(mockWindow.location.assign).toHaveBeenCalledOnce();
126
+ const url = new URL(mockWindow.location.assign.mock.calls[0][0]);
127
+ expect(url.origin).toEqual(clientArgs.foundryUrl);
128
+ expect(url.pathname).toEqual("/multipass/api/oauth2/authorize");
129
+ expect(Object.fromEntries(url.searchParams.entries())).toEqual(expect.objectContaining({
130
+ client_id: clientArgs.clientId,
131
+ code_challenge: expect.any(String),
132
+ redirect_uri: clientArgs.redirectUrl,
133
+ response_type: "code",
134
+ code_challenge_method: "S256",
135
+ scope: "offline_access api:read-data api:write-data",
136
+ state: expect.any(String)
137
+ }));
138
+ }
139
+ describe("refresh token marker", () => {
140
+ beforeEach(() => {
141
+ setupWindowLocation("https://foundry.local");
142
+ });
143
+ it("should not allow refresh if the refresh markers do not match", async () => {
144
+ setupLocalState({
145
+ refresh_token: "refreshToken",
146
+ refreshTokenMarker: "not-the-right-marker"
147
+ });
148
+ setupClient({
149
+ ...BASE_CLIENT_ARGS,
150
+ refreshTokenMarker: "marker"
151
+ });
152
+ await expectRedirectToMultipass(client());
153
+ });
154
+ it("should try to refresh if refresh tokens do match", async () => {
155
+ setupLocalState({
156
+ refresh_token: "refreshToken",
157
+ refreshTokenMarker: "marker"
158
+ });
159
+ setupClient({
160
+ ...BASE_CLIENT_ARGS,
161
+ refreshTokenMarker: "marker"
162
+ });
163
+ hoistedMocks.makeTokenAndSaveRefresh.mockImplementationOnce(() => ({
164
+ access_token: "some token",
165
+ expires_at: Date.now(),
166
+ expires_in: 10000
167
+ }));
168
+ const tokenPromise = client();
169
+ await expect(tokenPromise).resolves.toEqual("some token");
170
+ expect(hoistedMocks.makeTokenAndSaveRefresh).toBeCalledTimes(1);
171
+ });
172
+ });
98
173
  describe.each([{
99
174
  name: "Basic Usage",
100
175
  currentUrl: DEFAULT_CUR_URL,
@@ -149,17 +224,15 @@ describe(createPublicOauthClient, () => {
149
224
  currentUrl,
150
225
  should
151
226
  }) => {
152
- let client;
153
227
  beforeEach(() => {
154
- client = createPublicOauthClient(clientArgs.clientId, clientArgs.foundryUrl, clientArgs.redirectUrl, clientArgs.useHistory, clientArgs.loginPage, clientArgs.postLoginPage, clientArgs.scopes, clientArgs.fetchFn, clientArgs.ctxPath);
155
- mockWindow.location.href = new URL(currentUrl).href;
156
- mockWindow.location.pathname = new URL(currentUrl).pathname;
228
+ setupClient(clientArgs);
229
+ setupWindowLocation(currentUrl.toString());
157
230
  });
158
231
  it("calls common with expected values", () => {
159
232
  expect(vi.mocked(commonJs.common)).toHaveBeenCalledWith(expect.objectContaining({
160
233
  client_id: clientArgs.clientId,
161
234
  token_endpoint_auth_method: "none"
162
- }), commonJs.createAuthorizationServer(clientArgs.ctxPath ?? "/multipass", clientArgs.foundryUrl), expect.any(Function), expect.anything(), expect.any(Function));
235
+ }), commonJs.createAuthorizationServer(clientArgs.ctxPath ?? "/multipass", clientArgs.foundryUrl), expect.any(Function), expect.anything(), expect.any(Function), undefined);
163
236
  });
164
237
  describe.each([{
165
238
  localStorage: {
@@ -214,22 +287,7 @@ describe(createPublicOauthClient, () => {
214
287
  expect(mockWindow.history.replaceState).toHaveBeenCalledWith({}, "", clientArgs.loginPage);
215
288
  return;
216
289
  }
217
- // we assume window.location.assign will take you away therefore we
218
- // also have to expect in this scenario that the thrown error happens
219
- await expect(tokenPromise).rejects.toThrowError(new Error("Unable to redirect"));
220
- expect(mockWindow.location.assign).toHaveBeenCalledOnce();
221
- const url = new URL(mockWindow.location.assign.mock.calls[0][0]);
222
- expect(url.origin).toEqual(clientArgs.foundryUrl);
223
- expect(url.pathname).toEqual("/multipass/api/oauth2/authorize");
224
- expect(Object.fromEntries(url.searchParams.entries())).toEqual(expect.objectContaining({
225
- client_id: clientArgs.clientId,
226
- code_challenge: expect.any(String),
227
- redirect_uri: clientArgs.redirectUrl,
228
- response_type: "code",
229
- code_challenge_method: "S256",
230
- scope: "offline_access api:read-data api:write-data",
231
- state: expect.any(String)
232
- }));
290
+ await expectRedirectToMultipass(tokenPromise);
233
291
  });
234
292
  }
235
293
  }