Skip to content

Conversation

@carole-lavillonniere
Copy link
Collaborator

@carole-lavillonniere carole-lavillonniere commented Feb 5, 2026

This PR adds a device code flow as a fallback option when the browser-based authentication doesn't work.

When running lstk start, the CLI now supports two authentication paths:

  1. Browser Flow (primary, introduced here Browser authentication flow #9): Opens browser and listens for callback on localhost:45678
  2. Device Flow (fallback, new in this PR): User presses ENTER to manually complete authentication using a verification code

User Experience

When running lstk:

Browser didn't open? Open https://app.localstack.cloud/auth/request/abc123 to authorize device.
Verification code: XYZ789
Waiting for authentication... (Press ENTER when complete)

If user presses ENTER after confirming in browser:

Checking if auth request is confirmed...
Auth request confirmed, exchanging for token...
Fetching license token...
Login successful!

Mock Server Approach

This PR introduces a platform API client.
The device flow tests use httptest.NewServer to create a real HTTP server that mimics the platform API.
The production code remains unchanged, we just point it to a different URL via LOCALSTACK_PLATFORM_URL.
This allows TestDeviceFlowSuccess to verify the complete end-to-end flow including container startup with a valid token.

if err := listener.Close(); err != nil {
log.Printf("failed to close listener: %v", err)
}
}()
Copy link
Collaborator Author

@carole-lavillonniere carole-lavillonniere Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server.Shutdown() closes the listener, so no explicit close needed

func getWebAppURL() string {
// allows overriding the URL for testing
if url := os.Getenv("LOCALSTACK_WEB_APP_URL"); url != "" {
return url
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why I added this in the first place, but we never overwrite it at the moment, so I removed it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically we could use it to test against staging or locally started webapp.

I wonder though if we should maybe look into handling these envvars with the config package? I'll refactor it slightly later maybe

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Makes sense. Put it back in.
I agree it would be good to have a central place to read env vars and not do it all over the codebase.
I used this in the past https://github.com/caarlos0/env

assert.True(t, inspect.State.Running, "container should be running")
}

func TestStartCommandTriggersLoginWithoutToken(t *testing.T) {
Copy link
Collaborator Author

@carole-lavillonniere carole-lavillonniere Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was just moved to test/integration/login_browser_flow_test.go

@carole-lavillonniere carole-lavillonniere marked this pull request as ready for review February 6, 2026 11:03
Copy link
Member

@silv-io silv-io left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor nits and questions :) But looks nice ✅

func getWebAppURL() string {
// allows overriding the URL for testing
if url := os.Getenv("LOCALSTACK_WEB_APP_URL"); url != "" {
return url
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically we could use it to test against staging or locally started webapp.

I wonder though if we should maybe look into handling these envvars with the config package? I'll refactor it slightly later maybe

Copy link
Member

@silv-io silv-io left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but looks like the build is failing now :)

@carole-lavillonniere carole-lavillonniere merged commit 38a2498 into main Feb 10, 2026
5 of 9 checks passed
@carole-lavillonniere carole-lavillonniere deleted the carole/drg-450 branch February 10, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants