@osdk/oauth 0.3.0 → 0.4.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/build/browser/index.js +22 -14
- package/build/browser/index.js.map +1 -1
- package/build/esm/BaseOauthClient.d.ts +1 -0
- package/build/esm/BaseOauthClient.d.ts.map +1 -1
- package/build/esm/common.d.ts.map +1 -1
- package/build/esm/createPublicOauthClient.d.ts.map +1 -1
- package/build/esm/index.js +22 -5
- package/build/esm/index.js.map +1 -1
- package/package.json +3 -4
- package/build/cjs/index.cjs +0 -244
- package/build/cjs/index.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @osdk/oauth
|
|
2
2
|
|
|
3
|
+
## 0.4.0-beta.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1252d94: ESM Only
|
|
8
|
+
|
|
9
|
+
## 0.4.0-beta.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- cad781e: PublicClient allows relative paths for login pages
|
|
14
|
+
- cad781e: adds getTokenOrUndefined() to oauth clients
|
|
15
|
+
- cad781e: Redirects to root when visiting an old auth callback
|
|
16
|
+
- cad781e: Fixes a bug where process.env was being emitted
|
|
17
|
+
- cad781e: Uses default scopes when provided an empty array
|
|
18
|
+
|
|
3
19
|
## 0.3.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/build/browser/index.js
CHANGED
|
@@ -12,16 +12,7 @@ function throwIfError(result) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// src/common.ts
|
|
15
|
-
var CustomEvent =
|
|
16
|
-
#detail;
|
|
17
|
-
constructor(type, options) {
|
|
18
|
-
super(type, options);
|
|
19
|
-
this.#detail = options?.detail ?? null;
|
|
20
|
-
}
|
|
21
|
-
get detail() {
|
|
22
|
-
return this.#detail;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
15
|
+
var CustomEvent = globalThis.CustomEvent ;
|
|
25
16
|
var localStorage = globalThis.localStorage;
|
|
26
17
|
function saveLocal(client, x) {
|
|
27
18
|
localStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));
|
|
@@ -92,6 +83,12 @@ function common(client, as, _signIn, oauthHttpOptions, refresh) {
|
|
|
92
83
|
}
|
|
93
84
|
eventTarget.addEventListener("signIn", restartRefreshTimer);
|
|
94
85
|
eventTarget.addEventListener("refresh", restartRefreshTimer);
|
|
86
|
+
function getTokenOrUndefined() {
|
|
87
|
+
if (!token || Date.now() >= token.expires_at) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
return token?.access_token;
|
|
91
|
+
}
|
|
95
92
|
const getToken = Object.assign(async function getToken2() {
|
|
96
93
|
if (!token || Date.now() >= token.expires_at) {
|
|
97
94
|
token = await signIn();
|
|
@@ -102,6 +99,7 @@ function common(client, as, _signIn, oauthHttpOptions, refresh) {
|
|
|
102
99
|
refresh,
|
|
103
100
|
signOut,
|
|
104
101
|
rmTimeout,
|
|
102
|
+
getTokenOrUndefined,
|
|
105
103
|
addEventListener: eventTarget.addEventListener.bind(eventTarget),
|
|
106
104
|
removeEventListener: eventTarget.removeEventListener.bind(eventTarget)
|
|
107
105
|
});
|
|
@@ -141,7 +139,7 @@ function createConfidentialOauthClient(client_id, client_secret, url, scopes = [
|
|
|
141
139
|
}
|
|
142
140
|
return getToken;
|
|
143
141
|
}
|
|
144
|
-
function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = [
|
|
142
|
+
function createPublicOauthClient(client_id, url, redirectUrl, useHistory = true, loginPage, postLoginPage = window.location.toString(), scopes = [], fetchFn = globalThis.fetch, ctxPath = "/multipass") {
|
|
145
143
|
const client = {
|
|
146
144
|
client_id,
|
|
147
145
|
token_endpoint_auth_method: "none"
|
|
@@ -150,6 +148,9 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
150
148
|
const oauthHttpOptions = {
|
|
151
149
|
[customFetch]: fetchFn
|
|
152
150
|
};
|
|
151
|
+
if (scopes.length === 0) {
|
|
152
|
+
scopes = ["api:read-data", "api:write-data"];
|
|
153
|
+
}
|
|
153
154
|
const {
|
|
154
155
|
makeTokenAndSaveRefresh,
|
|
155
156
|
getToken
|
|
@@ -169,7 +170,14 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
169
170
|
return;
|
|
170
171
|
}
|
|
171
172
|
try {
|
|
172
|
-
|
|
173
|
+
const result = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), "refresh");
|
|
174
|
+
if (result && window.location.pathname === new URL(redirectUrl).pathname) {
|
|
175
|
+
const {
|
|
176
|
+
oldUrl
|
|
177
|
+
} = readLocal(client);
|
|
178
|
+
go(oldUrl ?? "/");
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
173
181
|
} catch (e) {
|
|
174
182
|
if (process?.env?.NODE_ENV !== "production") {
|
|
175
183
|
console.warn("Failed to get OAuth2 refresh token. Removing refresh token", e);
|
|
@@ -199,7 +207,7 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
199
207
|
}
|
|
200
208
|
}
|
|
201
209
|
async function initiateLoginRedirect() {
|
|
202
|
-
if (loginPage && window.location.href !== loginPage) {
|
|
210
|
+
if (loginPage && window.location.href !== loginPage && window.location.pathname !== loginPage) {
|
|
203
211
|
saveLocal(client, {
|
|
204
212
|
oldUrl: postLoginPage
|
|
205
213
|
});
|
|
@@ -232,5 +240,5 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
232
240
|
}
|
|
233
241
|
|
|
234
242
|
export { createConfidentialOauthClient, createPublicOauthClient };
|
|
235
|
-
//# sourceMappingURL=
|
|
243
|
+
//# sourceMappingURL=index.js.map
|
|
236
244
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/createConfidentialOauthClient.ts","../../src/common.ts","../../src/throwIfError.ts","../../src/createPublicOauthClient.ts"],"names":["CustomEvent","getToken","customFetch"],"mappings":"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","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 */\n\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n\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 = {\n client_id,\n client_secret\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n getToken,\n makeTokenAndSaveRefresh\n } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({\n scope: scopes.join(\" \")\n }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}","/*\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 */\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\" ? globalThis.CustomEvent : globalThis.CustomEvent ?? 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};\nconst localStorage = globalThis.localStorage;\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n 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 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 localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const {\n refresh_token,\n expires_in,\n access_token\n } = resp;\n !(expires_in != null) ? process.env.NODE_ENV !== \"production\" ? invariant(false) : invariant(false) : void 0;\n saveLocal(client, {\n refresh_token\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, {\n detail: token\n }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout) 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 !token ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"not signed in\") : invariant(false) : void 0;\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n\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 } finally {\n pendingSignIn = undefined;\n }\n }\n eventTarget.addEventListener(\"signIn\", restartRefreshTimer);\n eventTarget.addEventListener(\"refresh\", restartRefreshTimer);\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 addEventListener: eventTarget.addEventListener.bind(eventTarget),\n removeEventListener: eventTarget.removeEventListener.bind(eventTarget)\n });\n return {\n getToken,\n makeTokenAndSaveRefresh\n };\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 * 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 */\n\nimport { isOAuth2Error } from \"oauth4webapi\";\nexport function throwIfError(result) {\n if (isOAuth2Error(result)) {\n throw new Error(`Failed to get token: ${result.error}`);\n }\n return result;\n}","/*\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 */\n\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param url the base url of your foundry server\n * @param redirectUrl the url configured for redirect in the oauth configuration on the server\n * @param useHistory if true, when possible uses `history.replaceState()`, otherwise uses `window.location.assign()`\n * @param loginPage if you want a custom landing page prior to logging in, set this to that url\n * @param postLoginPage if you want to customize where you return to after a completed authentication cycle. defaults to the url when the page loaded\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns {PublicOauthClient} which can be used as a token provider\n */\nexport function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = [\"api:read-data\", \"api:write-data\"], fetchFn = globalThis.fetch, ctxPath = \"/multipass\") {\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\"\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n makeTokenAndSaveRefresh,\n getToken\n } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n async function go(x) {\n if (useHistory) return window.history.replaceState({}, \"\", x);else window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\n async function maybeRefresh(expectRefreshToken) {\n const {\n refresh_token\n } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken) 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 return makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), \"refresh\");\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 {\n codeVerifier,\n state,\n oldUrl\n } = readLocal(client);\n if (!codeVerifier) 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)), redirectUrl, codeVerifier, oauthHttpOptions))), \"signIn\");\n go(oldUrl);\n return ret;\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 }\n }\n async function initiateLoginRedirect() {\n if (loginPage && window.location.href !== loginPage) {\n saveLocal(client, {\n oldUrl: postLoginPage\n });\n return await go(loginPage);\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readLocal(client).oldUrl ?? window.location.toString();\n saveLocal(client, {\n codeVerifier,\n state,\n oldUrl\n });\n window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri: redirectUrl,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \")\n })}`);\n\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\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}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/throwIfError.ts","../../src/common.ts","../../src/createConfidentialOauthClient.ts","../../src/createPublicOauthClient.ts"],"names":["getToken","customFetch"],"mappings":"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","file":"index.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 */\n\nimport { isOAuth2Error } from \"oauth4webapi\";\nexport function throwIfError(result) {\n if (isOAuth2Error(result)) {\n throw new Error(`Failed to get token: ${result.error}`);\n }\n return result;\n}","/*\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 */\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\" ? globalThis.CustomEvent : globalThis.CustomEvent ?? 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};\nconst localStorage = globalThis.localStorage;\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n 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 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 localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const {\n refresh_token,\n expires_in,\n access_token\n } = resp;\n !(expires_in != null) ? process.env.NODE_ENV !== \"production\" ? invariant(false) : invariant(false) : void 0;\n saveLocal(client, {\n refresh_token\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, {\n detail: token\n }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout) 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 !token ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"not signed in\") : invariant(false) : void 0;\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n\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 } 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 {\n getToken,\n makeTokenAndSaveRefresh\n };\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 * 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 */\n\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n\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 = {\n client_id,\n client_secret\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n getToken,\n makeTokenAndSaveRefresh\n } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({\n scope: scopes.join(\" \")\n }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}","/*\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 */\n\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param url the base url of your foundry server\n * @param redirectUrl the url configured for redirect in the oauth configuration on the server\n * @param useHistory if true, when possible uses `history.replaceState()`, otherwise uses `window.location.assign()`\n * @param loginPage if you want a custom landing page prior to logging in, set this to that url\n * @param postLoginPage if you want to customize where you return to after a completed authentication cycle. defaults to the url when the page loaded\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns {PublicOauthClient} which can be used as a token provider\n */\nexport function createPublicOauthClient(client_id, url, redirectUrl, useHistory = true, loginPage, postLoginPage = window.location.toString(), scopes = [], fetchFn = globalThis.fetch, ctxPath = \"/multipass\") {\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\"\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n if (scopes.length === 0) {\n scopes = [\"api:read-data\", \"api:write-data\"];\n }\n const {\n makeTokenAndSaveRefresh,\n getToken\n } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n async function go(x) {\n if (useHistory) return window.history.replaceState({}, \"\", x);else window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\n async function maybeRefresh(expectRefreshToken) {\n const {\n refresh_token\n } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken) 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(redirectUrl).pathname) {\n const {\n oldUrl\n } = readLocal(client);\n go(oldUrl ?? \"/\");\n }\n return result;\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 {\n codeVerifier,\n state,\n oldUrl\n } = readLocal(client);\n if (!codeVerifier) 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)), redirectUrl, codeVerifier, oauthHttpOptions))), \"signIn\");\n go(oldUrl);\n return ret;\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 }\n }\n async function initiateLoginRedirect() {\n if (loginPage && window.location.href !== loginPage && window.location.pathname !== loginPage) {\n saveLocal(client, {\n oldUrl: postLoginPage\n });\n return await go(loginPage);\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readLocal(client).oldUrl ?? window.location.toString();\n saveLocal(client, {\n codeVerifier,\n state,\n oldUrl\n });\n window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri: redirectUrl,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \")\n })}`);\n\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\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}"]}
|
|
@@ -6,6 +6,7 @@ export type Events = {
|
|
|
6
6
|
};
|
|
7
7
|
export interface BaseOauthClient<K extends keyof Events & string> {
|
|
8
8
|
(): Promise<string>;
|
|
9
|
+
getTokenOrUndefined: () => string | undefined;
|
|
9
10
|
signIn: () => Promise<Token>;
|
|
10
11
|
signOut: () => Promise<void>;
|
|
11
12
|
addEventListener: <T extends K>(type: T, listener: ((evt: Events[T]) => void) | null, options?: boolean | AddEventListenerOptions) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseOauthClient.d.ts","sourceRoot":"","sources":["../../src/BaseOauthClient.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,MAAM,GAAG,MAAM;IAC9D,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpB,MAAM,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B,gBAAgB,EAAE,CAAC,CAAC,SAAS,CAAC,EAC5B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,KACxC,IAAI,CAAC;IAEV,mBAAmB,EAAE,CAAC,CAAC,SAAS,CAAC,EAC/B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,KACrC,IAAI,CAAC;CACX"}
|
|
1
|
+
{"version":3,"file":"BaseOauthClient.d.ts","sourceRoot":"","sources":["../../src/BaseOauthClient.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;CAC7B,CAAC;AAEF,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,MAAM,GAAG,MAAM;IAC9D,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpB,mBAAmB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC9C,MAAM,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B,gBAAgB,EAAE,CAAC,CAAC,SAAS,CAAC,EAC5B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,KACxC,IAAI,CAAC;IAEV,mBAAmB,EAAE,CAAC,CAAC,SAAS,CAAC,EAC/B,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,EAC3C,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,KACrC,IAAI,CAAC;CACX"}
|
|
@@ -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;AA0BxC,KAAK,iBAAiB,GAElB;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB,GACC;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,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,QAM7D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,QAGzC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAM3D;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,
|
|
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;AA0BxC,KAAK,iBAAiB,GAElB;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAEC;IACA,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB,GACC;IACA,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,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,QAM7D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,QAGzC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAM3D;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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPublicOauthClient.d.ts","sourceRoot":"","sources":["../../src/createPublicOauthClient.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAUhE;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,
|
|
1
|
+
{"version":3,"file":"createPublicOauthClient.d.ts","sourceRoot":"","sources":["../../src/createPublicOauthClient.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAUhE;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,UAAU,GAAE,OAAc,EAC1B,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,GAAE,MAAmC,EAClD,MAAM,GAAE,MAAM,EAAO,EACrB,OAAO,GAAE,OAAO,UAAU,CAAC,KAAwB,EACnD,OAAO,GAAE,MAAqB,GAC7B,iBAAiB,CAiKnB"}
|
package/build/esm/index.js
CHANGED
|
@@ -12,7 +12,7 @@ function throwIfError(result) {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// src/common.ts
|
|
15
|
-
var CustomEvent =
|
|
15
|
+
var CustomEvent = globalThis.CustomEvent ?? class CustomEvent2 extends Event {
|
|
16
16
|
#detail;
|
|
17
17
|
constructor(type, options) {
|
|
18
18
|
super(type, options);
|
|
@@ -92,6 +92,12 @@ function common(client, as, _signIn, oauthHttpOptions, refresh) {
|
|
|
92
92
|
}
|
|
93
93
|
eventTarget.addEventListener("signIn", restartRefreshTimer);
|
|
94
94
|
eventTarget.addEventListener("refresh", restartRefreshTimer);
|
|
95
|
+
function getTokenOrUndefined() {
|
|
96
|
+
if (!token || Date.now() >= token.expires_at) {
|
|
97
|
+
return void 0;
|
|
98
|
+
}
|
|
99
|
+
return token?.access_token;
|
|
100
|
+
}
|
|
95
101
|
const getToken = Object.assign(async function getToken2() {
|
|
96
102
|
if (!token || Date.now() >= token.expires_at) {
|
|
97
103
|
token = await signIn();
|
|
@@ -102,6 +108,7 @@ function common(client, as, _signIn, oauthHttpOptions, refresh) {
|
|
|
102
108
|
refresh,
|
|
103
109
|
signOut,
|
|
104
110
|
rmTimeout,
|
|
111
|
+
getTokenOrUndefined,
|
|
105
112
|
addEventListener: eventTarget.addEventListener.bind(eventTarget),
|
|
106
113
|
removeEventListener: eventTarget.removeEventListener.bind(eventTarget)
|
|
107
114
|
});
|
|
@@ -141,7 +148,7 @@ function createConfidentialOauthClient(client_id, client_secret, url, scopes = [
|
|
|
141
148
|
}
|
|
142
149
|
return getToken;
|
|
143
150
|
}
|
|
144
|
-
function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = [
|
|
151
|
+
function createPublicOauthClient(client_id, url, redirectUrl, useHistory = true, loginPage, postLoginPage = window.location.toString(), scopes = [], fetchFn = globalThis.fetch, ctxPath = "/multipass") {
|
|
145
152
|
const client = {
|
|
146
153
|
client_id,
|
|
147
154
|
token_endpoint_auth_method: "none"
|
|
@@ -150,6 +157,9 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
150
157
|
const oauthHttpOptions = {
|
|
151
158
|
[customFetch]: fetchFn
|
|
152
159
|
};
|
|
160
|
+
if (scopes.length === 0) {
|
|
161
|
+
scopes = ["api:read-data", "api:write-data"];
|
|
162
|
+
}
|
|
153
163
|
const {
|
|
154
164
|
makeTokenAndSaveRefresh,
|
|
155
165
|
getToken
|
|
@@ -169,7 +179,14 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
169
179
|
return;
|
|
170
180
|
}
|
|
171
181
|
try {
|
|
172
|
-
|
|
182
|
+
const result = makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), "refresh");
|
|
183
|
+
if (result && window.location.pathname === new URL(redirectUrl).pathname) {
|
|
184
|
+
const {
|
|
185
|
+
oldUrl
|
|
186
|
+
} = readLocal(client);
|
|
187
|
+
go(oldUrl ?? "/");
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
173
190
|
} catch (e) {
|
|
174
191
|
if (process?.env?.NODE_ENV !== "production") {
|
|
175
192
|
console.warn("Failed to get OAuth2 refresh token. Removing refresh token", e);
|
|
@@ -199,7 +216,7 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
199
216
|
}
|
|
200
217
|
}
|
|
201
218
|
async function initiateLoginRedirect() {
|
|
202
|
-
if (loginPage && window.location.href !== loginPage) {
|
|
219
|
+
if (loginPage && window.location.href !== loginPage && window.location.pathname !== loginPage) {
|
|
203
220
|
saveLocal(client, {
|
|
204
221
|
oldUrl: postLoginPage
|
|
205
222
|
});
|
|
@@ -232,5 +249,5 @@ function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginP
|
|
|
232
249
|
}
|
|
233
250
|
|
|
234
251
|
export { createConfidentialOauthClient, createPublicOauthClient };
|
|
235
|
-
//# sourceMappingURL=
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
236
253
|
//# sourceMappingURL=index.js.map
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/createConfidentialOauthClient.ts","../../src/common.ts","../../src/throwIfError.ts","../../src/createPublicOauthClient.ts"],"names":["CustomEvent","getToken","customFetch"],"mappings":"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","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 */\n\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n\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 = {\n client_id,\n client_secret\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n getToken,\n makeTokenAndSaveRefresh\n } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({\n scope: scopes.join(\" \")\n }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}","/*\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 */\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\" ? globalThis.CustomEvent : globalThis.CustomEvent ?? 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};\nconst localStorage = globalThis.localStorage;\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n 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 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 localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const {\n refresh_token,\n expires_in,\n access_token\n } = resp;\n !(expires_in != null) ? process.env.NODE_ENV !== \"production\" ? invariant(false) : invariant(false) : void 0;\n saveLocal(client, {\n refresh_token\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, {\n detail: token\n }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout) 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 !token ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"not signed in\") : invariant(false) : void 0;\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n\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 } finally {\n pendingSignIn = undefined;\n }\n }\n eventTarget.addEventListener(\"signIn\", restartRefreshTimer);\n eventTarget.addEventListener(\"refresh\", restartRefreshTimer);\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 addEventListener: eventTarget.addEventListener.bind(eventTarget),\n removeEventListener: eventTarget.removeEventListener.bind(eventTarget)\n });\n return {\n getToken,\n makeTokenAndSaveRefresh\n };\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 * 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 */\n\nimport { isOAuth2Error } from \"oauth4webapi\";\nexport function throwIfError(result) {\n if (isOAuth2Error(result)) {\n throw new Error(`Failed to get token: ${result.error}`);\n }\n return result;\n}","/*\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 */\n\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param url the base url of your foundry server\n * @param redirectUrl the url configured for redirect in the oauth configuration on the server\n * @param useHistory if true, when possible uses `history.replaceState()`, otherwise uses `window.location.assign()`\n * @param loginPage if you want a custom landing page prior to logging in, set this to that url\n * @param postLoginPage if you want to customize where you return to after a completed authentication cycle. defaults to the url when the page loaded\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns {PublicOauthClient} which can be used as a token provider\n */\nexport function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = [\"api:read-data\", \"api:write-data\"], fetchFn = globalThis.fetch, ctxPath = \"/multipass\") {\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\"\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n makeTokenAndSaveRefresh,\n getToken\n } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n async function go(x) {\n if (useHistory) return window.history.replaceState({}, \"\", x);else window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\n async function maybeRefresh(expectRefreshToken) {\n const {\n refresh_token\n } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken) 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 return makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), \"refresh\");\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 {\n codeVerifier,\n state,\n oldUrl\n } = readLocal(client);\n if (!codeVerifier) 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)), redirectUrl, codeVerifier, oauthHttpOptions))), \"signIn\");\n go(oldUrl);\n return ret;\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 }\n }\n async function initiateLoginRedirect() {\n if (loginPage && window.location.href !== loginPage) {\n saveLocal(client, {\n oldUrl: postLoginPage\n });\n return await go(loginPage);\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readLocal(client).oldUrl ?? window.location.toString();\n saveLocal(client, {\n codeVerifier,\n state,\n oldUrl\n });\n window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri: redirectUrl,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \")\n })}`);\n\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\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}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/throwIfError.ts","../../src/common.ts","../../src/createConfidentialOauthClient.ts","../../src/createPublicOauthClient.ts"],"names":["CustomEvent","getToken","customFetch"],"mappings":"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","file":"index.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 */\n\nimport { isOAuth2Error } from \"oauth4webapi\";\nexport function throwIfError(result) {\n if (isOAuth2Error(result)) {\n throw new Error(`Failed to get token: ${result.error}`);\n }\n return result;\n}","/*\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 */\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\" ? globalThis.CustomEvent : globalThis.CustomEvent ?? 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};\nconst localStorage = globalThis.localStorage;\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n 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 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 localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const {\n refresh_token,\n expires_in,\n access_token\n } = resp;\n !(expires_in != null) ? process.env.NODE_ENV !== \"production\" ? invariant(false) : invariant(false) : void 0;\n saveLocal(client, {\n refresh_token\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, {\n detail: token\n }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout) 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 !token ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"not signed in\") : invariant(false) : void 0;\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n\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 } 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 {\n getToken,\n makeTokenAndSaveRefresh\n };\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 * 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 */\n\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n\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 = {\n client_id,\n client_secret\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n getToken,\n makeTokenAndSaveRefresh\n } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({\n scope: scopes.join(\" \")\n }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}","/*\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 */\n\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param url the base url of your foundry server\n * @param redirectUrl the url configured for redirect in the oauth configuration on the server\n * @param useHistory if true, when possible uses `history.replaceState()`, otherwise uses `window.location.assign()`\n * @param loginPage if you want a custom landing page prior to logging in, set this to that url\n * @param postLoginPage if you want to customize where you return to after a completed authentication cycle. defaults to the url when the page loaded\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns {PublicOauthClient} which can be used as a token provider\n */\nexport function createPublicOauthClient(client_id, url, redirectUrl, useHistory = true, loginPage, postLoginPage = window.location.toString(), scopes = [], fetchFn = globalThis.fetch, ctxPath = \"/multipass\") {\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\"\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n if (scopes.length === 0) {\n scopes = [\"api:read-data\", \"api:write-data\"];\n }\n const {\n makeTokenAndSaveRefresh,\n getToken\n } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n async function go(x) {\n if (useHistory) return window.history.replaceState({}, \"\", x);else window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\n async function maybeRefresh(expectRefreshToken) {\n const {\n refresh_token\n } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken) 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(redirectUrl).pathname) {\n const {\n oldUrl\n } = readLocal(client);\n go(oldUrl ?? \"/\");\n }\n return result;\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 {\n codeVerifier,\n state,\n oldUrl\n } = readLocal(client);\n if (!codeVerifier) 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)), redirectUrl, codeVerifier, oauthHttpOptions))), \"signIn\");\n go(oldUrl);\n return ret;\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 }\n }\n async function initiateLoginRedirect() {\n if (loginPage && window.location.href !== loginPage && window.location.pathname !== loginPage) {\n saveLocal(client, {\n oldUrl: postLoginPage\n });\n return await go(loginPage);\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readLocal(client).oldUrl ?? window.location.toString();\n saveLocal(client, {\n codeVerifier,\n state,\n oldUrl\n });\n window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri: redirectUrl,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \")\n })}`);\n\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\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}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osdk/oauth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"jest-extended": "^4.0.2",
|
|
27
|
-
"typescript": "^5.5.
|
|
28
|
-
"@osdk/monorepo.tsconfig": "~0.0.0",
|
|
27
|
+
"typescript": "^5.5.4",
|
|
29
28
|
"@osdk/monorepo.api-extractor": "~0.0.0",
|
|
29
|
+
"@osdk/monorepo.tsconfig": "~0.0.0",
|
|
30
30
|
"@osdk/monorepo.tsup": "~0.0.0"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
"templates",
|
|
42
42
|
"*.d.ts"
|
|
43
43
|
],
|
|
44
|
-
"main": "./build/js/index.cjs",
|
|
45
44
|
"module": "./build/esm/index.js",
|
|
46
45
|
"types": "./build/esm/index.d.ts",
|
|
47
46
|
"type": "module",
|
package/build/cjs/index.cjs
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var oauth4webapi = require('oauth4webapi');
|
|
4
|
-
var invariant = require('tiny-invariant');
|
|
5
|
-
var typescriptEventTarget = require('typescript-event-target');
|
|
6
|
-
var delay = require('delay');
|
|
7
|
-
|
|
8
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
var invariant__default = /*#__PURE__*/_interopDefault(invariant);
|
|
11
|
-
var delay__default = /*#__PURE__*/_interopDefault(delay);
|
|
12
|
-
|
|
13
|
-
// src/createConfidentialOauthClient.ts
|
|
14
|
-
function throwIfError(result) {
|
|
15
|
-
if (oauth4webapi.isOAuth2Error(result)) {
|
|
16
|
-
throw new Error(`Failed to get token: ${result.error}`);
|
|
17
|
-
}
|
|
18
|
-
return result;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// src/common.ts
|
|
22
|
-
var CustomEvent = process.env.target === "browser" ? globalThis.CustomEvent : globalThis.CustomEvent ?? class CustomEvent2 extends Event {
|
|
23
|
-
#detail;
|
|
24
|
-
constructor(type, options) {
|
|
25
|
-
super(type, options);
|
|
26
|
-
this.#detail = options?.detail ?? null;
|
|
27
|
-
}
|
|
28
|
-
get detail() {
|
|
29
|
-
return this.#detail;
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
var localStorage = globalThis.localStorage;
|
|
33
|
-
function saveLocal(client, x) {
|
|
34
|
-
localStorage?.setItem(`@osdk/oauth : refresh : ${client.client_id}`, JSON.stringify(x));
|
|
35
|
-
}
|
|
36
|
-
function removeLocal(client) {
|
|
37
|
-
localStorage?.removeItem(`@osdk/oauth : refresh : ${client.client_id}`);
|
|
38
|
-
}
|
|
39
|
-
function readLocal(client) {
|
|
40
|
-
return JSON.parse(
|
|
41
|
-
// MUST `localStorage?` as nodejs does not have localStorage
|
|
42
|
-
localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? "{}"
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
function common(client, as, _signIn, oauthHttpOptions, refresh) {
|
|
46
|
-
let token;
|
|
47
|
-
const eventTarget = new typescriptEventTarget.TypedEventTarget();
|
|
48
|
-
function makeTokenAndSaveRefresh(resp, type) {
|
|
49
|
-
const {
|
|
50
|
-
refresh_token,
|
|
51
|
-
expires_in,
|
|
52
|
-
access_token
|
|
53
|
-
} = resp;
|
|
54
|
-
!(expires_in != null) ? process.env.NODE_ENV !== "production" ? invariant__default.default(false) : invariant__default.default(false) : void 0;
|
|
55
|
-
saveLocal(client, {
|
|
56
|
-
refresh_token
|
|
57
|
-
});
|
|
58
|
-
token = {
|
|
59
|
-
refresh_token,
|
|
60
|
-
expires_in,
|
|
61
|
-
access_token,
|
|
62
|
-
expires_at: Date.now() + expires_in * 1e3
|
|
63
|
-
};
|
|
64
|
-
eventTarget.dispatchTypedEvent(type, new CustomEvent(type, {
|
|
65
|
-
detail: token
|
|
66
|
-
}));
|
|
67
|
-
return token;
|
|
68
|
-
}
|
|
69
|
-
let refreshTimeout;
|
|
70
|
-
function rmTimeout() {
|
|
71
|
-
if (refreshTimeout) clearTimeout(refreshTimeout);
|
|
72
|
-
}
|
|
73
|
-
function restartRefreshTimer(evt) {
|
|
74
|
-
if (refresh) {
|
|
75
|
-
rmTimeout();
|
|
76
|
-
refreshTimeout = setTimeout(refresh, evt.detail.expires_in * 1e3 - 60 * 1e3);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
async function signOut() {
|
|
80
|
-
!token ? process.env.NODE_ENV !== "production" ? invariant__default.default(false, "not signed in") : invariant__default.default(false) : void 0;
|
|
81
|
-
const result = await oauth4webapi.processRevocationResponse(await oauth4webapi.revocationRequest(as, client, token.access_token, oauthHttpOptions));
|
|
82
|
-
rmTimeout();
|
|
83
|
-
removeLocal(client);
|
|
84
|
-
token = void 0;
|
|
85
|
-
throwIfError(result);
|
|
86
|
-
eventTarget.dispatchTypedEvent("signOut", new Event("signOut"));
|
|
87
|
-
}
|
|
88
|
-
let pendingSignIn;
|
|
89
|
-
async function signIn() {
|
|
90
|
-
if (pendingSignIn) {
|
|
91
|
-
return pendingSignIn;
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
pendingSignIn = _signIn();
|
|
95
|
-
return await pendingSignIn;
|
|
96
|
-
} finally {
|
|
97
|
-
pendingSignIn = void 0;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
eventTarget.addEventListener("signIn", restartRefreshTimer);
|
|
101
|
-
eventTarget.addEventListener("refresh", restartRefreshTimer);
|
|
102
|
-
const getToken = Object.assign(async function getToken2() {
|
|
103
|
-
if (!token || Date.now() >= token.expires_at) {
|
|
104
|
-
token = await signIn();
|
|
105
|
-
}
|
|
106
|
-
return token.access_token;
|
|
107
|
-
}, {
|
|
108
|
-
signIn,
|
|
109
|
-
refresh,
|
|
110
|
-
signOut,
|
|
111
|
-
rmTimeout,
|
|
112
|
-
addEventListener: eventTarget.addEventListener.bind(eventTarget),
|
|
113
|
-
removeEventListener: eventTarget.removeEventListener.bind(eventTarget)
|
|
114
|
-
});
|
|
115
|
-
return {
|
|
116
|
-
getToken,
|
|
117
|
-
makeTokenAndSaveRefresh
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function createAuthorizationServer(ctxPath, url) {
|
|
121
|
-
const issuer = `${new URL(ctxPath, url)}`;
|
|
122
|
-
return {
|
|
123
|
-
token_endpoint: `${issuer}/api/oauth2/token`,
|
|
124
|
-
authorization_endpoint: `${issuer}/api/oauth2/authorize`,
|
|
125
|
-
revocation_endpoint: `${issuer}/api/oauth2/revoke_token`,
|
|
126
|
-
issuer
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// src/createConfidentialOauthClient.ts
|
|
131
|
-
function createConfidentialOauthClient(client_id, client_secret, url, scopes = ["api:read-data", "api:write-data"], fetchFn = globalThis.fetch, ctxPath = "/multipass") {
|
|
132
|
-
const client = {
|
|
133
|
-
client_id,
|
|
134
|
-
client_secret
|
|
135
|
-
};
|
|
136
|
-
const authServer = createAuthorizationServer(ctxPath, url);
|
|
137
|
-
const oauthHttpOptions = {
|
|
138
|
-
[oauth4webapi.customFetch]: fetchFn
|
|
139
|
-
};
|
|
140
|
-
const {
|
|
141
|
-
getToken,
|
|
142
|
-
makeTokenAndSaveRefresh
|
|
143
|
-
} = common(client, authServer, _signIn, oauthHttpOptions, void 0);
|
|
144
|
-
async function _signIn() {
|
|
145
|
-
return makeTokenAndSaveRefresh(throwIfError(await oauth4webapi.processClientCredentialsResponse(authServer, client, await oauth4webapi.clientCredentialsGrantRequest(authServer, client, new URLSearchParams({
|
|
146
|
-
scope: scopes.join(" ")
|
|
147
|
-
}), oauthHttpOptions))), "signIn");
|
|
148
|
-
}
|
|
149
|
-
return getToken;
|
|
150
|
-
}
|
|
151
|
-
function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = ["api:read-data", "api:write-data"], fetchFn = globalThis.fetch, ctxPath = "/multipass") {
|
|
152
|
-
const client = {
|
|
153
|
-
client_id,
|
|
154
|
-
token_endpoint_auth_method: "none"
|
|
155
|
-
};
|
|
156
|
-
const authServer = createAuthorizationServer(ctxPath, url);
|
|
157
|
-
const oauthHttpOptions = {
|
|
158
|
-
[oauth4webapi.customFetch]: fetchFn
|
|
159
|
-
};
|
|
160
|
-
const {
|
|
161
|
-
makeTokenAndSaveRefresh,
|
|
162
|
-
getToken
|
|
163
|
-
} = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));
|
|
164
|
-
async function go(x) {
|
|
165
|
-
if (useHistory) return window.history.replaceState({}, "", x);
|
|
166
|
-
else window.location.assign(x);
|
|
167
|
-
await delay__default.default(1e3);
|
|
168
|
-
throw new Error("Unable to redirect");
|
|
169
|
-
}
|
|
170
|
-
async function maybeRefresh(expectRefreshToken) {
|
|
171
|
-
const {
|
|
172
|
-
refresh_token
|
|
173
|
-
} = readLocal(client);
|
|
174
|
-
if (!refresh_token) {
|
|
175
|
-
if (expectRefreshToken) throw new Error("No refresh token found");
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
try {
|
|
179
|
-
return makeTokenAndSaveRefresh(throwIfError(await oauth4webapi.processAuthorizationCodeOAuth2Response(authServer, client, await oauth4webapi.refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), "refresh");
|
|
180
|
-
} catch (e) {
|
|
181
|
-
if (process?.env?.NODE_ENV !== "production") {
|
|
182
|
-
console.warn("Failed to get OAuth2 refresh token. Removing refresh token", e);
|
|
183
|
-
}
|
|
184
|
-
removeLocal(client);
|
|
185
|
-
if (expectRefreshToken) {
|
|
186
|
-
throw new Error("Could not refresh token");
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
async function maybeHandleAuthReturn() {
|
|
191
|
-
const {
|
|
192
|
-
codeVerifier,
|
|
193
|
-
state,
|
|
194
|
-
oldUrl
|
|
195
|
-
} = readLocal(client);
|
|
196
|
-
if (!codeVerifier) return;
|
|
197
|
-
try {
|
|
198
|
-
const ret = makeTokenAndSaveRefresh(throwIfError(await oauth4webapi.processAuthorizationCodeOAuth2Response(authServer, client, await oauth4webapi.authorizationCodeGrantRequest(authServer, client, throwIfError(oauth4webapi.validateAuthResponse(authServer, client, new URL(window.location.href), state)), redirectUrl, codeVerifier, oauthHttpOptions))), "signIn");
|
|
199
|
-
go(oldUrl);
|
|
200
|
-
return ret;
|
|
201
|
-
} catch (e) {
|
|
202
|
-
if (process?.env?.NODE_ENV !== "production") {
|
|
203
|
-
console.warn("Failed to get OAuth2 token using PKCE, removing PKCE and starting a new auth flow", e);
|
|
204
|
-
}
|
|
205
|
-
removeLocal(client);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
async function initiateLoginRedirect() {
|
|
209
|
-
if (loginPage && window.location.href !== loginPage) {
|
|
210
|
-
saveLocal(client, {
|
|
211
|
-
oldUrl: postLoginPage
|
|
212
|
-
});
|
|
213
|
-
return await go(loginPage);
|
|
214
|
-
}
|
|
215
|
-
const state = oauth4webapi.generateRandomState();
|
|
216
|
-
const codeVerifier = oauth4webapi.generateRandomCodeVerifier();
|
|
217
|
-
const oldUrl = readLocal(client).oldUrl ?? window.location.toString();
|
|
218
|
-
saveLocal(client, {
|
|
219
|
-
codeVerifier,
|
|
220
|
-
state,
|
|
221
|
-
oldUrl
|
|
222
|
-
});
|
|
223
|
-
window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({
|
|
224
|
-
client_id,
|
|
225
|
-
response_type: "code",
|
|
226
|
-
state,
|
|
227
|
-
redirect_uri: redirectUrl,
|
|
228
|
-
code_challenge: await oauth4webapi.calculatePKCECodeChallenge(codeVerifier),
|
|
229
|
-
code_challenge_method: "S256",
|
|
230
|
-
scope: ["offline_access", ...scopes].join(" ")
|
|
231
|
-
})}`);
|
|
232
|
-
await delay__default.default(1e3);
|
|
233
|
-
throw new Error("Unable to redirect");
|
|
234
|
-
}
|
|
235
|
-
async function _signIn() {
|
|
236
|
-
return await maybeRefresh() ?? await maybeHandleAuthReturn() ?? await initiateLoginRedirect();
|
|
237
|
-
}
|
|
238
|
-
return getToken;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
exports.createConfidentialOauthClient = createConfidentialOauthClient;
|
|
242
|
-
exports.createPublicOauthClient = createPublicOauthClient;
|
|
243
|
-
//# sourceMappingURL=out.js.map
|
|
244
|
-
//# sourceMappingURL=index.cjs.map
|
package/build/cjs/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/createConfidentialOauthClient.ts","../../src/common.ts","../../src/throwIfError.ts","../../src/createPublicOauthClient.ts"],"names":["CustomEvent","getToken","customFetch"],"mappings":";AAgBA,SAAS,+BAA+B,aAAa,wCAAwC;;;ACA7F,SAAS,2BAA2B,yBAAyB;AAC7D,OAAO,eAAe;AACtB,SAAS,wBAAwB;;;ACFjC,SAAS,qBAAqB;AACvB,SAAS,aAAa,QAAQ;AACnC,MAAI,cAAc,MAAM,GAAG;AACzB,UAAM,IAAI,MAAM,wBAAwB,OAAO,KAAK,EAAE;AAAA,EACxD;AACA,SAAO;AACT;;;ADAA,IAAM,cAAc,QAAQ,IAAI,WAAW,YAAY,WAAW,cAAc,WAAW,eAAe,MAAMA,qBAAoB,MAAM;AAAA,EACxI;AAAA,EACA,YAAY,MAAM,SAAS;AACzB,UAAM,MAAM,OAAO;AACnB,SAAK,UAAU,SAAS,UAAU;AAAA,EACpC;AAAA,EACA,IAAI,SAAS;AACX,WAAO,KAAK;AAAA,EACd;AACF;AACA,IAAM,eAAe,WAAW;AACzB,SAAS,UAAU,QAAQ,GAAG;AAEnC,gBAAc,QAAQ,2BAA2B,OAAO,SAAS,IAAI,KAAK,UAAU,CAAC,CAAC;AACxF;AACO,SAAS,YAAY,QAAQ;AAElC,gBAAc,WAAW,2BAA2B,OAAO,SAAS,EAAE;AACxE;AACO,SAAS,UAAU,QAAQ;AAChC,SAAO,KAAK;AAAA;AAAA,IAEZ,cAAc,QAAQ,2BAA2B,OAAO,SAAS,EAAE,KAAK;AAAA,EAAI;AAC9E;AACO,SAAS,OAAO,QAAQ,IAAI,SAAS,kBAAkB,SAAS;AACrE,MAAI;AACJ,QAAM,cAAc,IAAI,iBAAiB;AACzC,WAAS,wBAAwB,MAAM,MAAM;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AACJ,MAAE,cAAc,QAAQ,QAAQ,IAAI,aAAa,eAAe,UAAU,KAAK,IAAI,UAAU,KAAK,IAAI;AACtG,cAAU,QAAQ;AAAA,MAChB;AAAA,IACF,CAAC;AACD,YAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI,IAAI,aAAa;AAAA,IACxC;AACA,gBAAY,mBAAmB,MAAM,IAAI,YAAY,MAAM;AAAA,MACzD,QAAQ;AAAA,IACV,CAAC,CAAC;AACF,WAAO;AAAA,EACT;AACA,MAAI;AACJ,WAAS,YAAY;AACnB,QAAI,eAAgB,cAAa,cAAc;AAAA,EACjD;AACA,WAAS,oBAAoB,KAAK;AAChC,QAAI,SAAS;AACX,gBAAU;AACV,uBAAiB,WAAW,SAAS,IAAI,OAAO,aAAa,MAAO,KAAK,GAAI;AAAA,IAC/E;AAAA,EACF;AACA,iBAAe,UAAU;AACvB,KAAC,QAAQ,QAAQ,IAAI,aAAa,eAAe,UAAU,OAAO,eAAe,IAAI,UAAU,KAAK,IAAI;AACxG,UAAM,SAAS,MAAM,0BAA0B,MAAM,kBAAkB,IAAI,QAAQ,MAAM,cAAc,gBAAgB,CAAC;AACxH,cAAU;AAGV,gBAAY,MAAM;AAClB,YAAQ;AACR,iBAAa,MAAM;AACnB,gBAAY,mBAAmB,WAAW,IAAI,MAAM,SAAS,CAAC;AAAA,EAChE;AACA,MAAI;AACJ,iBAAe,SAAS;AACtB,QAAI,eAAe;AACjB,aAAO;AAAA,IACT;AACA,QAAI;AACF,sBAAgB,QAAQ;AACxB,aAAO,MAAM;AAAA,IACf,UAAE;AACA,sBAAgB;AAAA,IAClB;AAAA,EACF;AACA,cAAY,iBAAiB,UAAU,mBAAmB;AAC1D,cAAY,iBAAiB,WAAW,mBAAmB;AAC3D,QAAM,WAAW,OAAO,OAAO,eAAeC,YAAW;AACvD,QAAI,CAAC,SAAS,KAAK,IAAI,KAAK,MAAM,YAAY;AAC5C,cAAQ,MAAM,OAAO;AAAA,IACvB;AACA,WAAO,MAAM;AAAA,EACf,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,YAAY,iBAAiB,KAAK,WAAW;AAAA,IAC/D,qBAAqB,YAAY,oBAAoB,KAAK,WAAW;AAAA,EACvE,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AACO,SAAS,0BAA0B,SAAS,KAAK;AACtD,QAAM,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG,CAAC;AACvC,SAAO;AAAA,IACL,gBAAgB,GAAG,MAAM;AAAA,IACzB,wBAAwB,GAAG,MAAM;AAAA,IACjC,qBAAqB,GAAG,MAAM;AAAA,IAC9B;AAAA,EACF;AACF;;;ADtGO,SAAS,8BAA8B,WAAW,eAAe,KAAK,SAAS,CAAC,iBAAiB,gBAAgB,GAAG,UAAU,WAAW,OAAO,UAAU,cAAc;AAC7K,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,EACF;AACA,QAAM,aAAa,0BAA0B,SAAS,GAAG;AACzD,QAAM,mBAAmB;AAAA,IACvB,CAAC,WAAW,GAAG;AAAA,EACjB;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF,IAAI,OAAO,QAAQ,YAAY,SAAS,kBAAkB,MAAS;AACnE,iBAAe,UAAU;AACvB,WAAO,wBAAwB,aAAa,MAAM,iCAAiC,YAAY,QAAQ,MAAM,8BAA8B,YAAY,QAAQ,IAAI,gBAAgB;AAAA,MACjL,OAAO,OAAO,KAAK,GAAG;AAAA,IACxB,CAAC,GAAG,gBAAgB,CAAC,CAAC,GAAG,QAAQ;AAAA,EACnC;AACA,SAAO;AACT;;;AGhCA,OAAO,WAAW;AAClB,SAAS,+BAA+B,4BAA4B,eAAAC,cAAa,4BAA4B,qBAAqB,wCAAwC,0BAA0B,4BAA4B;AAezN,SAAS,wBAAwB,WAAW,KAAK,aAAa,YAAY,WAAW,gBAAgB,OAAO,SAAS,SAAS,GAAG,SAAS,CAAC,iBAAiB,gBAAgB,GAAG,UAAU,WAAW,OAAO,UAAU,cAAc;AACxO,QAAM,SAAS;AAAA,IACb;AAAA,IACA,4BAA4B;AAAA,EAC9B;AACA,QAAM,aAAa,0BAA0B,SAAS,GAAG;AACzD,QAAM,mBAAmB;AAAA,IACvB,CAACA,YAAW,GAAG;AAAA,EACjB;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF,IAAI,OAAO,QAAQ,YAAY,SAAS,kBAAkB,aAAa,KAAK,YAAY,IAAI,CAAC;AAC7F,iBAAe,GAAG,GAAG;AACnB,QAAI,WAAY,QAAO,OAAO,QAAQ,aAAa,CAAC,GAAG,IAAI,CAAC;AAAA,QAAO,QAAO,SAAS,OAAO,CAAC;AAC3F,UAAM,MAAM,GAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AACA,iBAAe,aAAa,oBAAoB;AAC9C,UAAM;AAAA,MACJ;AAAA,IACF,IAAI,UAAU,MAAM;AACpB,QAAI,CAAC,eAAe;AAClB,UAAI,mBAAoB,OAAM,IAAI,MAAM,wBAAwB;AAChE;AAAA,IACF;AACA,QAAI;AAGF,aAAO,wBAAwB,aAAa,MAAM,uCAAuC,YAAY,QAAQ,MAAM,yBAAyB,YAAY,QAAQ,eAAe,gBAAgB,CAAC,CAAC,GAAG,SAAS;AAAA,IAC/M,SAAS,GAAG;AACV,UAAI,SAAS,KAAK,aAAa,cAAc;AAE3C,gBAAQ,KAAK,8DAA8D,CAAC;AAAA,MAC9E;AACA,kBAAY,MAAM;AAClB,UAAI,oBAAoB;AACtB,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACA,iBAAe,wBAAwB;AACrC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,UAAU,MAAM;AACpB,QAAI,CAAC,aAAc;AACnB,QAAI;AACF,YAAM,MAAM,wBAAwB,aAAa,MAAM,uCAAuC,YAAY,QAAQ,MAAM,8BAA8B,YAAY,QAAQ,aAAa,qBAAqB,YAAY,QAAQ,IAAI,IAAI,OAAO,SAAS,IAAI,GAAG,KAAK,CAAC,GAAG,aAAa,cAAc,gBAAgB,CAAC,CAAC,GAAG,QAAQ;AAChU,SAAG,MAAM;AACT,aAAO;AAAA,IACT,SAAS,GAAG;AACV,UAAI,SAAS,KAAK,aAAa,cAAc;AAE3C,gBAAQ,KAAK,qFAAqF,CAAC;AAAA,MACrG;AACA,kBAAY,MAAM;AAAA,IACpB;AAAA,EACF;AACA,iBAAe,wBAAwB;AACrC,QAAI,aAAa,OAAO,SAAS,SAAS,WAAW;AACnD,gBAAU,QAAQ;AAAA,QAChB,QAAQ;AAAA,MACV,CAAC;AACD,aAAO,MAAM,GAAG,SAAS;AAAA,IAC3B;AACA,UAAM,QAAQ,oBAAoB;AAClC,UAAM,eAAe,2BAA2B;AAChD,UAAM,SAAS,UAAU,MAAM,EAAE,UAAU,OAAO,SAAS,SAAS;AACpE,cAAU,QAAQ;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS,OAAO,GAAG,WAAW,sBAAsB,IAAI,IAAI,gBAAgB;AAAA,MACjF;AAAA,MACA,eAAe;AAAA,MACf;AAAA,MACA,cAAc;AAAA,MACd,gBAAgB,MAAM,2BAA2B,YAAY;AAAA,MAC7D,uBAAuB;AAAA,MACvB,OAAO,CAAC,kBAAkB,GAAG,MAAM,EAAE,KAAK,GAAG;AAAA,IAC/C,CAAC,CAAC,EAAE;AAGJ,UAAM,MAAM,GAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAGA,iBAAe,UAAU;AAEvB,WAAQ,MAAM,aAAa,KAErB,MAAM,sBAAsB,KAE9B,MAAM,sBAAsB;AAAA,EAClC;AACA,SAAO;AACT","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 */\n\nimport { clientCredentialsGrantRequest, customFetch, processClientCredentialsResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n\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 = {\n client_id,\n client_secret\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n getToken,\n makeTokenAndSaveRefresh\n } = common(client, authServer, _signIn, oauthHttpOptions, undefined);\n async function _signIn() {\n return makeTokenAndSaveRefresh(throwIfError(await processClientCredentialsResponse(authServer, client, await clientCredentialsGrantRequest(authServer, client, new URLSearchParams({\n scope: scopes.join(\" \")\n }), oauthHttpOptions))), \"signIn\");\n }\n return getToken;\n}","/*\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 */\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\" ? globalThis.CustomEvent : globalThis.CustomEvent ?? 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};\nconst localStorage = globalThis.localStorage;\nexport function saveLocal(client, x) {\n // MUST `localStorage?` as nodejs does not have localStorage\n 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 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 localStorage?.getItem(`@osdk/oauth : refresh : ${client.client_id}`) ?? \"{}\");\n}\nexport function common(client, as, _signIn, oauthHttpOptions, refresh) {\n let token;\n const eventTarget = new TypedEventTarget();\n function makeTokenAndSaveRefresh(resp, type) {\n const {\n refresh_token,\n expires_in,\n access_token\n } = resp;\n !(expires_in != null) ? process.env.NODE_ENV !== \"production\" ? invariant(false) : invariant(false) : void 0;\n saveLocal(client, {\n refresh_token\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, {\n detail: token\n }));\n return token;\n }\n let refreshTimeout;\n function rmTimeout() {\n if (refreshTimeout) 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 !token ? process.env.NODE_ENV !== \"production\" ? invariant(false, \"not signed in\") : invariant(false) : void 0;\n const result = await processRevocationResponse(await revocationRequest(as, client, token.access_token, oauthHttpOptions));\n rmTimeout();\n\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 } finally {\n pendingSignIn = undefined;\n }\n }\n eventTarget.addEventListener(\"signIn\", restartRefreshTimer);\n eventTarget.addEventListener(\"refresh\", restartRefreshTimer);\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 addEventListener: eventTarget.addEventListener.bind(eventTarget),\n removeEventListener: eventTarget.removeEventListener.bind(eventTarget)\n });\n return {\n getToken,\n makeTokenAndSaveRefresh\n };\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 * 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 */\n\nimport { isOAuth2Error } from \"oauth4webapi\";\nexport function throwIfError(result) {\n if (isOAuth2Error(result)) {\n throw new Error(`Failed to get token: ${result.error}`);\n }\n return result;\n}","/*\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 */\n\nimport delay from \"delay\";\nimport { authorizationCodeGrantRequest, calculatePKCECodeChallenge, customFetch, generateRandomCodeVerifier, generateRandomState, processAuthorizationCodeOAuth2Response, refreshTokenGrantRequest, validateAuthResponse } from \"oauth4webapi\";\nimport { common, createAuthorizationServer, readLocal, removeLocal, saveLocal } from \"./common.js\";\nimport { throwIfError } from \"./throwIfError.js\";\n/**\n * @param client_id\n * @param url the base url of your foundry server\n * @param redirectUrl the url configured for redirect in the oauth configuration on the server\n * @param useHistory if true, when possible uses `history.replaceState()`, otherwise uses `window.location.assign()`\n * @param loginPage if you want a custom landing page prior to logging in, set this to that url\n * @param postLoginPage if you want to customize where you return to after a completed authentication cycle. defaults to the url when the page loaded\n * @param scopes\n * @param fetchFn\n * @param ctxPath\n * @returns {PublicOauthClient} which can be used as a token provider\n */\nexport function createPublicOauthClient(client_id, url, redirectUrl, useHistory, loginPage, postLoginPage = window.location.toString(), scopes = [\"api:read-data\", \"api:write-data\"], fetchFn = globalThis.fetch, ctxPath = \"/multipass\") {\n const client = {\n client_id,\n token_endpoint_auth_method: \"none\"\n };\n const authServer = createAuthorizationServer(ctxPath, url);\n const oauthHttpOptions = {\n [customFetch]: fetchFn\n };\n const {\n makeTokenAndSaveRefresh,\n getToken\n } = common(client, authServer, _signIn, oauthHttpOptions, maybeRefresh.bind(globalThis, true));\n async function go(x) {\n if (useHistory) return window.history.replaceState({}, \"\", x);else window.location.assign(x);\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\n async function maybeRefresh(expectRefreshToken) {\n const {\n refresh_token\n } = readLocal(client);\n if (!refresh_token) {\n if (expectRefreshToken) 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 return makeTokenAndSaveRefresh(throwIfError(await processAuthorizationCodeOAuth2Response(authServer, client, await refreshTokenGrantRequest(authServer, client, refresh_token, oauthHttpOptions))), \"refresh\");\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 {\n codeVerifier,\n state,\n oldUrl\n } = readLocal(client);\n if (!codeVerifier) 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)), redirectUrl, codeVerifier, oauthHttpOptions))), \"signIn\");\n go(oldUrl);\n return ret;\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 }\n }\n async function initiateLoginRedirect() {\n if (loginPage && window.location.href !== loginPage) {\n saveLocal(client, {\n oldUrl: postLoginPage\n });\n return await go(loginPage);\n }\n const state = generateRandomState();\n const codeVerifier = generateRandomCodeVerifier();\n const oldUrl = readLocal(client).oldUrl ?? window.location.toString();\n saveLocal(client, {\n codeVerifier,\n state,\n oldUrl\n });\n window.location.assign(`${authServer.authorization_endpoint}?${new URLSearchParams({\n client_id,\n response_type: \"code\",\n state,\n redirect_uri: redirectUrl,\n code_challenge: await calculatePKCECodeChallenge(codeVerifier),\n code_challenge_method: \"S256\",\n scope: [\"offline_access\", ...scopes].join(\" \")\n })}`);\n\n // Give time for redirect to happen\n await delay(1000);\n throw new Error(\"Unable to redirect\");\n }\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}"]}
|