If you are reading this article, you know what a URI handler in Visual Studio Code is, but in case you do not. A URI Handler allows you to create a callback into your extension. Typically this is used in authentication flows to open your browser, fill in your credentials, and get redirected back into Visual Studio Code. Your URI Handler will then process the rest of the authentication process, like requesting an access token.
While working on a custom authentication provider, I found it needed to be fixed for GitHub Codespaces and Gitpod. The URI Handler, configured in my Visual Studio Code extension, never got triggered when invoked from within a Codespace. On the desktop, it works fine, so this got me to understand better how it works.
First, I investigated the differences between the desktop and codespaces URI handler flows.
A good starting point was the callbacks and URI handlers for codespaces documentation from Visual Studio Code. The documentation explains that you should use the
vscode.env.asExternalUri method to generate the redirect URL.
You need to use the
vscode.env.asExternalUri method, because it will convert the URL to the right environment.
For the desktop, your URL should look as follows:
vscode://<publisher>.<extension name>. If you are using the insiders version of Visual Studio Code, it will be
If you use the
asExternalUri method in your extension running on a codespace, its URL will be linked to your remote URL of GitHub Codespaces or Gitpod.
For the example, I use the following code:
This code generates me the following results:
- Codespace URL:
- External URI:
extension-auth-callback path and
state query string parameter. Both are required for the URI Handler to handle the callback.
info In my auth provider, the state got overwritten by my state ID, which is why the URI handler was not triggered.
On Gitpod, these URLs are different, but the functionality is the same.
- Gitpod URL:
- External URI:
To ensure the URI handler can get triggered, ensure these query string parameters you retrieve from the asExternalUri method are kept unchanged.
The code for the URI handler is pretty simple. It look as follows:
info In the documentation, they use a
uri.path === '/auth-complete'statement, this is only required if you want to be aware the handler is triggered on a codespace.