diff --git a/satellite/console/consoleweb/consoleapi/auth.go b/satellite/console/consoleweb/consoleapi/auth.go index d18b52112289..b584d524794a 100644 --- a/satellite/console/consoleweb/consoleapi/auth.go +++ b/satellite/console/consoleweb/consoleapi/auth.go @@ -495,7 +495,7 @@ func (a *Auth) ActivateAccount(w http.ResponseWriter, r *http.Request) { return } - tokenInfo, err := a.service.GenerateSessionToken(ctx, user.ID, user.Email, ip, r.UserAgent()) + tokenInfo, err := a.service.GenerateSessionToken(ctx, user.ID, user.Email, ip, r.UserAgent(), nil) if err != nil { a.serveJSONError(ctx, w, err) return diff --git a/satellite/console/consoleweb/consoleapi/auth_test.go b/satellite/console/consoleweb/consoleapi/auth_test.go index 5c313a766098..69f00838fe72 100644 --- a/satellite/console/consoleweb/consoleapi/auth_test.go +++ b/satellite/console/consoleweb/consoleapi/auth_test.go @@ -47,7 +47,7 @@ func doRequestWithAuth( ) (responseBody []byte, statusCode int, err error) { fullURL := "http://" + sat.API.Console.Listener.Addr().String() + "/api/v0/" + endpoint - tokenInfo, err := sat.API.Console.Service.GenerateSessionToken(ctx, user.ID, user.Email, "", "") + tokenInfo, err := sat.API.Console.Service.GenerateSessionToken(ctx, user.ID, user.Email, "", "", nil) if err != nil { return nil, 0, err } diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 4cc8c00f77fb..3265bcaac03a 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -894,7 +894,7 @@ func (server *Server) accountActivationHandler(w http.ResponseWriter, r *http.Re return } - tokenInfo, err := server.service.GenerateSessionToken(ctx, user.ID, user.Email, ip, r.UserAgent()) + tokenInfo, err := server.service.GenerateSessionToken(ctx, user.ID, user.Email, ip, r.UserAgent(), nil) if err != nil { server.serveError(w, http.StatusInternalServerError) return diff --git a/satellite/console/service.go b/satellite/console/service.go index 7a5fa98373db..0ef33f4dd198 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -956,7 +956,7 @@ func (s *Service) GeneratePasswordRecoveryToken(ctx context.Context, id uuid.UUI } // GenerateSessionToken creates a new session and returns the string representation of its token. -func (s *Service) GenerateSessionToken(ctx context.Context, userID uuid.UUID, email, ip, userAgent string) (_ *TokenInfo, err error) { +func (s *Service) GenerateSessionToken(ctx context.Context, userID uuid.UUID, email, ip, userAgent string, customDuration *time.Duration) (_ *TokenInfo, err error) { defer mon.Task()(&ctx)(&err) sessionID, err := uuid.New() @@ -965,7 +965,9 @@ func (s *Service) GenerateSessionToken(ctx context.Context, userID uuid.UUID, em } duration := s.config.Session.Duration - if s.config.Session.InactivityTimerEnabled { + if customDuration != nil { + duration = *customDuration + } else if s.config.Session.InactivityTimerEnabled { settings, err := s.store.Users().GetSettings(ctx, userID) if err != nil && !errs.Is(err, sql.ErrNoRows) { return nil, Error.Wrap(err) @@ -1360,7 +1362,12 @@ func (s *Service) Token(ctx context.Context, request AuthUser) (response *TokenI } } - response, err = s.GenerateSessionToken(ctx, user.ID, user.Email, request.IP, request.UserAgent) + var customDurationPtr *time.Duration + if request.RememberForOneWeek { + weekDuration := 7 * 24 * time.Hour + customDurationPtr = &weekDuration + } + response, err = s.GenerateSessionToken(ctx, user.ID, user.Email, request.IP, request.UserAgent, customDurationPtr) if err != nil { return nil, err } @@ -1384,7 +1391,7 @@ func (s *Service) TokenByAPIKey(ctx context.Context, userAgent string, ip string return nil, Error.New(failedToRetrieveUserErrMsg) } - response, err = s.GenerateSessionToken(ctx, user.ID, user.Email, ip, userAgent) + response, err = s.GenerateSessionToken(ctx, user.ID, user.Email, ip, userAgent, nil) if err != nil { return nil, Error.New(generateSessionTokenErrMsg) } diff --git a/satellite/console/service_test.go b/satellite/console/service_test.go index 850a9a387466..e470a9d15ec9 100644 --- a/satellite/console/service_test.go +++ b/satellite/console/service_test.go @@ -1215,7 +1215,7 @@ func TestGenerateSessionToken(t *testing.T) { require.NoError(t, err) now := time.Now() - token1, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "") + token1, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "", nil) require.NoError(t, err) require.NotNil(t, token1) @@ -1228,7 +1228,7 @@ func TestGenerateSessionToken(t *testing.T) { })) now = time.Now() - token2, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "") + token2, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "", nil) require.NoError(t, err) token2Duration := token2.ExpiresAt.Sub(now) require.Greater(t, token2Duration, token1Duration) @@ -1241,10 +1241,17 @@ func TestGenerateSessionToken(t *testing.T) { })) now = time.Now() - token3, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "") + token3, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "", nil) require.NoError(t, err) token3Duration := token3.ExpiresAt.Sub(now) require.Less(t, token3Duration, token1Duration) + + now = time.Now() + customDuration := 7 * 24 * time.Hour + inAWeek := now.Add(customDuration) + token4, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "", &customDuration) + require.NoError(t, err) + require.True(t, token4.ExpiresAt.After(inAWeek)) }) } @@ -1268,7 +1275,7 @@ func TestRefreshSessionToken(t *testing.T) { require.NoError(t, err) now := time.Now() - token, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "") + token, err := srv.GenerateSessionToken(userCtx, user.ID, user.Email, "", "", nil) require.NoError(t, err) require.NotNil(t, token) diff --git a/satellite/console/users.go b/satellite/console/users.go index b5b449743e9d..7199cf8c5d35 100644 --- a/satellite/console/users.go +++ b/satellite/console/users.go @@ -149,13 +149,14 @@ type ProjectLimits struct { // AuthUser holds info for user authentication token requests. type AuthUser struct { - Email string `json:"email"` - Password string `json:"password"` - MFAPasscode string `json:"mfaPasscode"` - MFARecoveryCode string `json:"mfaRecoveryCode"` - CaptchaResponse string `json:"captchaResponse"` - IP string `json:"-"` - UserAgent string `json:"-"` + Email string `json:"email"` + Password string `json:"password"` + MFAPasscode string `json:"mfaPasscode"` + MFARecoveryCode string `json:"mfaRecoveryCode"` + CaptchaResponse string `json:"captchaResponse"` + RememberForOneWeek bool `json:"rememberForOneWeek"` + IP string `json:"-"` + UserAgent string `json:"-"` } // TokenInfo holds info for user authentication token responses. diff --git a/satellite/oidc/integration_test.go b/satellite/oidc/integration_test.go index 51b0a6e2021e..4855c2104f94 100644 --- a/satellite/oidc/integration_test.go +++ b/satellite/oidc/integration_test.go @@ -124,7 +124,7 @@ func TestOIDC(t *testing.T) { user, err = sat.API.Console.Service.ActivateAccount(ctx, activationToken) require.NoError(t, err) - tokenInfo, err := sat.API.Console.Service.GenerateSessionToken(ctx, user.ID, user.Email, "", "") + tokenInfo, err := sat.API.Console.Service.GenerateSessionToken(ctx, user.ID, user.Email, "", "", nil) require.NoError(t, err) // Set up a test project and bucket