From 64883ea97d72d4db243f163d496e250a30ea4c23 Mon Sep 17 00:00:00 2001 From: Jorge Turrado Date: Fri, 28 Nov 2025 16:19:07 +0100 Subject: [PATCH 1/3] feat: max_age is set during auth request to limit user session Signed-off-by: Jorge Turrado --- .../config/profile/import/template/profile.json | 2 +- internal/pkg/auth/auth.go | 14 +++++++++++--- internal/pkg/auth/user_login.go | 7 ++++++- internal/pkg/config/config.go | 2 +- internal/pkg/config/template/test_profile.json | 2 +- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/internal/cmd/config/profile/import/template/profile.json b/internal/cmd/config/profile/import/template/profile.json index ab56ce66b..dbc0bad02 100644 --- a/internal/cmd/config/profile/import/template/profile.json +++ b/internal/cmd/config/profile/import/template/profile.json @@ -25,7 +25,7 @@ "serverbackup_custom_endpoint": "", "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", - "session_time_limit": "2h", + "session_time_limit": "12h", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", diff --git a/internal/pkg/auth/auth.go b/internal/pkg/auth/auth.go index ea549a2cb..dd56536d3 100644 --- a/internal/pkg/auth/auth.go +++ b/internal/pkg/auth/auth.go @@ -110,15 +110,23 @@ func GetAccessToken() (string, error) { func getStartingSessionExpiresAtUnix() (string, error) { sessionStart := time.Now() - sessionTimeLimitString := viper.GetString(config.SessionTimeLimitKey) - sessionTimeLimit, err := time.ParseDuration(sessionTimeLimitString) + sessionTimeLimit, err := getSessionExpiration() if err != nil { - return "", fmt.Errorf("parse session time limit \"%s\": %w", sessionTimeLimitString, err) + return "", err } sessionExpiresAt := sessionStart.Add(sessionTimeLimit) return strconv.FormatInt(sessionExpiresAt.Unix(), 10), nil } +func getSessionExpiration() (time.Duration, error) { + sessionTimeLimitString := viper.GetString(config.SessionTimeLimitKey) + duration, err := time.ParseDuration(sessionTimeLimitString) + if err != nil { + return 0, fmt.Errorf("parse session time limit \"%s\": %w", sessionTimeLimitString, err) + } + return duration, nil +} + func getEmailFromToken(token string) (string, error) { // We can safely use ParseUnverified because we are not authenticating the user at this point, // We are parsing the token just to get the service account e-mail diff --git a/internal/pkg/auth/user_login.go b/internal/pkg/auth/user_login.go index 8ac94743e..0921aa5a4 100644 --- a/internal/pkg/auth/user_login.go +++ b/internal/pkg/auth/user_login.go @@ -121,8 +121,13 @@ func AuthorizeUser(p *print.Printer, isReauthentication bool) error { // Initialize the code verifier codeVerifier := oauth2.GenerateVerifier() + // Generate max age based on the session time limit + maxSessionDuration, err := getSessionExpiration() + if err != nil { + return err + } // Construct the authorization URL - authorizationURL := conf.AuthCodeURL("", oauth2.S256ChallengeOption(codeVerifier)) + authorizationURL := conf.AuthCodeURL("", oauth2.S256ChallengeOption(codeVerifier), oauth2.SetAuthURLParam("max_age", fmt.Sprintf("%d", int64(maxSessionDuration.Seconds())))) // Start a web server to listen on a callback URL mux := http.NewServeMux() diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 957d7c475..d21d1ceec 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -52,7 +52,7 @@ const ( AsyncDefault = false RegionDefault = "eu01" - SessionTimeLimitDefault = "2h" + SessionTimeLimitDefault = "12h" AllowedUrlDomainDefault = "stackit.cloud" ) diff --git a/internal/pkg/config/template/test_profile.json b/internal/pkg/config/template/test_profile.json index ab56ce66b..dbc0bad02 100644 --- a/internal/pkg/config/template/test_profile.json +++ b/internal/pkg/config/template/test_profile.json @@ -25,7 +25,7 @@ "serverbackup_custom_endpoint": "", "service_account_custom_endpoint": "", "service_enablement_custom_endpoint": "", - "session_time_limit": "2h", + "session_time_limit": "12h", "ske_custom_endpoint": "", "sqlserverflex_custom_endpoint": "", "token_custom_endpoint": "", From 802368112857d4ad23e5808cf39a74562dc9954f Mon Sep 17 00:00:00 2001 From: Jorge Turrado Date: Fri, 28 Nov 2025 16:48:54 +0100 Subject: [PATCH 2/3] update docs Signed-off-by: Jorge Turrado --- docs/stackit_config_unset.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/stackit_config_unset.md b/docs/stackit_config_unset.md index 4a48b759e..77a2deaac 100644 --- a/docs/stackit_config_unset.md +++ b/docs/stackit_config_unset.md @@ -54,7 +54,7 @@ stackit config unset [flags] --serverbackup-custom-endpoint Server Backup base URL. If unset, uses the default base URL --service-account-custom-endpoint Service Account API base URL. If unset, uses the default base URL --service-enablement-custom-endpoint Service Enablement API base URL. If unset, uses the default base URL - --session-time-limit Maximum time before authentication is required again. If unset, defaults to 2h + --session-time-limit Maximum time before authentication is required again. If unset, defaults to 12h --ske-custom-endpoint SKE API base URL. If unset, uses the default base URL --sqlserverflex-custom-endpoint SQLServer Flex API base URL. If unset, uses the default base URL --token-custom-endpoint Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. From 9c3251a56e5f402d4d8fbd7b89a0f575dc83a7a8 Mon Sep 17 00:00:00 2001 From: Jorge Turrado Date: Mon, 15 Dec 2025 14:13:40 +0100 Subject: [PATCH 3/3] feedback Signed-off-by: Jorge Turrado --- docs/stackit_config_set.md | 2 +- internal/cmd/config/set/set.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/stackit_config_set.md b/docs/stackit_config_set.md index b1abf5662..11ab5587d 100644 --- a/docs/stackit_config_set.md +++ b/docs/stackit_config_set.md @@ -53,7 +53,7 @@ stackit config set [flags] --serverbackup-custom-endpoint string Server Backup API base URL, used in calls to this API --service-account-custom-endpoint string Service Account API base URL, used in calls to this API --service-enablement-custom-endpoint string Service Enablement API base URL, used in calls to this API - --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect) + --session-time-limit string Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s --ske-custom-endpoint string SKE API base URL, used in calls to this API --sqlserverflex-custom-endpoint string SQLServer Flex API base URL, used in calls to this API --token-custom-endpoint string Custom token endpoint of the Service Account API, which is used to request access tokens when the service account authentication is activated. Not relevant for user authentication. diff --git a/internal/cmd/config/set/set.go b/internal/cmd/config/set/set.go index 841f8e66e..3197aca3a 100644 --- a/internal/cmd/config/set/set.go +++ b/internal/cmd/config/set/set.go @@ -132,7 +132,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e } func configureFlags(cmd *cobra.Command) { - cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s (BETA: currently values greater than 2h have no effect)") + cmd.Flags().String(sessionTimeLimitFlag, "", "Maximum time before authentication is required again. After this time, you will be prompted to login again to execute commands that require authentication. Can't be larger than 24h. Requires authentication after being set to take effect. Examples: 3h, 5h30m40s") cmd.Flags().String(identityProviderCustomWellKnownConfigurationFlag, "", "Identity Provider well-known OpenID configuration URL, used for user authentication") cmd.Flags().String(identityProviderCustomClientIdFlag, "", "Identity Provider client ID, used for user authentication") cmd.Flags().String(allowedUrlDomainFlag, "", `Domain name, used for the verification of the URLs that are given in the custom identity provider endpoint and "STACKIT curl" command`)