@hanzo/browser-extension 1.7.5 → 1.7.6
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/dist/browser-extension/background-firefox.js +38 -26
- package/dist/browser-extension/background.js +38 -26
- package/dist/browser-extension/chrome/background.js +38 -26
- package/dist/browser-extension/chrome/manifest.json +1 -1
- package/dist/browser-extension/firefox/background.js +38 -26
- package/dist/browser-extension/firefox/manifest.json +1 -1
- package/dist/browser-extension/manifest.json +1 -1
- package/dist/browser-extension/safari/background.js +38 -26
- package/dist/safari/Hanzo AI/Hanzo AI.xcodeproj/project.pbxproj +295 -295
- package/dist/safari/Hanzo AI/Shared (App)/ViewController.swift +1 -1
- package/dist/safari/Hanzo AI/Shared (Extension)/SafariWebExtensionHandler.swift +1 -1
- package/dist/safari/Hanzo AI/iOS (App)/AppDelegate.swift +1 -1
- package/dist/safari/Hanzo AI/iOS (App)/SceneDelegate.swift +1 -1
- package/dist/safari/Hanzo AI/macOS (App)/AppDelegate.swift +1 -1
- package/hanzo-ai-chrome-v1.7.6.zip +0 -0
- package/hanzo-ai-firefox-v1.7.6.zip +0 -0
- package/package.json +1 -1
- package/src/manifest-firefox.json +1 -1
- package/src/manifest.json +1 -1
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
function generateState() {
|
|
28
28
|
return generateRandomString(32);
|
|
29
29
|
}
|
|
30
|
-
var
|
|
30
|
+
var IAM_LOGIN = "https://hanzo.id";
|
|
31
|
+
var IAM_API = "https://iam.hanzo.ai";
|
|
31
32
|
var CLIENT_ID = "app-hanzo";
|
|
32
33
|
var SCOPES = "openid profile email";
|
|
33
34
|
function getRedirectUri() {
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
const { codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
70
71
|
const state = generateState();
|
|
71
72
|
const redirectUri = getRedirectUri();
|
|
72
|
-
const authorizeUrl = new URL(`${
|
|
73
|
+
const authorizeUrl = new URL(`${IAM_LOGIN}/login/oauth/authorize`);
|
|
73
74
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
|
74
75
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
75
76
|
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
@@ -82,28 +83,39 @@
|
|
|
82
83
|
const returnedState = url.searchParams.get("state");
|
|
83
84
|
if (returnedState !== state) throw new Error("State mismatch \u2014 possible CSRF");
|
|
84
85
|
const code = url.searchParams.get("code");
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
const directToken = url.searchParams.get("access_token");
|
|
87
|
+
if (directToken) {
|
|
88
|
+
const tokens = {
|
|
89
|
+
access_token: directToken,
|
|
90
|
+
refresh_token: url.searchParams.get("refresh_token") || void 0,
|
|
91
|
+
token_type: "Bearer"
|
|
92
|
+
};
|
|
93
|
+
await storeTokens(tokens);
|
|
94
|
+
} else if (code) {
|
|
95
|
+
const tokenResponse = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json" },
|
|
98
|
+
body: JSON.stringify({
|
|
99
|
+
grant_type: "authorization_code",
|
|
100
|
+
client_id: CLIENT_ID,
|
|
101
|
+
code,
|
|
102
|
+
redirect_uri: redirectUri,
|
|
103
|
+
code_verifier: codeVerifier
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
if (!tokenResponse.ok) {
|
|
107
|
+
const errText = await tokenResponse.text();
|
|
108
|
+
throw new Error(`Token exchange failed: ${errText}`);
|
|
109
|
+
}
|
|
110
|
+
const tokens = await tokenResponse.json();
|
|
111
|
+
await storeTokens(tokens);
|
|
112
|
+
} else {
|
|
113
|
+
const error = url.searchParams.get("error_description") || url.searchParams.get("error") || "No authorization code or token";
|
|
87
114
|
throw new Error(error);
|
|
88
115
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
body: new URLSearchParams({
|
|
93
|
-
grant_type: "authorization_code",
|
|
94
|
-
client_id: CLIENT_ID,
|
|
95
|
-
code,
|
|
96
|
-
redirect_uri: redirectUri,
|
|
97
|
-
code_verifier: codeVerifier
|
|
98
|
-
})
|
|
99
|
-
});
|
|
100
|
-
if (!tokenResponse.ok) {
|
|
101
|
-
const errText = await tokenResponse.text();
|
|
102
|
-
throw new Error(`Token exchange failed: ${errText}`);
|
|
103
|
-
}
|
|
104
|
-
const tokens = await tokenResponse.json();
|
|
105
|
-
await storeTokens(tokens);
|
|
106
|
-
const user = await fetchUserInfo(tokens.access_token);
|
|
116
|
+
const { accessToken } = await getStoredTokens();
|
|
117
|
+
if (!accessToken) throw new Error("Login succeeded but no token was stored");
|
|
118
|
+
const user = await fetchUserInfo(accessToken);
|
|
107
119
|
await chrome.storage.local.set({ [STORAGE_KEYS.user]: user });
|
|
108
120
|
return user;
|
|
109
121
|
}
|
|
@@ -167,10 +179,10 @@
|
|
|
167
179
|
return accessToken;
|
|
168
180
|
}
|
|
169
181
|
async function refreshAccessToken(refreshToken) {
|
|
170
|
-
const response = await fetch(`${
|
|
182
|
+
const response = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
171
183
|
method: "POST",
|
|
172
|
-
headers: { "Content-Type": "application/
|
|
173
|
-
body:
|
|
184
|
+
headers: { "Content-Type": "application/json" },
|
|
185
|
+
body: JSON.stringify({
|
|
174
186
|
grant_type: "refresh_token",
|
|
175
187
|
client_id: CLIENT_ID,
|
|
176
188
|
refresh_token: refreshToken
|
|
@@ -182,7 +194,7 @@
|
|
|
182
194
|
return tokens.access_token;
|
|
183
195
|
}
|
|
184
196
|
async function fetchUserInfo(accessToken) {
|
|
185
|
-
const response = await fetch(`${
|
|
197
|
+
const response = await fetch(`${IAM_API}/api/userinfo`, {
|
|
186
198
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
187
199
|
});
|
|
188
200
|
if (!response.ok) throw new Error("Failed to fetch user info");
|
|
@@ -1608,7 +1608,8 @@ async function generatePkceChallenge() {
|
|
|
1608
1608
|
function generateState() {
|
|
1609
1609
|
return generateRandomString(32);
|
|
1610
1610
|
}
|
|
1611
|
-
var
|
|
1611
|
+
var IAM_LOGIN = "https://hanzo.id";
|
|
1612
|
+
var IAM_API = "https://iam.hanzo.ai";
|
|
1612
1613
|
var CLIENT_ID = "app-hanzo";
|
|
1613
1614
|
var SCOPES = "openid profile email";
|
|
1614
1615
|
function getRedirectUri() {
|
|
@@ -1650,7 +1651,7 @@ async function login() {
|
|
|
1650
1651
|
const { codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
1651
1652
|
const state = generateState();
|
|
1652
1653
|
const redirectUri = getRedirectUri();
|
|
1653
|
-
const authorizeUrl = new URL(`${
|
|
1654
|
+
const authorizeUrl = new URL(`${IAM_LOGIN}/login/oauth/authorize`);
|
|
1654
1655
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
|
1655
1656
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
1656
1657
|
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
@@ -1663,28 +1664,39 @@ async function login() {
|
|
|
1663
1664
|
const returnedState = url.searchParams.get("state");
|
|
1664
1665
|
if (returnedState !== state) throw new Error("State mismatch \u2014 possible CSRF");
|
|
1665
1666
|
const code = url.searchParams.get("code");
|
|
1666
|
-
|
|
1667
|
-
|
|
1667
|
+
const directToken = url.searchParams.get("access_token");
|
|
1668
|
+
if (directToken) {
|
|
1669
|
+
const tokens = {
|
|
1670
|
+
access_token: directToken,
|
|
1671
|
+
refresh_token: url.searchParams.get("refresh_token") || void 0,
|
|
1672
|
+
token_type: "Bearer"
|
|
1673
|
+
};
|
|
1674
|
+
await storeTokens(tokens);
|
|
1675
|
+
} else if (code) {
|
|
1676
|
+
const tokenResponse = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1677
|
+
method: "POST",
|
|
1678
|
+
headers: { "Content-Type": "application/json" },
|
|
1679
|
+
body: JSON.stringify({
|
|
1680
|
+
grant_type: "authorization_code",
|
|
1681
|
+
client_id: CLIENT_ID,
|
|
1682
|
+
code,
|
|
1683
|
+
redirect_uri: redirectUri,
|
|
1684
|
+
code_verifier: codeVerifier
|
|
1685
|
+
})
|
|
1686
|
+
});
|
|
1687
|
+
if (!tokenResponse.ok) {
|
|
1688
|
+
const errText = await tokenResponse.text();
|
|
1689
|
+
throw new Error(`Token exchange failed: ${errText}`);
|
|
1690
|
+
}
|
|
1691
|
+
const tokens = await tokenResponse.json();
|
|
1692
|
+
await storeTokens(tokens);
|
|
1693
|
+
} else {
|
|
1694
|
+
const error = url.searchParams.get("error_description") || url.searchParams.get("error") || "No authorization code or token";
|
|
1668
1695
|
throw new Error(error);
|
|
1669
1696
|
}
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
body: new URLSearchParams({
|
|
1674
|
-
grant_type: "authorization_code",
|
|
1675
|
-
client_id: CLIENT_ID,
|
|
1676
|
-
code,
|
|
1677
|
-
redirect_uri: redirectUri,
|
|
1678
|
-
code_verifier: codeVerifier
|
|
1679
|
-
})
|
|
1680
|
-
});
|
|
1681
|
-
if (!tokenResponse.ok) {
|
|
1682
|
-
const errText = await tokenResponse.text();
|
|
1683
|
-
throw new Error(`Token exchange failed: ${errText}`);
|
|
1684
|
-
}
|
|
1685
|
-
const tokens = await tokenResponse.json();
|
|
1686
|
-
await storeTokens(tokens);
|
|
1687
|
-
const user = await fetchUserInfo(tokens.access_token);
|
|
1697
|
+
const { accessToken } = await getStoredTokens();
|
|
1698
|
+
if (!accessToken) throw new Error("Login succeeded but no token was stored");
|
|
1699
|
+
const user = await fetchUserInfo(accessToken);
|
|
1688
1700
|
await chrome.storage.local.set({ [STORAGE_KEYS.user]: user });
|
|
1689
1701
|
return user;
|
|
1690
1702
|
}
|
|
@@ -1749,10 +1761,10 @@ async function getValidAccessToken() {
|
|
|
1749
1761
|
return accessToken;
|
|
1750
1762
|
}
|
|
1751
1763
|
async function refreshAccessToken(refreshToken) {
|
|
1752
|
-
const response = await fetch(`${
|
|
1764
|
+
const response = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1753
1765
|
method: "POST",
|
|
1754
|
-
headers: { "Content-Type": "application/
|
|
1755
|
-
body:
|
|
1766
|
+
headers: { "Content-Type": "application/json" },
|
|
1767
|
+
body: JSON.stringify({
|
|
1756
1768
|
grant_type: "refresh_token",
|
|
1757
1769
|
client_id: CLIENT_ID,
|
|
1758
1770
|
refresh_token: refreshToken
|
|
@@ -1764,7 +1776,7 @@ async function refreshAccessToken(refreshToken) {
|
|
|
1764
1776
|
return tokens.access_token;
|
|
1765
1777
|
}
|
|
1766
1778
|
async function fetchUserInfo(accessToken) {
|
|
1767
|
-
const response = await fetch(`${
|
|
1779
|
+
const response = await fetch(`${IAM_API}/api/userinfo`, {
|
|
1768
1780
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
1769
1781
|
});
|
|
1770
1782
|
if (!response.ok) throw new Error("Failed to fetch user info");
|
|
@@ -1608,7 +1608,8 @@ async function generatePkceChallenge() {
|
|
|
1608
1608
|
function generateState() {
|
|
1609
1609
|
return generateRandomString(32);
|
|
1610
1610
|
}
|
|
1611
|
-
var
|
|
1611
|
+
var IAM_LOGIN = "https://hanzo.id";
|
|
1612
|
+
var IAM_API = "https://iam.hanzo.ai";
|
|
1612
1613
|
var CLIENT_ID = "app-hanzo";
|
|
1613
1614
|
var SCOPES = "openid profile email";
|
|
1614
1615
|
function getRedirectUri() {
|
|
@@ -1650,7 +1651,7 @@ async function login() {
|
|
|
1650
1651
|
const { codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
1651
1652
|
const state = generateState();
|
|
1652
1653
|
const redirectUri = getRedirectUri();
|
|
1653
|
-
const authorizeUrl = new URL(`${
|
|
1654
|
+
const authorizeUrl = new URL(`${IAM_LOGIN}/login/oauth/authorize`);
|
|
1654
1655
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
|
1655
1656
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
1656
1657
|
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
@@ -1663,28 +1664,39 @@ async function login() {
|
|
|
1663
1664
|
const returnedState = url.searchParams.get("state");
|
|
1664
1665
|
if (returnedState !== state) throw new Error("State mismatch \u2014 possible CSRF");
|
|
1665
1666
|
const code = url.searchParams.get("code");
|
|
1666
|
-
|
|
1667
|
-
|
|
1667
|
+
const directToken = url.searchParams.get("access_token");
|
|
1668
|
+
if (directToken) {
|
|
1669
|
+
const tokens = {
|
|
1670
|
+
access_token: directToken,
|
|
1671
|
+
refresh_token: url.searchParams.get("refresh_token") || void 0,
|
|
1672
|
+
token_type: "Bearer"
|
|
1673
|
+
};
|
|
1674
|
+
await storeTokens(tokens);
|
|
1675
|
+
} else if (code) {
|
|
1676
|
+
const tokenResponse = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1677
|
+
method: "POST",
|
|
1678
|
+
headers: { "Content-Type": "application/json" },
|
|
1679
|
+
body: JSON.stringify({
|
|
1680
|
+
grant_type: "authorization_code",
|
|
1681
|
+
client_id: CLIENT_ID,
|
|
1682
|
+
code,
|
|
1683
|
+
redirect_uri: redirectUri,
|
|
1684
|
+
code_verifier: codeVerifier
|
|
1685
|
+
})
|
|
1686
|
+
});
|
|
1687
|
+
if (!tokenResponse.ok) {
|
|
1688
|
+
const errText = await tokenResponse.text();
|
|
1689
|
+
throw new Error(`Token exchange failed: ${errText}`);
|
|
1690
|
+
}
|
|
1691
|
+
const tokens = await tokenResponse.json();
|
|
1692
|
+
await storeTokens(tokens);
|
|
1693
|
+
} else {
|
|
1694
|
+
const error = url.searchParams.get("error_description") || url.searchParams.get("error") || "No authorization code or token";
|
|
1668
1695
|
throw new Error(error);
|
|
1669
1696
|
}
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
body: new URLSearchParams({
|
|
1674
|
-
grant_type: "authorization_code",
|
|
1675
|
-
client_id: CLIENT_ID,
|
|
1676
|
-
code,
|
|
1677
|
-
redirect_uri: redirectUri,
|
|
1678
|
-
code_verifier: codeVerifier
|
|
1679
|
-
})
|
|
1680
|
-
});
|
|
1681
|
-
if (!tokenResponse.ok) {
|
|
1682
|
-
const errText = await tokenResponse.text();
|
|
1683
|
-
throw new Error(`Token exchange failed: ${errText}`);
|
|
1684
|
-
}
|
|
1685
|
-
const tokens = await tokenResponse.json();
|
|
1686
|
-
await storeTokens(tokens);
|
|
1687
|
-
const user = await fetchUserInfo(tokens.access_token);
|
|
1697
|
+
const { accessToken } = await getStoredTokens();
|
|
1698
|
+
if (!accessToken) throw new Error("Login succeeded but no token was stored");
|
|
1699
|
+
const user = await fetchUserInfo(accessToken);
|
|
1688
1700
|
await chrome.storage.local.set({ [STORAGE_KEYS.user]: user });
|
|
1689
1701
|
return user;
|
|
1690
1702
|
}
|
|
@@ -1749,10 +1761,10 @@ async function getValidAccessToken() {
|
|
|
1749
1761
|
return accessToken;
|
|
1750
1762
|
}
|
|
1751
1763
|
async function refreshAccessToken(refreshToken) {
|
|
1752
|
-
const response = await fetch(`${
|
|
1764
|
+
const response = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1753
1765
|
method: "POST",
|
|
1754
|
-
headers: { "Content-Type": "application/
|
|
1755
|
-
body:
|
|
1766
|
+
headers: { "Content-Type": "application/json" },
|
|
1767
|
+
body: JSON.stringify({
|
|
1756
1768
|
grant_type: "refresh_token",
|
|
1757
1769
|
client_id: CLIENT_ID,
|
|
1758
1770
|
refresh_token: refreshToken
|
|
@@ -1764,7 +1776,7 @@ async function refreshAccessToken(refreshToken) {
|
|
|
1764
1776
|
return tokens.access_token;
|
|
1765
1777
|
}
|
|
1766
1778
|
async function fetchUserInfo(accessToken) {
|
|
1767
|
-
const response = await fetch(`${
|
|
1779
|
+
const response = await fetch(`${IAM_API}/api/userinfo`, {
|
|
1768
1780
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
1769
1781
|
});
|
|
1770
1782
|
if (!response.ok) throw new Error("Failed to fetch user info");
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
function generateState() {
|
|
28
28
|
return generateRandomString(32);
|
|
29
29
|
}
|
|
30
|
-
var
|
|
30
|
+
var IAM_LOGIN = "https://hanzo.id";
|
|
31
|
+
var IAM_API = "https://iam.hanzo.ai";
|
|
31
32
|
var CLIENT_ID = "app-hanzo";
|
|
32
33
|
var SCOPES = "openid profile email";
|
|
33
34
|
function getRedirectUri() {
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
const { codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
70
71
|
const state = generateState();
|
|
71
72
|
const redirectUri = getRedirectUri();
|
|
72
|
-
const authorizeUrl = new URL(`${
|
|
73
|
+
const authorizeUrl = new URL(`${IAM_LOGIN}/login/oauth/authorize`);
|
|
73
74
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
|
74
75
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
75
76
|
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
@@ -82,28 +83,39 @@
|
|
|
82
83
|
const returnedState = url.searchParams.get("state");
|
|
83
84
|
if (returnedState !== state) throw new Error("State mismatch \u2014 possible CSRF");
|
|
84
85
|
const code = url.searchParams.get("code");
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
const directToken = url.searchParams.get("access_token");
|
|
87
|
+
if (directToken) {
|
|
88
|
+
const tokens = {
|
|
89
|
+
access_token: directToken,
|
|
90
|
+
refresh_token: url.searchParams.get("refresh_token") || void 0,
|
|
91
|
+
token_type: "Bearer"
|
|
92
|
+
};
|
|
93
|
+
await storeTokens(tokens);
|
|
94
|
+
} else if (code) {
|
|
95
|
+
const tokenResponse = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json" },
|
|
98
|
+
body: JSON.stringify({
|
|
99
|
+
grant_type: "authorization_code",
|
|
100
|
+
client_id: CLIENT_ID,
|
|
101
|
+
code,
|
|
102
|
+
redirect_uri: redirectUri,
|
|
103
|
+
code_verifier: codeVerifier
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
if (!tokenResponse.ok) {
|
|
107
|
+
const errText = await tokenResponse.text();
|
|
108
|
+
throw new Error(`Token exchange failed: ${errText}`);
|
|
109
|
+
}
|
|
110
|
+
const tokens = await tokenResponse.json();
|
|
111
|
+
await storeTokens(tokens);
|
|
112
|
+
} else {
|
|
113
|
+
const error = url.searchParams.get("error_description") || url.searchParams.get("error") || "No authorization code or token";
|
|
87
114
|
throw new Error(error);
|
|
88
115
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
body: new URLSearchParams({
|
|
93
|
-
grant_type: "authorization_code",
|
|
94
|
-
client_id: CLIENT_ID,
|
|
95
|
-
code,
|
|
96
|
-
redirect_uri: redirectUri,
|
|
97
|
-
code_verifier: codeVerifier
|
|
98
|
-
})
|
|
99
|
-
});
|
|
100
|
-
if (!tokenResponse.ok) {
|
|
101
|
-
const errText = await tokenResponse.text();
|
|
102
|
-
throw new Error(`Token exchange failed: ${errText}`);
|
|
103
|
-
}
|
|
104
|
-
const tokens = await tokenResponse.json();
|
|
105
|
-
await storeTokens(tokens);
|
|
106
|
-
const user = await fetchUserInfo(tokens.access_token);
|
|
116
|
+
const { accessToken } = await getStoredTokens();
|
|
117
|
+
if (!accessToken) throw new Error("Login succeeded but no token was stored");
|
|
118
|
+
const user = await fetchUserInfo(accessToken);
|
|
107
119
|
await chrome.storage.local.set({ [STORAGE_KEYS.user]: user });
|
|
108
120
|
return user;
|
|
109
121
|
}
|
|
@@ -167,10 +179,10 @@
|
|
|
167
179
|
return accessToken;
|
|
168
180
|
}
|
|
169
181
|
async function refreshAccessToken(refreshToken) {
|
|
170
|
-
const response = await fetch(`${
|
|
182
|
+
const response = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
171
183
|
method: "POST",
|
|
172
|
-
headers: { "Content-Type": "application/
|
|
173
|
-
body:
|
|
184
|
+
headers: { "Content-Type": "application/json" },
|
|
185
|
+
body: JSON.stringify({
|
|
174
186
|
grant_type: "refresh_token",
|
|
175
187
|
client_id: CLIENT_ID,
|
|
176
188
|
refresh_token: refreshToken
|
|
@@ -182,7 +194,7 @@
|
|
|
182
194
|
return tokens.access_token;
|
|
183
195
|
}
|
|
184
196
|
async function fetchUserInfo(accessToken) {
|
|
185
|
-
const response = await fetch(`${
|
|
197
|
+
const response = await fetch(`${IAM_API}/api/userinfo`, {
|
|
186
198
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
187
199
|
});
|
|
188
200
|
if (!response.ok) throw new Error("Failed to fetch user info");
|
|
@@ -1608,7 +1608,8 @@ async function generatePkceChallenge() {
|
|
|
1608
1608
|
function generateState() {
|
|
1609
1609
|
return generateRandomString(32);
|
|
1610
1610
|
}
|
|
1611
|
-
var
|
|
1611
|
+
var IAM_LOGIN = "https://hanzo.id";
|
|
1612
|
+
var IAM_API = "https://iam.hanzo.ai";
|
|
1612
1613
|
var CLIENT_ID = "app-hanzo";
|
|
1613
1614
|
var SCOPES = "openid profile email";
|
|
1614
1615
|
function getRedirectUri() {
|
|
@@ -1650,7 +1651,7 @@ async function login() {
|
|
|
1650
1651
|
const { codeVerifier, codeChallenge } = await generatePkceChallenge();
|
|
1651
1652
|
const state = generateState();
|
|
1652
1653
|
const redirectUri = getRedirectUri();
|
|
1653
|
-
const authorizeUrl = new URL(`${
|
|
1654
|
+
const authorizeUrl = new URL(`${IAM_LOGIN}/login/oauth/authorize`);
|
|
1654
1655
|
authorizeUrl.searchParams.set("client_id", CLIENT_ID);
|
|
1655
1656
|
authorizeUrl.searchParams.set("response_type", "code");
|
|
1656
1657
|
authorizeUrl.searchParams.set("redirect_uri", redirectUri);
|
|
@@ -1663,28 +1664,39 @@ async function login() {
|
|
|
1663
1664
|
const returnedState = url.searchParams.get("state");
|
|
1664
1665
|
if (returnedState !== state) throw new Error("State mismatch \u2014 possible CSRF");
|
|
1665
1666
|
const code = url.searchParams.get("code");
|
|
1666
|
-
|
|
1667
|
-
|
|
1667
|
+
const directToken = url.searchParams.get("access_token");
|
|
1668
|
+
if (directToken) {
|
|
1669
|
+
const tokens = {
|
|
1670
|
+
access_token: directToken,
|
|
1671
|
+
refresh_token: url.searchParams.get("refresh_token") || void 0,
|
|
1672
|
+
token_type: "Bearer"
|
|
1673
|
+
};
|
|
1674
|
+
await storeTokens(tokens);
|
|
1675
|
+
} else if (code) {
|
|
1676
|
+
const tokenResponse = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1677
|
+
method: "POST",
|
|
1678
|
+
headers: { "Content-Type": "application/json" },
|
|
1679
|
+
body: JSON.stringify({
|
|
1680
|
+
grant_type: "authorization_code",
|
|
1681
|
+
client_id: CLIENT_ID,
|
|
1682
|
+
code,
|
|
1683
|
+
redirect_uri: redirectUri,
|
|
1684
|
+
code_verifier: codeVerifier
|
|
1685
|
+
})
|
|
1686
|
+
});
|
|
1687
|
+
if (!tokenResponse.ok) {
|
|
1688
|
+
const errText = await tokenResponse.text();
|
|
1689
|
+
throw new Error(`Token exchange failed: ${errText}`);
|
|
1690
|
+
}
|
|
1691
|
+
const tokens = await tokenResponse.json();
|
|
1692
|
+
await storeTokens(tokens);
|
|
1693
|
+
} else {
|
|
1694
|
+
const error = url.searchParams.get("error_description") || url.searchParams.get("error") || "No authorization code or token";
|
|
1668
1695
|
throw new Error(error);
|
|
1669
1696
|
}
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
body: new URLSearchParams({
|
|
1674
|
-
grant_type: "authorization_code",
|
|
1675
|
-
client_id: CLIENT_ID,
|
|
1676
|
-
code,
|
|
1677
|
-
redirect_uri: redirectUri,
|
|
1678
|
-
code_verifier: codeVerifier
|
|
1679
|
-
})
|
|
1680
|
-
});
|
|
1681
|
-
if (!tokenResponse.ok) {
|
|
1682
|
-
const errText = await tokenResponse.text();
|
|
1683
|
-
throw new Error(`Token exchange failed: ${errText}`);
|
|
1684
|
-
}
|
|
1685
|
-
const tokens = await tokenResponse.json();
|
|
1686
|
-
await storeTokens(tokens);
|
|
1687
|
-
const user = await fetchUserInfo(tokens.access_token);
|
|
1697
|
+
const { accessToken } = await getStoredTokens();
|
|
1698
|
+
if (!accessToken) throw new Error("Login succeeded but no token was stored");
|
|
1699
|
+
const user = await fetchUserInfo(accessToken);
|
|
1688
1700
|
await chrome.storage.local.set({ [STORAGE_KEYS.user]: user });
|
|
1689
1701
|
return user;
|
|
1690
1702
|
}
|
|
@@ -1749,10 +1761,10 @@ async function getValidAccessToken() {
|
|
|
1749
1761
|
return accessToken;
|
|
1750
1762
|
}
|
|
1751
1763
|
async function refreshAccessToken(refreshToken) {
|
|
1752
|
-
const response = await fetch(`${
|
|
1764
|
+
const response = await fetch(`${IAM_API}/api/login/oauth/access_token`, {
|
|
1753
1765
|
method: "POST",
|
|
1754
|
-
headers: { "Content-Type": "application/
|
|
1755
|
-
body:
|
|
1766
|
+
headers: { "Content-Type": "application/json" },
|
|
1767
|
+
body: JSON.stringify({
|
|
1756
1768
|
grant_type: "refresh_token",
|
|
1757
1769
|
client_id: CLIENT_ID,
|
|
1758
1770
|
refresh_token: refreshToken
|
|
@@ -1764,7 +1776,7 @@ async function refreshAccessToken(refreshToken) {
|
|
|
1764
1776
|
return tokens.access_token;
|
|
1765
1777
|
}
|
|
1766
1778
|
async function fetchUserInfo(accessToken) {
|
|
1767
|
-
const response = await fetch(`${
|
|
1779
|
+
const response = await fetch(`${IAM_API}/api/userinfo`, {
|
|
1768
1780
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
1769
1781
|
});
|
|
1770
1782
|
if (!response.ok) throw new Error("Failed to fetch user info");
|