From 428f5645f34ac2713279291afc4ccfae0b56a28a Mon Sep 17 00:00:00 2001 From: niri81 <38499069+niri81@users.noreply.github.com> Date: Thu, 10 Sep 2026 20:39:14 +0200 Subject: [PATCH] feat(auth): add no browser open flag to login Add an additional option to only print the authorization URL and not open it directly in the standard browser. Especially useful if another browser or an incognito tab need to be used. --- docs/stackit_auth_login.md | 7 ++++--- internal/cmd/auth/login/login.go | 15 ++++++++++++--- internal/pkg/auth/user_login.go | 29 ++++++++++++++++++++--------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/docs/stackit_auth_login.md b/docs/stackit_auth_login.md index 232c2cbe3..306900b11 100644 --- a/docs/stackit_auth_login.md +++ b/docs/stackit_auth_login.md @@ -21,9 +21,10 @@ stackit auth login [flags] ### Options ``` - -h, --help Help for "stackit auth login" - --port int The port on which the callback server will listen to. By default, it tries to bind a port between 8000 and 8020. - When a value is specified, it will only try to use the specified port. Valid values are within the range of 8000 to 8020. + -h, --help Help for "stackit auth login" + --no-browser-open If set, does not open the browser automatically but only prints the URL to the terminal + --port int The port on which the callback server will listen to. By default, it tries to bind a port between 8000 and 8020. + When a value is specified, it will only try to use the specified port. Valid values are within the range of 8000 to 8020. ``` ### Options inherited from parent commands diff --git a/internal/cmd/auth/login/login.go b/internal/cmd/auth/login/login.go index 8a03d19af..2eb3655e5 100644 --- a/internal/cmd/auth/login/login.go +++ b/internal/cmd/auth/login/login.go @@ -14,11 +14,13 @@ import ( ) const ( - portFlag = "port" + portFlag = "port" + noBrowserOpenFlag = "no-browser-open" ) type inputModel struct { - Port *int + Port *int + NoBrowserOpen bool } func NewCmd(params *types.CmdParams) *cobra.Command { @@ -43,6 +45,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { err = auth.AuthorizeUser(params.Printer, auth.UserAuthConfig{ IsReauthentication: false, Port: model.Port, + NoBrowserOpen: model.NoBrowserOpen, }) if err != nil { return fmt.Errorf("authorization failed: %w", err) @@ -62,6 +65,9 @@ func configureFlags(cmd *cobra.Command) { "The port on which the callback server will listen to. By default, it tries to bind a port between 8000 and 8020.\n"+ "When a value is specified, it will only try to use the specified port. Valid values are within the range of 8000 to 8020.", ) + cmd.Flags().Bool(noBrowserOpenFlag, false, + "If set, does not open the browser automatically but only prints the URL to the terminal", + ) } func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, error) { @@ -71,8 +77,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, return nil, fmt.Errorf("port must be between 8000 and 8020") } + noBrowserOpen := flags.FlagToBoolValue(p, cmd, noBrowserOpenFlag) + model := inputModel{ - Port: port, + Port: port, + NoBrowserOpen: noBrowserOpen, } p.DebugInputModel(model) diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 5ad94d0a6..2adc2add5 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -51,6 +51,8 @@ type UserAuthConfig struct { IsReauthentication bool // Port defines which port should be used for the UserAuthFlow callback Port *int + // NoBrowserOpen stops the browser from opening automatically during the login flow + NoBrowserOpen bool } type apiClient interface { @@ -250,19 +252,28 @@ func AuthorizeUser(p *print.Printer, authConfig UserAuthConfig) error { } }) - p.Debug(print.DebugLevel, "opening browser for authentication: %s", authorizationURL) p.Debug(print.DebugLevel, "using authentication server on %s", idpWellKnownConfig.Issuer) p.Debug(print.DebugLevel, "using client ID %s for authentication ", idpClientID) - // Open a browser window to the authorizationURL - err = openBrowser(authorizationURL) - if err != nil { - return fmt.Errorf("open browser to URL %s: %w", authorizationURL, err) - } + if authConfig.NoBrowserOpen { + p.Debug(print.DebugLevel, "skipping browser opening since the commandline flag was passed") - // Print the link - p.Info("Your browser has been opened to visit:\n\n") - p.Info("%s\n\n", authorizationURL) + // Print the link in terminal + p.Info("Open the following URL in your browser:\n\n") + p.Info("%s\n\n", authorizationURL) + } else { + p.Debug(print.DebugLevel, "opening browser for authentication: %s", authorizationURL) + + // Open a browser window to the authorizationURL + err = openBrowser(authorizationURL) + if err != nil { + return fmt.Errorf("open browser to URL %s: %w", authorizationURL, err) + } + + // Print the link + p.Info("Your browser has been opened to visit:\n\n") + p.Info("%s\n\n", authorizationURL) + } // Start the blocking web server loop // It will exit when the handlers get fired and call server.Close()