Skip to content

Commit be91898

Browse files
authored
Merge pull request #29 from e2b-dev/improve-auth
Improve auth DX
2 parents 36f3936 + 01fd339 commit be91898

File tree

9 files changed

+63
-49
lines changed

9 files changed

+63
-49
lines changed

.changeset/cute-deer-fall.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@e2b/desktop-python": minor
3+
"@e2b/desktop": minor
4+
---
5+
6+
updates auth dx

README.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,14 @@ desktop = Sandbox()
124124

125125
# Start the stream
126126
desktop.stream.start(
127-
enable_auth=True # Enable authentication with an auto-generated password that will be injected in the stream URL
127+
require_auth=True # Require authentication with an auto-generated key
128128
)
129129

130+
# Retrieve the authentication key
131+
auth_key = desktop.stream.get_auth_key()
132+
130133
# Get stream URL
131-
url = desktop.stream.get_url()
134+
url = desktop.stream.get_url(auth_key=auth_key)
132135
print(url)
133136

134137
# Stop the stream
@@ -144,11 +147,14 @@ const desktop = await Sandbox.create()
144147

145148
// Start the stream
146149
await desktop.stream.start({
147-
enableAuth: true, // Enable authentication with an auto-generated password that will be injected in the stream UR
150+
requireAuth: true, // Require authentication with an auto-generated key
148151
})
149152

153+
// Retrieve the authentication key
154+
const authKey = await desktop.stream.getAuthKey()
155+
150156
// Get stream URL
151-
const url = desktop.stream.getUrl()
157+
const url = desktop.stream.getUrl({ authKey })
152158
console.log(url)
153159

154160
// Stop the stream

