oauth.do 0.1.14 → 0.2.0
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/LICENSE +21 -0
- package/README.md +231 -6
- package/bin/duckdb-auth +71 -0
- package/dist/cli.js +125 -276
- package/dist/cli.js.map +1 -1
- package/dist/hono.d.ts +137 -0
- package/dist/hono.js +198 -0
- package/dist/hono.js.map +1 -0
- package/dist/index.d.ts +6 -90
- package/dist/index.js +77 -24
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +2 -1
- package/dist/node.js +151 -101
- package/dist/node.js.map +1 -1
- package/dist/react.d.ts +200 -0
- package/dist/react.js +67 -0
- package/dist/react.js.map +1 -0
- package/dist/types-export.d.ts +90 -0
- package/dist/types-export.js +3 -0
- package/dist/types-export.js.map +1 -0
- package/package.json +79 -9
package/dist/node.js
CHANGED
|
@@ -8,6 +8,17 @@ var __export = (target, all) => {
|
|
|
8
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
+
// src/utils.ts
|
|
12
|
+
function getEnv(key) {
|
|
13
|
+
if (globalThis[key]) return globalThis[key];
|
|
14
|
+
if (typeof process !== "undefined" && process.env?.[key]) return process.env[key];
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
var init_utils = __esm({
|
|
18
|
+
"src/utils.ts"() {
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
11
22
|
// src/storage.ts
|
|
12
23
|
var storage_exports = {};
|
|
13
24
|
__export(storage_exports, {
|
|
@@ -22,10 +33,6 @@ __export(storage_exports, {
|
|
|
22
33
|
function isNode() {
|
|
23
34
|
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
24
35
|
}
|
|
25
|
-
function getEnv2(key) {
|
|
26
|
-
if (typeof process !== "undefined" && process.env?.[key]) return process.env[key];
|
|
27
|
-
return void 0;
|
|
28
|
-
}
|
|
29
36
|
function createSecureStorage(storagePath) {
|
|
30
37
|
if (isNode()) {
|
|
31
38
|
return new SecureFileTokenStorage(storagePath);
|
|
@@ -38,6 +45,7 @@ function createSecureStorage(storagePath) {
|
|
|
38
45
|
var KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, KeychainTokenStorage, SecureFileTokenStorage, FileTokenStorage, MemoryTokenStorage, LocalStorageTokenStorage, CompositeTokenStorage;
|
|
39
46
|
var init_storage = __esm({
|
|
40
47
|
"src/storage.ts"() {
|
|
48
|
+
init_utils();
|
|
41
49
|
KEYCHAIN_SERVICE = "oauth.do";
|
|
42
50
|
KEYCHAIN_ACCOUNT = "access_token";
|
|
43
51
|
KeychainTokenStorage = class {
|
|
@@ -57,7 +65,7 @@ var init_storage = __esm({
|
|
|
57
65
|
const keytarModule = imported.default || imported;
|
|
58
66
|
this.keytar = keytarModule;
|
|
59
67
|
if (typeof this.keytar.getPassword !== "function") {
|
|
60
|
-
if (
|
|
68
|
+
if (getEnv("DEBUG")) {
|
|
61
69
|
console.warn("Keytar module loaded but getPassword is not a function:", Object.keys(this.keytar));
|
|
62
70
|
}
|
|
63
71
|
this.keytar = null;
|
|
@@ -65,7 +73,7 @@ var init_storage = __esm({
|
|
|
65
73
|
}
|
|
66
74
|
return this.keytar;
|
|
67
75
|
} catch (error) {
|
|
68
|
-
if (
|
|
76
|
+
if (getEnv("DEBUG")) {
|
|
69
77
|
console.warn("Keychain storage not available:", error);
|
|
70
78
|
}
|
|
71
79
|
return null;
|
|
@@ -80,7 +88,7 @@ var init_storage = __esm({
|
|
|
80
88
|
const token = await keytar.getPassword(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT);
|
|
81
89
|
return token;
|
|
82
90
|
} catch (error) {
|
|
83
|
-
if (
|
|
91
|
+
if (getEnv("DEBUG")) {
|
|
84
92
|
console.warn("Failed to get token from keychain:", error);
|
|
85
93
|
}
|
|
86
94
|
return null;
|
|
@@ -122,7 +130,7 @@ var init_storage = __esm({
|
|
|
122
130
|
await keytar.getPassword(KEYCHAIN_SERVICE, "__test__");
|
|
123
131
|
return true;
|
|
124
132
|
} catch (error) {
|
|
125
|
-
if (
|
|
133
|
+
if (getEnv("DEBUG")) {
|
|
126
134
|
console.warn("Keychain not available:", error);
|
|
127
135
|
}
|
|
128
136
|
return false;
|
|
@@ -167,7 +175,7 @@ var init_storage = __esm({
|
|
|
167
175
|
const fs = await import('fs/promises');
|
|
168
176
|
const stats = await fs.stat(this.tokenPath);
|
|
169
177
|
const mode = stats.mode & 511;
|
|
170
|
-
if (mode !== 384 &&
|
|
178
|
+
if (mode !== 384 && getEnv("DEBUG")) {
|
|
171
179
|
console.warn(
|
|
172
180
|
`Warning: Token file has insecure permissions (${mode.toString(8)}). Expected 600. Run: chmod 600 ${this.tokenPath}`
|
|
173
181
|
);
|
|
@@ -346,7 +354,7 @@ var init_storage = __esm({
|
|
|
346
354
|
try {
|
|
347
355
|
await this.keychainStorage.setToken(fileToken);
|
|
348
356
|
await this.fileStorage.removeToken();
|
|
349
|
-
if (
|
|
357
|
+
if (getEnv("DEBUG")) {
|
|
350
358
|
console.log("Migrated token from file to keychain");
|
|
351
359
|
}
|
|
352
360
|
} catch {
|
|
@@ -377,11 +385,7 @@ var init_storage = __esm({
|
|
|
377
385
|
});
|
|
378
386
|
|
|
379
387
|
// src/config.ts
|
|
380
|
-
|
|
381
|
-
if (globalThis[key]) return globalThis[key];
|
|
382
|
-
if (typeof process !== "undefined" && process.env?.[key]) return process.env[key];
|
|
383
|
-
return void 0;
|
|
384
|
-
}
|
|
388
|
+
init_utils();
|
|
385
389
|
var globalConfig = {
|
|
386
390
|
apiUrl: getEnv("OAUTH_API_URL") || getEnv("API_URL") || "https://apis.do",
|
|
387
391
|
clientId: getEnv("OAUTH_CLIENT_ID") || "client_01JQYTRXK9ZPD8JPJTKDCRB656",
|
|
@@ -400,6 +404,7 @@ function getConfig() {
|
|
|
400
404
|
}
|
|
401
405
|
|
|
402
406
|
// src/auth.ts
|
|
407
|
+
init_utils();
|
|
403
408
|
async function resolveSecret(value) {
|
|
404
409
|
if (!value) return null;
|
|
405
410
|
if (typeof value === "string") return value;
|
|
@@ -408,14 +413,9 @@ async function resolveSecret(value) {
|
|
|
408
413
|
}
|
|
409
414
|
return null;
|
|
410
415
|
}
|
|
411
|
-
function getEnv3(key) {
|
|
412
|
-
if (globalThis[key]) return globalThis[key];
|
|
413
|
-
if (typeof process !== "undefined" && process.env?.[key]) return process.env[key];
|
|
414
|
-
return void 0;
|
|
415
|
-
}
|
|
416
416
|
async function getUser(token) {
|
|
417
417
|
const config = getConfig();
|
|
418
|
-
const authToken = token ||
|
|
418
|
+
const authToken = token || getEnv("DO_TOKEN") || "";
|
|
419
419
|
if (!authToken) {
|
|
420
420
|
return { user: null };
|
|
421
421
|
}
|
|
@@ -462,7 +462,7 @@ async function login(credentials) {
|
|
|
462
462
|
}
|
|
463
463
|
async function logout(token) {
|
|
464
464
|
const config = getConfig();
|
|
465
|
-
const authToken = token ||
|
|
465
|
+
const authToken = token || getEnv("DO_TOKEN") || "";
|
|
466
466
|
if (!authToken) {
|
|
467
467
|
return;
|
|
468
468
|
}
|
|
@@ -481,10 +481,15 @@ async function logout(token) {
|
|
|
481
481
|
console.error("Logout error:", error);
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
|
+
var REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
485
|
+
function isTokenExpired(expiresAt) {
|
|
486
|
+
if (!expiresAt) return false;
|
|
487
|
+
return Date.now() >= expiresAt - REFRESH_BUFFER_MS;
|
|
488
|
+
}
|
|
484
489
|
async function getToken() {
|
|
485
|
-
const adminToken =
|
|
490
|
+
const adminToken = getEnv("DO_ADMIN_TOKEN");
|
|
486
491
|
if (adminToken) return adminToken;
|
|
487
|
-
const doToken =
|
|
492
|
+
const doToken = getEnv("DO_TOKEN");
|
|
488
493
|
if (doToken) return doToken;
|
|
489
494
|
try {
|
|
490
495
|
const { env } = await import('cloudflare:workers');
|
|
@@ -498,6 +503,32 @@ async function getToken() {
|
|
|
498
503
|
const { createSecureStorage: createSecureStorage2 } = await Promise.resolve().then(() => (init_storage(), storage_exports));
|
|
499
504
|
const config = getConfig();
|
|
500
505
|
const storage = createSecureStorage2(config.storagePath);
|
|
506
|
+
const tokenData = storage.getTokenData ? await storage.getTokenData() : null;
|
|
507
|
+
if (tokenData) {
|
|
508
|
+
if (!isTokenExpired(tokenData.expiresAt)) {
|
|
509
|
+
return tokenData.accessToken;
|
|
510
|
+
}
|
|
511
|
+
if (tokenData.refreshToken) {
|
|
512
|
+
try {
|
|
513
|
+
const newTokens = await refreshAccessToken(tokenData.refreshToken);
|
|
514
|
+
const expiresAt = newTokens.expires_in ? Date.now() + newTokens.expires_in * 1e3 : void 0;
|
|
515
|
+
const newData = {
|
|
516
|
+
accessToken: newTokens.access_token,
|
|
517
|
+
refreshToken: newTokens.refresh_token || tokenData.refreshToken,
|
|
518
|
+
expiresAt
|
|
519
|
+
};
|
|
520
|
+
if (storage.setTokenData) {
|
|
521
|
+
await storage.setTokenData(newData);
|
|
522
|
+
} else {
|
|
523
|
+
await storage.setToken(newTokens.access_token);
|
|
524
|
+
}
|
|
525
|
+
return newTokens.access_token;
|
|
526
|
+
} catch {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
501
532
|
return await storage.getToken();
|
|
502
533
|
} catch {
|
|
503
534
|
return null;
|
|
@@ -768,97 +799,116 @@ init_storage();
|
|
|
768
799
|
|
|
769
800
|
// src/login.ts
|
|
770
801
|
init_storage();
|
|
771
|
-
var
|
|
772
|
-
|
|
802
|
+
var REFRESH_BUFFER_MS2 = 5 * 60 * 1e3;
|
|
803
|
+
var loginInProgress = null;
|
|
804
|
+
var refreshInProgress = null;
|
|
805
|
+
function isTokenExpired2(expiresAt) {
|
|
773
806
|
if (!expiresAt) return false;
|
|
774
|
-
return Date.now() >= expiresAt -
|
|
807
|
+
return Date.now() >= expiresAt - REFRESH_BUFFER_MS2;
|
|
808
|
+
}
|
|
809
|
+
async function doRefresh(tokenData, storage) {
|
|
810
|
+
if (refreshInProgress) {
|
|
811
|
+
return refreshInProgress;
|
|
812
|
+
}
|
|
813
|
+
refreshInProgress = (async () => {
|
|
814
|
+
try {
|
|
815
|
+
const newTokens = await refreshAccessToken(tokenData.refreshToken);
|
|
816
|
+
const expiresAt = newTokens.expires_in ? Date.now() + newTokens.expires_in * 1e3 : void 0;
|
|
817
|
+
const newData = {
|
|
818
|
+
accessToken: newTokens.access_token,
|
|
819
|
+
refreshToken: newTokens.refresh_token || tokenData.refreshToken,
|
|
820
|
+
expiresAt
|
|
821
|
+
};
|
|
822
|
+
if (storage?.setTokenData) {
|
|
823
|
+
await storage.setTokenData(newData);
|
|
824
|
+
} else if (storage?.setToken) {
|
|
825
|
+
await storage.setToken(newTokens.access_token);
|
|
826
|
+
}
|
|
827
|
+
return { token: newTokens.access_token, isNewLogin: false };
|
|
828
|
+
} finally {
|
|
829
|
+
refreshInProgress = null;
|
|
830
|
+
}
|
|
831
|
+
})();
|
|
832
|
+
return refreshInProgress;
|
|
833
|
+
}
|
|
834
|
+
async function doDeviceLogin(options) {
|
|
835
|
+
if (loginInProgress) {
|
|
836
|
+
return loginInProgress;
|
|
837
|
+
}
|
|
838
|
+
const config = getConfig();
|
|
839
|
+
const {
|
|
840
|
+
openBrowser = true,
|
|
841
|
+
print = console.log,
|
|
842
|
+
provider,
|
|
843
|
+
storage = createSecureStorage(config.storagePath)
|
|
844
|
+
} = options;
|
|
845
|
+
loginInProgress = (async () => {
|
|
846
|
+
try {
|
|
847
|
+
print("\nLogging in...\n");
|
|
848
|
+
const authResponse = await authorizeDevice({ provider });
|
|
849
|
+
print(`To complete login:`);
|
|
850
|
+
print(` 1. Visit: ${authResponse.verification_uri}`);
|
|
851
|
+
print(` 2. Enter code: ${authResponse.user_code}`);
|
|
852
|
+
print(`
|
|
853
|
+
Or open: ${authResponse.verification_uri_complete}
|
|
854
|
+
`);
|
|
855
|
+
if (openBrowser) {
|
|
856
|
+
try {
|
|
857
|
+
const open = await import('open');
|
|
858
|
+
await open.default(authResponse.verification_uri_complete);
|
|
859
|
+
print("Browser opened automatically\n");
|
|
860
|
+
} catch {
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
print("Waiting for authorization...\n");
|
|
864
|
+
const tokenResponse = await pollForTokens(
|
|
865
|
+
authResponse.device_code,
|
|
866
|
+
authResponse.interval,
|
|
867
|
+
authResponse.expires_in
|
|
868
|
+
);
|
|
869
|
+
const expiresAt = tokenResponse.expires_in ? Date.now() + tokenResponse.expires_in * 1e3 : void 0;
|
|
870
|
+
const newData = {
|
|
871
|
+
accessToken: tokenResponse.access_token,
|
|
872
|
+
refreshToken: tokenResponse.refresh_token,
|
|
873
|
+
expiresAt
|
|
874
|
+
};
|
|
875
|
+
if (storage.setTokenData) {
|
|
876
|
+
await storage.setTokenData(newData);
|
|
877
|
+
} else {
|
|
878
|
+
await storage.setToken(tokenResponse.access_token);
|
|
879
|
+
}
|
|
880
|
+
print("Login successful!\n");
|
|
881
|
+
return { token: tokenResponse.access_token, isNewLogin: true };
|
|
882
|
+
} finally {
|
|
883
|
+
loginInProgress = null;
|
|
884
|
+
}
|
|
885
|
+
})();
|
|
886
|
+
return loginInProgress;
|
|
775
887
|
}
|
|
776
888
|
async function ensureLoggedIn(options = {}) {
|
|
777
889
|
const config = getConfig();
|
|
778
|
-
const {
|
|
890
|
+
const { storage = createSecureStorage(config.storagePath) } = options;
|
|
779
891
|
const tokenData = storage.getTokenData ? await storage.getTokenData() : null;
|
|
780
892
|
const existingToken = tokenData?.accessToken || await storage.getToken();
|
|
781
893
|
if (existingToken) {
|
|
782
|
-
if (tokenData &&
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
expiresAt: expiresAt2
|
|
791
|
-
};
|
|
792
|
-
if (storage.setTokenData) {
|
|
793
|
-
await storage.setTokenData(newData2);
|
|
794
|
-
} else {
|
|
795
|
-
await storage.setToken(newTokens.access_token);
|
|
796
|
-
}
|
|
797
|
-
return { token: newTokens.access_token, isNewLogin: false };
|
|
798
|
-
} catch (error) {
|
|
799
|
-
console.warn("Token refresh failed:", error);
|
|
800
|
-
}
|
|
894
|
+
if (tokenData?.expiresAt && !isTokenExpired2(tokenData.expiresAt)) {
|
|
895
|
+
return { token: existingToken, isNewLogin: false };
|
|
896
|
+
}
|
|
897
|
+
if (tokenData?.refreshToken) {
|
|
898
|
+
try {
|
|
899
|
+
return await doRefresh(tokenData, storage);
|
|
900
|
+
} catch (error) {
|
|
901
|
+
console.warn("Token refresh failed:", error);
|
|
801
902
|
}
|
|
802
|
-
}
|
|
903
|
+
}
|
|
904
|
+
if (!tokenData?.expiresAt && !tokenData?.refreshToken) {
|
|
803
905
|
const { user } = await getUser(existingToken);
|
|
804
906
|
if (user) {
|
|
805
907
|
return { token: existingToken, isNewLogin: false };
|
|
806
908
|
}
|
|
807
|
-
if (tokenData?.refreshToken) {
|
|
808
|
-
try {
|
|
809
|
-
const newTokens = await refreshAccessToken(tokenData.refreshToken);
|
|
810
|
-
const expiresAt2 = newTokens.expires_in ? Date.now() + newTokens.expires_in * 1e3 : void 0;
|
|
811
|
-
const newData2 = {
|
|
812
|
-
accessToken: newTokens.access_token,
|
|
813
|
-
refreshToken: newTokens.refresh_token || tokenData.refreshToken,
|
|
814
|
-
expiresAt: expiresAt2
|
|
815
|
-
};
|
|
816
|
-
if (storage.setTokenData) {
|
|
817
|
-
await storage.setTokenData(newData2);
|
|
818
|
-
} else {
|
|
819
|
-
await storage.setToken(newTokens.access_token);
|
|
820
|
-
}
|
|
821
|
-
return { token: newTokens.access_token, isNewLogin: false };
|
|
822
|
-
} catch {
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
909
|
}
|
|
826
910
|
}
|
|
827
|
-
|
|
828
|
-
const authResponse = await authorizeDevice({ provider });
|
|
829
|
-
print(`To complete login:`);
|
|
830
|
-
print(` 1. Visit: ${authResponse.verification_uri}`);
|
|
831
|
-
print(` 2. Enter code: ${authResponse.user_code}`);
|
|
832
|
-
print(`
|
|
833
|
-
Or open: ${authResponse.verification_uri_complete}
|
|
834
|
-
`);
|
|
835
|
-
if (openBrowser) {
|
|
836
|
-
try {
|
|
837
|
-
const open = await import('open');
|
|
838
|
-
await open.default(authResponse.verification_uri_complete);
|
|
839
|
-
print("Browser opened automatically\n");
|
|
840
|
-
} catch {
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
print("Waiting for authorization...\n");
|
|
844
|
-
const tokenResponse = await pollForTokens(
|
|
845
|
-
authResponse.device_code,
|
|
846
|
-
authResponse.interval,
|
|
847
|
-
authResponse.expires_in
|
|
848
|
-
);
|
|
849
|
-
const expiresAt = tokenResponse.expires_in ? Date.now() + tokenResponse.expires_in * 1e3 : void 0;
|
|
850
|
-
const newData = {
|
|
851
|
-
accessToken: tokenResponse.access_token,
|
|
852
|
-
refreshToken: tokenResponse.refresh_token,
|
|
853
|
-
expiresAt
|
|
854
|
-
};
|
|
855
|
-
if (storage.setTokenData) {
|
|
856
|
-
await storage.setTokenData(newData);
|
|
857
|
-
} else {
|
|
858
|
-
await storage.setToken(tokenResponse.access_token);
|
|
859
|
-
}
|
|
860
|
-
print("Login successful!\n");
|
|
861
|
-
return { token: tokenResponse.access_token, isNewLogin: true };
|
|
911
|
+
return doDeviceLogin(options);
|
|
862
912
|
}
|
|
863
913
|
async function forceLogin(options = {}) {
|
|
864
914
|
const config = getConfig();
|