usertold 1.9.2 → 1.9.3
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/package.json +1 -1
- package/usertold +87 -66
package/package.json
CHANGED
package/usertold
CHANGED
|
@@ -728,79 +728,98 @@ function generateState() {
|
|
|
728
728
|
function base64UrlEncode(buffer) {
|
|
729
729
|
return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
730
730
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
res.writeHead(400, {
|
|
756
|
-
'Content-Type': 'text/html'
|
|
757
|
-
});
|
|
758
|
-
res.end(getErrorPage(error, errorDescription || undefined));
|
|
759
|
-
clearTimeout(timeout);
|
|
760
|
-
server.close();
|
|
761
|
-
reject(new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ''}`));
|
|
762
|
-
return;
|
|
763
|
-
}
|
|
764
|
-
if (!code) {
|
|
765
|
-
res.writeHead(400, {
|
|
766
|
-
'Content-Type': 'text/html'
|
|
767
|
-
});
|
|
768
|
-
res.end(getErrorPage('invalid_request', 'Missing authorization code'));
|
|
769
|
-
clearTimeout(timeout);
|
|
770
|
-
server.close();
|
|
771
|
-
reject(new Error('Missing authorization code'));
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
if (state !== expectedState) {
|
|
775
|
-
res.writeHead(400, {
|
|
776
|
-
'Content-Type': 'text/html'
|
|
777
|
-
});
|
|
778
|
-
res.end(getErrorPage('invalid_request', 'State parameter mismatch - possible CSRF attack'));
|
|
779
|
-
clearTimeout(timeout);
|
|
780
|
-
server.close();
|
|
781
|
-
reject(new Error('State mismatch'));
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
res.writeHead(200, {
|
|
731
|
+
function startAuthorizationCodeListener(port, expectedState) {
|
|
732
|
+
const server = http.createServer((req, res)=>{
|
|
733
|
+
if (!req.url) {
|
|
734
|
+
res.writeHead(400, {
|
|
735
|
+
'Content-Type': 'text/html'
|
|
736
|
+
});
|
|
737
|
+
res.end(getErrorPage('invalid_request', 'Invalid request'));
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
const url = new URL(req.url, `http://127.0.0.1:${port}`);
|
|
741
|
+
if (url.pathname !== '/callback') {
|
|
742
|
+
res.writeHead(404, {
|
|
743
|
+
'Content-Type': 'text/html'
|
|
744
|
+
});
|
|
745
|
+
res.end(getErrorPage('not_found', 'Page not found'));
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
const code = url.searchParams.get('code');
|
|
749
|
+
const state = url.searchParams.get('state');
|
|
750
|
+
const error = url.searchParams.get('error');
|
|
751
|
+
const errorDescription = url.searchParams.get('error_description');
|
|
752
|
+
// Handle OAuth error response
|
|
753
|
+
if (error) {
|
|
754
|
+
res.writeHead(400, {
|
|
785
755
|
'Content-Type': 'text/html'
|
|
786
756
|
});
|
|
787
|
-
res.end(
|
|
757
|
+
res.end(getErrorPage(error, errorDescription || undefined));
|
|
788
758
|
clearTimeout(timeout);
|
|
789
759
|
server.close();
|
|
790
|
-
|
|
791
|
-
|
|
760
|
+
rejectResult(new Error(`OAuth error: ${error}${errorDescription ? ` - ${errorDescription}` : ''}`));
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
if (!code) {
|
|
764
|
+
res.writeHead(400, {
|
|
765
|
+
'Content-Type': 'text/html'
|
|
792
766
|
});
|
|
767
|
+
res.end(getErrorPage('invalid_request', 'Missing authorization code'));
|
|
768
|
+
clearTimeout(timeout);
|
|
769
|
+
server.close();
|
|
770
|
+
rejectResult(new Error('Missing authorization code'));
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
if (state !== expectedState) {
|
|
774
|
+
res.writeHead(400, {
|
|
775
|
+
'Content-Type': 'text/html'
|
|
776
|
+
});
|
|
777
|
+
res.end(getErrorPage('invalid_request', 'State parameter mismatch - possible CSRF attack'));
|
|
778
|
+
clearTimeout(timeout);
|
|
779
|
+
server.close();
|
|
780
|
+
rejectResult(new Error('State mismatch'));
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
res.writeHead(200, {
|
|
784
|
+
'Content-Type': 'text/html'
|
|
785
|
+
});
|
|
786
|
+
res.end(getSuccessPage());
|
|
787
|
+
clearTimeout(timeout);
|
|
788
|
+
server.close();
|
|
789
|
+
resolveResult({
|
|
790
|
+
code
|
|
793
791
|
});
|
|
794
|
-
|
|
795
|
-
|
|
792
|
+
});
|
|
793
|
+
let rejectResult = ()=>{};
|
|
794
|
+
let resolveResult = ()=>{};
|
|
795
|
+
const result = new Promise((resolve, reject)=>{
|
|
796
|
+
resolveResult = resolve;
|
|
797
|
+
rejectResult = reject;
|
|
798
|
+
});
|
|
799
|
+
const ready = new Promise((resolve, reject)=>{
|
|
800
|
+
const handleStartupError = (error)=>{
|
|
796
801
|
clearTimeout(timeout);
|
|
802
|
+
rejectResult(new Error(`Failed to start local callback server: ${error.message}`));
|
|
797
803
|
reject(new Error(`Failed to start local callback server: ${error.message}`));
|
|
804
|
+
};
|
|
805
|
+
server.once('error', handleStartupError);
|
|
806
|
+
server.listen(port, '127.0.0.1', ()=>{
|
|
807
|
+
server.off('error', handleStartupError);
|
|
808
|
+
server.on('error', (error)=>{
|
|
809
|
+
clearTimeout(timeout);
|
|
810
|
+
rejectResult(new Error(`Local callback server error: ${error.message}`));
|
|
811
|
+
});
|
|
812
|
+
resolve();
|
|
798
813
|
});
|
|
799
|
-
const timeout = setTimeout(()=>{
|
|
800
|
-
server.close();
|
|
801
|
-
reject(new Error('Login timed out waiting for authorization response'));
|
|
802
|
-
}, 5 * 60 * 1000);
|
|
803
814
|
});
|
|
815
|
+
const timeout = setTimeout(()=>{
|
|
816
|
+
server.close();
|
|
817
|
+
rejectResult(new Error('Login timed out waiting for authorization response'));
|
|
818
|
+
}, 5 * 60 * 1000);
|
|
819
|
+
return {
|
|
820
|
+
ready,
|
|
821
|
+
result
|
|
822
|
+
};
|
|
804
823
|
}
|
|
805
824
|
// =============================================================================
|
|
806
825
|
// CLI Auth Page Design Tokens
|
|
@@ -1052,6 +1071,8 @@ async function handleLogin(parsed) {
|
|
|
1052
1071
|
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
1053
1072
|
authUrl.searchParams.set('state', state);
|
|
1054
1073
|
authUrl.searchParams.set('access_type', 'offline');
|
|
1074
|
+
const authorizationCodeListener = startAuthorizationCodeListener(redirectPort, state);
|
|
1075
|
+
await authorizationCodeListener.ready;
|
|
1055
1076
|
// Always print the URL so it works on headless/remote hosts
|
|
1056
1077
|
console.log('\nOpen this URL in your browser to authenticate:\n');
|
|
1057
1078
|
console.log(authUrl.toString());
|
|
@@ -1068,7 +1089,7 @@ async function handleLogin(parsed) {
|
|
|
1068
1089
|
console.log('(Could not open browser — use the URL above)');
|
|
1069
1090
|
}
|
|
1070
1091
|
}
|
|
1071
|
-
const { code } = await
|
|
1092
|
+
const { code } = await authorizationCodeListener.result;
|
|
1072
1093
|
console.log('Received authorization code. Exchanging for access token...');
|
|
1073
1094
|
const tokenResponse = await exchangeCodeForToken({
|
|
1074
1095
|
baseUrl,
|
|
@@ -14713,7 +14734,7 @@ function printExtractHelp() {
|
|
|
14713
14734
|
console.log(EXTRACT_HELP);
|
|
14714
14735
|
}
|
|
14715
14736
|
|
|
14716
|
-
const CLI_VERSION$1 = '1.9.
|
|
14737
|
+
const CLI_VERSION$1 = '1.9.3';
|
|
14717
14738
|
const GLOBAL_FLAGS = [
|
|
14718
14739
|
'env',
|
|
14719
14740
|
'json',
|
|
@@ -15009,7 +15030,7 @@ function printCompletionsHelp() {
|
|
|
15009
15030
|
console.log(COMPLETIONS_HELP);
|
|
15010
15031
|
}
|
|
15011
15032
|
|
|
15012
|
-
const CLI_VERSION = '1.9.
|
|
15033
|
+
const CLI_VERSION = '1.9.3';
|
|
15013
15034
|
function detectJsonMode() {
|
|
15014
15035
|
const argv = process$2.argv.slice(2);
|
|
15015
15036
|
if (argv.includes('--json')) return true;
|