examples/basic-javascript/index.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,18 @@ async function main() {
6767
console.log(' - Desktop sandbox screen size:', size)
6868

6969
console.log('\n> Starting desktop stream...')
70-
await desktop.stream.start()
70+
await desktop.stream.start({
71+
requireAuth: true
72+
})
7173

7274
console.log('\n> Waiting 5 seconds for the stream to load...')
7375
for (let i = 5; i > 0; i--) {
7476
console.log(` - ${i} seconds remaining until the next step...`)
7577
await wait(1000)
7678
}
7779

78-
const url = desktop.stream.getUrl()
80+
const authKey = await desktop.stream.getAuthKey()
81+
const url = desktop.stream.getUrl({ authKey })
7982
console.log(' - Stream URL:', url)
8083

8184
console.log('\n> Creating browser window...')

examples/basic-python/main.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ def main():
5151
print(" - Desktop Sandbox screen size:", width, height)
5252

5353
print("\n> Starting desktop stream...")
54-
desktop.stream.start(enable_auth=True)
55-
stream_url = desktop.stream.get_url()
54+
desktop.stream.start(require_auth=True)
55+
auth_key = desktop.stream.get_auth_key()
56+
stream_url = desktop.stream.get_url(auth_key=auth_key)
5657
print(" - Stream URL:", stream_url)
5758

5859
# The webview needs to run on the main thread. That would mean that it would block the program execution.

packages/js-sdk/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,14 @@ const desktop = await Sandbox.create()
7878

7979
// Start the stream
8080
await desktop.stream.start({
81-
enableAuth: true, // Enable authentication with an auto-generated password that will be injected in the stream UR
81+
requireAuth: true, // Enable authentication with an auto-generated key
8282
})
8383

84+
// Retrieve the authentication key
85+
const authKey = await desktop.stream.getAuthKey()
86+
8487
// Get stream URL
85-
const url = desktop.stream.getUrl()
88+
const url = desktop.stream.getUrl({ authKey })
8689
console.log(url)
8790

8891
// Stop the stream

packages/js-sdk/example.mts

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ console.log("Desktop Sandbox started, ID:", desktop.sandboxId)
1515
console.log("Screen size:", await desktop.getScreenSize())
1616

1717
await desktop.stream.start({
18-
enableAuth: true
18+
requireAuth: true
1919
})
2020

21-
console.log("Stream URL:", desktop.stream.getUrl())
21+
const authKey = await desktop.stream.getAuthKey()
22+
console.log("Stream URL:", desktop.stream.getUrl({ authKey }))
2223

2324
await new Promise(resolve => setTimeout(resolve, 5000));
2425

packages/js-sdk/src/sandbox.ts

+16-26
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,6 @@ export interface SandboxOpts extends SandboxOptsBase {
3636
* @type {string}
3737
*/
3838
display?: string
39-
40-
/**
41-
* Port number for the VNC server.
42-
* @type {number}
43-
*/
44-
vncPort?: number
45-
46-
/**
47-
* Port number for the noVNC proxy server.
48-
* @type {number}
49-
*/
50-
port?: number
51-
52-
/**
53-
* Whether to enable authentication for noVNC connections.
54-
* @type {boolean}
55-
*/
56-
enableAuth?: boolean
5739
}
5840

5941

@@ -413,7 +395,7 @@ export class Sandbox extends SandboxBase {
413395
interface VNCServerOptions {
414396
vncPort?: number;
415397
port?: number;
416-
enableAuth?: boolean;
398+
requireAuth?: boolean;
417399
}
418400

419401
// Modified VNCServer class
@@ -424,21 +406,27 @@ class VNCServer {
424406
private url: URL | null = null;
425407
private vncHandle: CommandHandle | null = null;
426408
private novncHandle: CommandHandle | null = null;
427-
private readonly password: string;
409+
private password: string | undefined;
428410
private vncCommand: string = "";
429411
private readonly novncCommand: string;
430412
private readonly desktop: Sandbox;
431413

432414
constructor(desktop: Sandbox) {
433415
this.desktop = desktop;
434-
this.password = generateRandomString();
435-
436416
this.novncCommand = (
437417
`cd /opt/noVNC/utils && ./novnc_proxy --vnc localhost:${this.vncPort} ` +
438418
`--listen ${this.port} --web /opt/noVNC > /tmp/novnc.log 2>&1`
439419
);
440420
}
441421

422+
public getAuthKey(): string {
423+
if (!this.password) {
424+
throw new Error('Unable to retrieve stream auth key, check if requireAuth is enabled');
425+
}
426+
427+
return this.password;
428+
}
429+
442430
/**
443431
* Set the VNC command to start the VNC server.
444432
*/
@@ -465,9 +453,10 @@ class VNCServer {
465453
/**
466454
* Get the URL to connect to the VNC server.
467455
* @param autoConnect - Whether to automatically connect to the server after opening the URL.
456+
* @param authKey - The password to use to connect to the server.
468457
* @returns The URL to connect to the VNC server.
469458
*/
470-
public getUrl(autoConnect: boolean = true): string {
459+
public getUrl({ autoConnect = true, authKey }: { autoConnect?: boolean, authKey?: string } = {}): string {
471460
if (this.url === null) {
472461
throw new Error('Server is not running');
473462
}
@@ -476,8 +465,8 @@ class VNCServer {
476465
if (autoConnect) {
477466
url.searchParams.set('autoconnect', 'true');
478467
}
479-
if (this.novncAuthEnabled) {
480-
url.searchParams.set("password", this.password);
468+
if (authKey) {
469+
url.searchParams.set("password", authKey);
481470
}
482471
return url.toString()
483472
}
@@ -493,7 +482,8 @@ class VNCServer {
493482

494483
this.vncPort = opts.vncPort ?? this.vncPort;
495484
this.port = opts.port ?? this.port;
496-
this.novncAuthEnabled = opts.enableAuth ?? this.novncAuthEnabled;
485+
this.novncAuthEnabled = opts.requireAuth ?? this.novncAuthEnabled;
486+
this.password = this.novncAuthEnabled ? generateRandomString() : undefined;
497487
this.url = new URL(`https://${this.desktop.getHost(this.port)}/vnc.html`);
498488

499489
// Stop both servers in case one of them is running.

packages/python-sdk/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,14 @@ desktop = Sandbox()
7676

7777
# Start the stream
7878
desktop.stream.start(
79-
enable_auth=True # Enable authentication with an auto-generated password that will be injected in the stream URL
79+
require_auth=True # Enable authentication with an auto-generated key
8080
)
8181

82+
# Retrieve the authentication key
83+
auth_key = desktop.stream.get_auth_key()
84+
8285
# Get stream URL
83-
url = desktop.stream.get_url()
86+
url = desktop.stream.get_url(auth_key=auth_key)
8487
print(url)
8588

8689
# Stop the stream

packages/python-sdk/e2b_desktop/main.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@ def __init__(self, desktop: "Sandbox") -> None:
1515
self._vnc_port = 5900
1616
self._port = 6080
1717
self._novnc_auth_enabled = False
18+
self._novnc_password = None
1819

1920
self._url = f"https://{desktop.get_host(self._port)}/vnc.html"
2021

21-
self._novnc_password = self._generate_password()
22-
2322
self.__desktop = desktop
2423

2524
def _wait_for_port(self, port: int) -> bool:
@@ -35,21 +34,22 @@ def _generate_password(length: int = 16) -> str:
3534
characters = string.ascii_letters + string.digits
3635
return ''.join(secrets.choice(characters) for _ in range(length))
3736

38-
def get_url(self, auto_connect: bool = True) -> str:
37+
def get_url(self, auto_connect: bool = True, auth_key: Optional[str] = None) -> str:
3938
params = []
4039
if auto_connect:
4140
params.append("autoconnect=true")
42-
if self._novnc_auth_enabled:
43-
params.append(f"password={self._novnc_password}")
41+
if auth_key:
42+
params.append(f"password={auth_key}")
4443
if params:
4544
return f"{self._url}?{'&'.join(params)}"
4645
return self._url
4746

48-
@property
49-
def password(self) -> str:
47+
def get_auth_key(self) -> str:
48+
if not self._novnc_password:
49+
raise RuntimeError('Unable to retrieve stream auth key, check if require_auth is enabled')
5050
return self._novnc_password
5151

52-
def start(self, vnc_port: Optional[int] = None, port: Optional[int] = None, enable_auth: bool = False) -> None:
52+
def start(self, vnc_port: Optional[int] = None, port: Optional[int] = None, require_auth: bool = False) -> None:
5353
# If both servers are already running, throw an error
5454
if self.__vnc_handle is not None and self.__novnc_handle is not None:
5555
raise RuntimeError('Server is already running')
@@ -60,7 +60,8 @@ def start(self, vnc_port: Optional[int] = None, port: Optional[int] = None, enab
6060
# Update parameters if provided
6161
self._vnc_port = vnc_port or self._vnc_port
6262
self._port = port or self._port
63-
self._novnc_auth_enabled = enable_auth or self._novnc_auth_enabled
63+
self._novnc_auth_enabled = require_auth or self._novnc_auth_enabled
64+
self._novnc_password = self._generate_password() if require_auth else None
6465

6566
# Update URL with new port
6667
self._url = f"https://{self.__desktop.get_host(self._port)}/vnc.html"

0 commit comments

Comments
 (0)