github.com/kiali/kiali@v1.84.0/business/authentication/session_persistor_test.go (about)

     1  package authentication
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"github.com/kiali/kiali/config"
    15  	"github.com/kiali/kiali/util"
    16  )
    17  
    18  type testSessionPayload struct {
    19  	FirstField string `json:"firstField,omitempty"`
    20  }
    21  
    22  // TestSecureFlag tests that the cookie Secure flag is set to true when using HTTPS.
    23  func TestSecureFlag(t *testing.T) {
    24  	cfg := config.NewConfig()
    25  	cfg.Server.WebRoot = "/kiali-app"
    26  	cfg.LoginToken.SigningKey = "kiali67890123456"
    27  	cfg.Identity.CertFile = "foo.cert"      // setting conf.Identity will make it look as if the endpoint ...
    28  	cfg.Identity.PrivateKeyFile = "foo.key" // ... is HTTPS - this causes the cookies' Secure flag to be true
    29  	config.Set(cfg)
    30  
    31  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
    32  	util.Clock = util.ClockMock{Time: clockTime}
    33  
    34  	payload := testSessionPayload{
    35  		FirstField: "Foo",
    36  	}
    37  
    38  	rr := httptest.NewRecorder()
    39  	persistor := NewCookieSessionPersistor(cfg)
    40  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
    41  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
    42  
    43  	response := rr.Result()
    44  
    45  	assert.Nil(t, err)
    46  	assert.Len(t, response.Cookies(), 1)
    47  
    48  	cookie := response.Cookies()[0]
    49  	assert.True(t, cookie.HttpOnly)
    50  	assert.True(t, cfg.IsServerHTTPS())
    51  	assert.True(t, cookie.Secure)
    52  }
    53  
    54  // TestCreateSessionNoChunks tests that the CookieSessionPersistor correctly
    55  // sets one cookie if the payload of a session fits in one browser cookie
    56  func TestCreateSessionNoChunks(t *testing.T) {
    57  	cfg := config.NewConfig()
    58  	cfg.Server.WebRoot = "/kiali-app"
    59  	cfg.LoginToken.SigningKey = "kiali67890123456"
    60  	config.Set(cfg)
    61  
    62  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
    63  	util.Clock = util.ClockMock{Time: clockTime}
    64  
    65  	payload := testSessionPayload{
    66  		FirstField: "Foo",
    67  	}
    68  
    69  	rr := httptest.NewRecorder()
    70  	persistor := NewCookieSessionPersistor(cfg)
    71  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
    72  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
    73  
    74  	response := rr.Result()
    75  
    76  	assert.Nil(t, err)
    77  	assert.Len(t, response.Cookies(), 1)
    78  
    79  	cookie := response.Cookies()[0]
    80  	assert.True(t, cookie.HttpOnly)
    81  	assert.False(t, cfg.IsServerHTTPS())
    82  	assert.False(t, cookie.Secure)
    83  	assert.Equal(t, AESSessionCookieName, cookie.Name)
    84  	assert.Equal(t, "/kiali-app", cookie.Path)
    85  	assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite)
    86  	assert.Equal(t, expiresTime, cookie.Expires)
    87  
    88  	// Unfortunately, the internals of the CreateSession is using a "nonce" to encrypt data.
    89  	// This means that the output is not predictable. The only thing is possible to test here
    90  	// is to check that the returned cookie won't have a plain text payload on it (which is the "Foo" text).
    91  	decodedB64Cookie, err := base64.StdEncoding.DecodeString(response.Cookies()[0].Value)
    92  	assert.Nil(t, err)
    93  	payloadJson, err1 := json.Marshal(payload)
    94  	assert.Nil(t, err1)
    95  	// sometimes (randomly) the result of "nonce" encrypted data can contain the plain text, so avoiding "NotContains" direct assertion here and checking the JSON
    96  	assert.NotEqual(t, cookie.Value, "Foo")
    97  	assert.NotEqual(t, string(decodedB64Cookie), "Foo")
    98  	assert.NotContains(t, string(decodedB64Cookie), string(payloadJson))
    99  	assert.NotContains(t, cookie.Value, string(payloadJson))
   100  }
   101  
   102  // TestCreateSessionWithChunks tests that the CookieSessionPersistor correctly
   103  // sets the needed browser cookies if the payload does not fit in one browser cookie.
   104  func TestCreateSessionWithChunks(t *testing.T) {
   105  	cfg := config.NewConfig()
   106  	cfg.Server.WebRoot = "/kiali-app"
   107  	cfg.LoginToken.SigningKey = "kiali67890123456"
   108  	config.Set(cfg)
   109  
   110  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   111  	util.Clock = util.ClockMock{Time: clockTime}
   112  
   113  	// Create a long enough payload to overflow our maximum size of a cookie.
   114  	payload := testSessionPayload{
   115  		FirstField: strings.Repeat("1234567890", SessionCookieMaxSize/len("1234567890")),
   116  	}
   117  
   118  	rr := httptest.NewRecorder()
   119  	persistor := NewCookieSessionPersistor(cfg)
   120  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   121  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   122  
   123  	response := rr.Result()
   124  
   125  	assert.Nil(t, err)
   126  	assert.Len(t, response.Cookies(), 3)
   127  	assert.Equal(t, AESSessionCookieName, response.Cookies()[0].Name)
   128  	assert.Equal(t, config.TokenCookieName+"-aes-1", response.Cookies()[1].Name)
   129  	assert.Equal(t, config.TokenCookieName+"-chunks", response.Cookies()[2].Name)
   130  	assert.Equal(t, "2", response.Cookies()[2].Value)
   131  
   132  	for _, cookie := range response.Cookies() {
   133  		assert.True(t, cookie.HttpOnly)
   134  		assert.False(t, cookie.Secure)
   135  		assert.Equal(t, "/kiali-app", cookie.Path)
   136  		assert.Equal(t, http.SameSiteStrictMode, cookie.SameSite)
   137  		assert.Equal(t, expiresTime, cookie.Expires)
   138  	}
   139  }
   140  
   141  // TestCreateSessionRejectsNilPayload tests that the CookieSessionPersistor rejects
   142  // creating a session if a nil payload is passed.
   143  func TestCreateSessionRejectsNilPayload(t *testing.T) {
   144  	rr := httptest.NewRecorder()
   145  	persistor := NewCookieSessionPersistor(config.NewConfig())
   146  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   147  	err := persistor.CreateSession(nil, rr, "test", expiresTime, nil)
   148  
   149  	response := rr.Result()
   150  
   151  	assert.NotNil(t, err)
   152  	assert.Len(t, response.Cookies(), 0)
   153  }
   154  
   155  // TestCreateSessionRejectsEmptyStrategy tests that the CookieSessionPersistor rejects
   156  // creating a session if an empty strategy is passed.
   157  func TestCreateSessionRejectsEmptyStrategy(t *testing.T) {
   158  	payload := testSessionPayload{
   159  		FirstField: "1234567890",
   160  	}
   161  
   162  	rr := httptest.NewRecorder()
   163  	persistor := NewCookieSessionPersistor(config.NewConfig())
   164  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   165  	err := persistor.CreateSession(nil, rr, "", expiresTime, payload)
   166  
   167  	response := rr.Result()
   168  
   169  	assert.NotNil(t, err)
   170  	assert.Len(t, response.Cookies(), 0)
   171  }
   172  
   173  // TestCreateSessionRejectsExpireTimeInThePast tests that the CookieSessionPersistor rejects
   174  // creating a session if the indicated expiration time is already in the past.
   175  func TestCreateSessionRejectsExpireTimeInThePast(t *testing.T) {
   176  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 1, time.UTC)
   177  	util.Clock = util.ClockMock{Time: clockTime}
   178  
   179  	payload := testSessionPayload{
   180  		FirstField: "1234567890",
   181  	}
   182  
   183  	rr := httptest.NewRecorder()
   184  	persistor := NewCookieSessionPersistor(config.NewConfig())
   185  	expiresTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   186  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   187  
   188  	response := rr.Result()
   189  
   190  	assert.NotNil(t, err)
   191  	assert.Len(t, response.Cookies(), 0)
   192  }
   193  
   194  // TestReadSessionWithNoActiveSession tests that the CookieSessionPersistor does not emit
   195  // an error when restoring a session if the HTTP request contains no active session.
   196  func TestReadSessionWithNoActiveSession(t *testing.T) {
   197  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   198  
   199  	var payload testSessionPayload
   200  	rr := httptest.NewRecorder()
   201  	persistor := NewCookieSessionPersistor(config.NewConfig())
   202  	sData, err := persistor.ReadSession(request, rr, payload)
   203  
   204  	assert.Nil(t, sData)
   205  	assert.Nil(t, err)
   206  }
   207  
   208  // TestReadSessionWithSingleCookie tests that the CookieSessionPersistor correctly
   209  // restores a session that fit in a single browser cookie.
   210  func TestReadSessionWithSingleCookie(t *testing.T) {
   211  	cfg := config.NewConfig()
   212  	cfg.Auth.Strategy = "test"
   213  	cfg.LoginToken.SigningKey = "kiali67890123456"
   214  	config.Set(cfg)
   215  
   216  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   217  	util.Clock = util.ClockMock{Time: clockTime}
   218  
   219  	payload := testSessionPayload{
   220  		FirstField: "FooBar",
   221  	}
   222  
   223  	rr := httptest.NewRecorder()
   224  	persistor := NewCookieSessionPersistor(cfg)
   225  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   226  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   227  	assert.Nil(t, err)
   228  
   229  	response := rr.Result()
   230  
   231  	// Create a request containing the cookies of the response
   232  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   233  	assert.Len(t, response.Cookies(), 1)
   234  	for _, c := range response.Cookies() {
   235  		request.AddCookie(c)
   236  	}
   237  
   238  	// Read/restore the session.
   239  	rr = httptest.NewRecorder()
   240  	restoredPayload := testSessionPayload{}
   241  	sData, err := persistor.ReadSession(request, rr, &restoredPayload)
   242  
   243  	assert.Nil(t, err)
   244  	assert.NotNil(t, sData)
   245  	assert.Equal(t, expiresTime, sData.ExpiresOn)
   246  	assert.Equal(t, "test", sData.Strategy)
   247  	assert.Equal(t, "FooBar", restoredPayload.FirstField)
   248  }
   249  
   250  // TestReadSessionWithTwoCookies tests that the CookieSessionPersistor correctly
   251  // restores a session that didn't fit in a single browser cookie.
   252  func TestReadSessionWithTwoCookies(t *testing.T) {
   253  	cfg := config.NewConfig()
   254  	cfg.Auth.Strategy = "test"
   255  	cfg.LoginToken.SigningKey = "kiali67890123456"
   256  	config.Set(cfg)
   257  
   258  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   259  	util.Clock = util.ClockMock{Time: clockTime}
   260  
   261  	payloadStr := strings.Repeat("FooBar", SessionCookieMaxSize/len("FooBar"))
   262  	payload := testSessionPayload{
   263  		FirstField: payloadStr,
   264  	}
   265  
   266  	rr := httptest.NewRecorder()
   267  	persistor := NewCookieSessionPersistor(cfg)
   268  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   269  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   270  	assert.Nil(t, err)
   271  
   272  	response := rr.Result()
   273  
   274  	// Create a request containing the cookies of the response
   275  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   276  	assert.Len(t, response.Cookies(), 3)
   277  	for _, c := range response.Cookies() {
   278  		request.AddCookie(c)
   279  	}
   280  
   281  	// Read/restore the session.
   282  	rr = httptest.NewRecorder()
   283  	restoredPayload := testSessionPayload{}
   284  	sData, err := persistor.ReadSession(request, rr, &restoredPayload)
   285  
   286  	assert.Nil(t, err)
   287  	assert.NotNil(t, sData)
   288  	assert.Equal(t, expiresTime, sData.ExpiresOn)
   289  	assert.Equal(t, "test", sData.Strategy)
   290  	assert.Equal(t, payloadStr, restoredPayload.FirstField)
   291  }
   292  
   293  // TestReadSessionRejectsExpired tests that the CookieSessionPersistor does
   294  // not restore a session that is already expired.
   295  func TestReadSessionRejectsExpired(t *testing.T) {
   296  	cfg := config.NewConfig()
   297  	cfg.Auth.Strategy = "test"
   298  	cfg.LoginToken.SigningKey = "kiali67890123456"
   299  	config.Set(cfg)
   300  
   301  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   302  	util.Clock = util.ClockMock{Time: clockTime}
   303  
   304  	payload := testSessionPayload{
   305  		FirstField: "FooBar",
   306  	}
   307  
   308  	rr := httptest.NewRecorder()
   309  	persistor := NewCookieSessionPersistor(cfg)
   310  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   311  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   312  	assert.Nil(t, err)
   313  
   314  	response := rr.Result()
   315  
   316  	// Create a request containing the cookies of the response
   317  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   318  	for _, c := range response.Cookies() {
   319  		request.AddCookie(c)
   320  	}
   321  
   322  	// Go to the future
   323  	util.Clock = util.ClockMock{Time: expiresTime}
   324  
   325  	// Read/restore the session.
   326  	rr = httptest.NewRecorder()
   327  	restoredPayload := testSessionPayload{}
   328  	sData, err := persistor.ReadSession(request, rr, &restoredPayload)
   329  
   330  	assert.Nil(t, err)
   331  	assert.Nil(t, sData)
   332  	assert.Empty(t, restoredPayload.FirstField)
   333  }
   334  
   335  // TestReadSessionRejectsDifferentStrategy tests that the CookieSessionPersistor does
   336  // not restore a session that was created with a strategy different from the currently configured one.
   337  func TestReadSessionRejectsDifferentStrategy(t *testing.T) {
   338  	cfg := config.NewConfig()
   339  	cfg.LoginToken.SigningKey = "kiali67890123456"
   340  	config.Set(cfg)
   341  
   342  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   343  	util.Clock = util.ClockMock{Time: clockTime}
   344  
   345  	payload := testSessionPayload{
   346  		FirstField: "FooBar",
   347  	}
   348  
   349  	rr := httptest.NewRecorder()
   350  	persistor := NewCookieSessionPersistor(cfg)
   351  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   352  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   353  	assert.Nil(t, err)
   354  
   355  	response := rr.Result()
   356  
   357  	// Create a request containing the cookies of the response
   358  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   359  	for _, c := range response.Cookies() {
   360  		request.AddCookie(c)
   361  	}
   362  
   363  	// Read/restore the session.
   364  	rr = httptest.NewRecorder()
   365  	restoredPayload := testSessionPayload{}
   366  	sData, err := persistor.ReadSession(request, rr, &restoredPayload)
   367  
   368  	assert.Nil(t, err)
   369  	assert.Nil(t, sData)
   370  	assert.Empty(t, restoredPayload.FirstField)
   371  }
   372  
   373  // TestReadSessionRejectsDifferentSigningKey tests that the CookieSessionPersistor does
   374  // not restore a session that was created with an old Kiali signing key
   375  func TestReadSessionRejectsDifferentSigningKey(t *testing.T) {
   376  	cfg := config.NewConfig()
   377  	cfg.Auth.Strategy = "test"
   378  	cfg.LoginToken.SigningKey = "kiali67890123456"
   379  	config.Set(cfg)
   380  
   381  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   382  	util.Clock = util.ClockMock{Time: clockTime}
   383  
   384  	payload := testSessionPayload{
   385  		FirstField: "FooBar",
   386  	}
   387  
   388  	rr := httptest.NewRecorder()
   389  	persistor := NewCookieSessionPersistor(cfg)
   390  	expiresTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   391  	err := persistor.CreateSession(nil, rr, "test", expiresTime, payload)
   392  	assert.Nil(t, err)
   393  
   394  	response := rr.Result()
   395  
   396  	// Create a request containing the cookies of the response
   397  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   398  	for _, c := range response.Cookies() {
   399  		request.AddCookie(c)
   400  	}
   401  
   402  	// Set a new signing key
   403  	cfg.LoginToken.SigningKey = "kiali-----------"
   404  	config.Set(cfg)
   405  
   406  	// Read/restore the session.
   407  	rr = httptest.NewRecorder()
   408  	restoredPayload := testSessionPayload{}
   409  	sData, err := persistor.ReadSession(request, rr, &restoredPayload)
   410  
   411  	assert.NotNil(t, err) // When the signing key does not match, an error is generated.
   412  	assert.Nil(t, sData)
   413  	assert.Empty(t, restoredPayload.FirstField)
   414  }
   415  
   416  // TestTerminateSessionClearsNonAesSession tests that the CookieSessionPersistor correctly clears
   417  // a session that was created with the old JWT method.
   418  func TestTerminateSessionClearsNonAesSession(t *testing.T) {
   419  	c := config.NewConfig()
   420  	c.Server.WebRoot = "/kiali-app"
   421  	config.Set(c)
   422  
   423  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   424  	util.Clock = util.ClockMock{Time: clockTime}
   425  
   426  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   427  	cookie := http.Cookie{
   428  		Name:    config.TokenCookieName,
   429  		Value:   "",
   430  		Expires: time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC),
   431  	}
   432  	request.AddCookie(&cookie)
   433  
   434  	persistor := NewCookieSessionPersistor(c)
   435  
   436  	rr := httptest.NewRecorder()
   437  	persistor.TerminateSession(request, rr)
   438  
   439  	response := rr.Result()
   440  	assert.Len(t, response.Cookies(), 1)
   441  	assert.Equal(t, config.TokenCookieName, response.Cookies()[0].Name)
   442  	assert.Empty(t, response.Cookies()[0].Value)
   443  	assert.True(t, response.Cookies()[0].Expires.Before(util.Clock.Now()))
   444  	assert.Equal(t, "/kiali-app", response.Cookies()[0].Path)
   445  }
   446  
   447  // TestTerminateSessionClearsAesSession tests that the CookieSessionPersistor correctly clears
   448  // a session that is using encrypted cookies with the AES-GCM algorithm where no "-chunks" cookie is set.
   449  func TestTerminateSessionClearsAesSession(t *testing.T) {
   450  	c := config.NewConfig()
   451  	c.Server.WebRoot = "/kiali-app"
   452  	config.Set(c)
   453  
   454  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   455  	util.Clock = util.ClockMock{Time: clockTime}
   456  
   457  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   458  	cookie := http.Cookie{
   459  		Name:    AESSessionCookieName,
   460  		Value:   "",
   461  		Expires: time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC),
   462  	}
   463  	request.AddCookie(&cookie)
   464  
   465  	persistor := NewCookieSessionPersistor(c)
   466  
   467  	rr := httptest.NewRecorder()
   468  	persistor.TerminateSession(request, rr)
   469  
   470  	response := rr.Result()
   471  	assert.Len(t, response.Cookies(), 1)
   472  	assert.Equal(t, AESSessionCookieName, response.Cookies()[0].Name)
   473  	assert.Empty(t, response.Cookies()[0].Value)
   474  	assert.True(t, response.Cookies()[0].Expires.Before(util.Clock.Now()))
   475  	assert.Equal(t, "/kiali-app", response.Cookies()[0].Path)
   476  }
   477  
   478  // TestTerminateSessionClearsAesSessionWithOneChunk tests that the CookieSessionPersistor correctly
   479  // clears a session where the payload fit in a single browser cookie, yet the "-chunks" cookie is set.
   480  func TestTerminateSessionClearsAesSessionWithOneChunk(t *testing.T) {
   481  	c := config.NewConfig()
   482  	c.Server.WebRoot = "/kiali-app"
   483  	config.Set(c)
   484  
   485  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   486  	util.Clock = util.ClockMock{Time: clockTime}
   487  
   488  	expireTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   489  
   490  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   491  	cookie := http.Cookie{
   492  		Name:    AESSessionCookieName,
   493  		Value:   "",
   494  		Expires: expireTime,
   495  	}
   496  	request.AddCookie(&cookie)
   497  	cookie = http.Cookie{
   498  		Name:    config.TokenCookieName + "-chunks",
   499  		Value:   "1",
   500  		Expires: expireTime,
   501  	}
   502  	request.AddCookie(&cookie)
   503  
   504  	persistor := NewCookieSessionPersistor(c)
   505  
   506  	rr := httptest.NewRecorder()
   507  	persistor.TerminateSession(request, rr)
   508  
   509  	response := rr.Result()
   510  	assert.Len(t, response.Cookies(), 2)
   511  	assert.Equal(t, AESSessionCookieName, response.Cookies()[0].Name)
   512  	assert.Equal(t, config.TokenCookieName+"-chunks", response.Cookies()[1].Name)
   513  
   514  	for i := 0; i < 2; i++ {
   515  		assert.True(t, response.Cookies()[i].Expires.Before(util.Clock.Now()))
   516  		assert.Equal(t, "/kiali-app", response.Cookies()[i].Path)
   517  		assert.Empty(t, response.Cookies()[i].Value)
   518  	}
   519  }
   520  
   521  // TestTerminateSessionClearsAesSessionWithTwoChunks tests that the CookieSessionPersistor correctly
   522  // clears a session where the payload didn't fit in a single browser cookie.
   523  func TestTerminateSessionClearsAesSessionWithTwoChunks(t *testing.T) {
   524  	c := config.NewConfig()
   525  	c.Server.WebRoot = "/kiali-app"
   526  	config.Set(c)
   527  
   528  	clockTime := time.Date(2021, 12, 1, 0, 0, 0, 0, time.UTC)
   529  	util.Clock = util.ClockMock{Time: clockTime}
   530  
   531  	expireTime := time.Date(2021, 12, 1, 1, 0, 0, 0, time.UTC)
   532  
   533  	request := httptest.NewRequest(http.MethodGet, "/api/logout", nil)
   534  	cookie := http.Cookie{
   535  		Name:    AESSessionCookieName,
   536  		Value:   "",
   537  		Expires: expireTime,
   538  	}
   539  	request.AddCookie(&cookie)
   540  	cookie = http.Cookie{
   541  		Name:    config.TokenCookieName + "-chunks",
   542  		Value:   "2",
   543  		Expires: expireTime,
   544  	}
   545  	request.AddCookie(&cookie)
   546  	cookie = http.Cookie{
   547  		Name:    config.TokenCookieName + "-aes-1",
   548  		Value:   "x",
   549  		Expires: expireTime,
   550  	}
   551  	request.AddCookie(&cookie)
   552  
   553  	persistor := NewCookieSessionPersistor(c)
   554  
   555  	rr := httptest.NewRecorder()
   556  	persistor.TerminateSession(request, rr)
   557  
   558  	response := rr.Result()
   559  	assert.Len(t, response.Cookies(), 3)
   560  	assert.Equal(t, config.TokenCookieName+"-aes-1", response.Cookies()[0].Name)
   561  	assert.Equal(t, AESSessionCookieName, response.Cookies()[1].Name)
   562  	assert.Equal(t, config.TokenCookieName+"-chunks", response.Cookies()[2].Name)
   563  
   564  	for i := 0; i < 3; i++ {
   565  		assert.True(t, response.Cookies()[i].Expires.Before(util.Clock.Now()))
   566  		assert.Equal(t, "/kiali-app", response.Cookies()[i].Path)
   567  		assert.Empty(t, response.Cookies()[i].Value)
   568  	}
   569  }