Skip to content

Commit 2a4d097

Browse files
committed
feat: improve authentication flow
- Show a modal before starting the authentication redirect - In rare cases, telemetry wouldn’t track if the authentication process was canceled
1 parent 14698d5 commit 2a4d097

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

src/plugins/setup.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,13 @@ export default createPlugin(
126126
message:
127127
"Waiting for authentication response from the browser...",
128128
});
129-
const { authToken } = await minDelay(
129+
const { authToken, canceled } = await minDelay(
130130
requestAuthentication(context, cancellationToken),
131131
);
132-
if (cancellationToken.isCancellationRequested) {
132+
if (canceled) {
133+
void window.showWarningMessage("Authentication cancelled.");
134+
}
135+
if (canceled || cancellationToken.isCancellationRequested) {
133136
telemetry.track({
134137
name: "auth_token_configured",
135138
payload: {

src/utils/authenticate.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ import { assertIsError } from "./assert.ts";
2222
export async function requestAuthentication(
2323
context: ExtensionContext,
2424
cancellationToken?: CancellationToken,
25-
): Promise<{ authToken: string }> {
25+
): Promise<
26+
| { authToken: string; canceled?: undefined }
27+
| { authToken?: undefined; canceled: true }
28+
> {
2629
return new Promise((resolve, reject) => {
2730
const uriHandler = window.registerUriHandler({
2831
handleUri: (uri: Uri) => {
@@ -34,22 +37,27 @@ export async function requestAuthentication(
3437
if (authToken) {
3538
resolve({ authToken });
3639
} else {
37-
window.showErrorMessage("No token found in URI.");
40+
void window.showErrorMessage("No token found in URI.");
3841
reject(new Error("No token found in URI"));
3942
}
4043
},
4144
});
4245
context.subscriptions.push(uriHandler);
4346
cancellationToken?.onCancellationRequested(() => {
4447
uriHandler.dispose();
45-
reject(new Error("Authentication cancelled"));
48+
resolve({ canceled: true });
4649
});
4750

48-
void redirectToLocalStack();
51+
void redirectToLocalStack().then(({ canceled }) => {
52+
if (canceled) {
53+
uriHandler.dispose();
54+
resolve({ canceled: true });
55+
}
56+
});
4957
});
5058
}
5159

52-
async function redirectToLocalStack() {
60+
async function redirectToLocalStack(): Promise<{ canceled: boolean }> {
5361
// You don't have to get the Uri from the `env.asExternalUri` API but it will add a query
5462
// parameter (ex: "windowId%3D14") that will help VS Code decide which window to redirect to.
5563
// If this query parameter isn't specified, VS Code will pick the last windows that was focused.
@@ -63,13 +71,17 @@ async function redirectToLocalStack() {
6371
const url = new URL(process.env.LOCALSTACK_WEB_AUTH_REDIRECT!);
6472
url.searchParams.set("windowId", redirectSearchParams.get("windowId") ?? "");
6573

66-
const openSuccessful = await env.openExternal(Uri.parse(url.toString()));
67-
68-
if (!openSuccessful) {
69-
window.showErrorMessage(
70-
`Open LocalStack sign-in URL in browser by entering the URL manually: ${url.toString()}`,
71-
);
74+
const selection = await window.showInformationMessage(
75+
`LocalStack needs to open the browser to continue with the authentication process.`,
76+
{ modal: true },
77+
"Continue",
78+
);
79+
if (!selection) {
80+
return { canceled: true };
7281
}
82+
83+
const openSuccessful = await env.openExternal(Uri.parse(url.toString()));
84+
return { canceled: !openSuccessful };
7385
}
7486

7587
const LOCALSTACK_AUTH_FILENAME = `${os.homedir()}/.localstack/auth.json`;

0 commit comments

Comments
 (0)