2019-05-05 14:33:13 +02:00
|
|
|
package sessions_test
|
2015-06-23 13:23:39 +02:00
|
|
|
|
|
|
|
import (
|
2017-09-26 23:31:27 +02:00
|
|
|
"fmt"
|
2015-06-23 13:23:39 +02:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2020-03-29 15:54:36 +02:00
|
|
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
|
|
|
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
|
2017-10-23 18:23:46 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
2015-06-23 13:23:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const secret = "0123456789abcdefghijklmnopqrstuv"
|
|
|
|
const altSecret = "0000000000abcdefghijklmnopqrstuv"
|
|
|
|
|
2020-05-30 09:53:38 +02:00
|
|
|
func timePtr(t time.Time) *time.Time {
|
|
|
|
return &t
|
|
|
|
}
|
|
|
|
|
2015-06-23 13:23:39 +02:00
|
|
|
func TestSessionStateSerialization(t *testing.T) {
|
2019-05-24 18:06:48 +02:00
|
|
|
c, err := encryption.NewCipher([]byte(secret))
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, nil, err)
|
2019-05-24 18:06:48 +02:00
|
|
|
c2, err := encryption.NewCipher([]byte(altSecret))
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, nil, err)
|
2019-05-05 14:33:13 +02:00
|
|
|
s := &sessions.SessionState{
|
2020-03-01 17:02:51 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
PreferredUsername: "user",
|
|
|
|
AccessToken: "token1234",
|
|
|
|
IDToken: "rawtoken1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: timePtr(time.Now()),
|
|
|
|
ExpiresOn: timePtr(time.Now().Add(time.Duration(1) * time.Hour)),
|
2020-03-01 17:02:51 +02:00
|
|
|
RefreshToken: "refresh4321",
|
2015-06-23 13:23:39 +02:00
|
|
|
}
|
|
|
|
encoded, err := s.EncodeSessionState(c)
|
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err := sessions.DecodeSessionState(encoded, c)
|
2015-06-23 13:23:39 +02:00
|
|
|
t.Logf("%#v", ss)
|
|
|
|
assert.Equal(t, nil, err)
|
2020-05-12 17:04:51 +02:00
|
|
|
assert.Equal(t, "", ss.User)
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, s.Email, ss.Email)
|
2020-03-01 17:02:51 +02:00
|
|
|
assert.Equal(t, s.PreferredUsername, ss.PreferredUsername)
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, s.AccessToken, ss.AccessToken)
|
2018-01-27 12:53:17 +02:00
|
|
|
assert.Equal(t, s.IDToken, ss.IDToken)
|
2019-05-07 16:32:46 +02:00
|
|
|
assert.Equal(t, s.CreatedAt.Unix(), ss.CreatedAt.Unix())
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, s.ExpiresOn.Unix(), ss.ExpiresOn.Unix())
|
|
|
|
assert.Equal(t, s.RefreshToken, ss.RefreshToken)
|
|
|
|
|
|
|
|
// ensure a different cipher can't decode properly (ie: it gets gibberish)
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err = sessions.DecodeSessionState(encoded, c2)
|
2015-06-23 13:23:39 +02:00
|
|
|
t.Logf("%#v", ss)
|
2020-06-02 21:53:33 +02:00
|
|
|
assert.NotEqual(t, nil, err)
|
2015-06-23 13:23:39 +02:00
|
|
|
}
|
|
|
|
|
2017-09-26 23:31:27 +02:00
|
|
|
func TestSessionStateSerializationWithUser(t *testing.T) {
|
2019-05-24 18:06:48 +02:00
|
|
|
c, err := encryption.NewCipher([]byte(secret))
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, nil, err)
|
2019-05-24 18:06:48 +02:00
|
|
|
c2, err := encryption.NewCipher([]byte(altSecret))
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, nil, err)
|
2019-05-05 14:33:13 +02:00
|
|
|
s := &sessions.SessionState{
|
2020-03-01 17:02:51 +02:00
|
|
|
User: "just-user",
|
|
|
|
PreferredUsername: "ju",
|
|
|
|
Email: "user@domain.com",
|
|
|
|
AccessToken: "token1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: timePtr(time.Now()),
|
|
|
|
ExpiresOn: timePtr(time.Now().Add(time.Duration(1) * time.Hour)),
|
2020-03-01 17:02:51 +02:00
|
|
|
RefreshToken: "refresh4321",
|
2017-09-26 23:31:27 +02:00
|
|
|
}
|
|
|
|
encoded, err := s.EncodeSessionState(c)
|
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err := sessions.DecodeSessionState(encoded, c)
|
2017-09-26 23:31:27 +02:00
|
|
|
t.Logf("%#v", ss)
|
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
assert.Equal(t, s.User, ss.User)
|
|
|
|
assert.Equal(t, s.Email, ss.Email)
|
2020-03-01 17:02:51 +02:00
|
|
|
assert.Equal(t, s.PreferredUsername, ss.PreferredUsername)
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, s.AccessToken, ss.AccessToken)
|
2019-05-07 16:32:46 +02:00
|
|
|
assert.Equal(t, s.CreatedAt.Unix(), ss.CreatedAt.Unix())
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, s.ExpiresOn.Unix(), ss.ExpiresOn.Unix())
|
|
|
|
assert.Equal(t, s.RefreshToken, ss.RefreshToken)
|
|
|
|
|
|
|
|
// ensure a different cipher can't decode properly (ie: it gets gibberish)
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err = sessions.DecodeSessionState(encoded, c2)
|
2017-09-26 23:31:27 +02:00
|
|
|
t.Logf("%#v", ss)
|
2020-06-02 21:53:33 +02:00
|
|
|
assert.NotEqual(t, nil, err)
|
2017-09-26 23:31:27 +02:00
|
|
|
}
|
2015-06-23 13:23:39 +02:00
|
|
|
|
2017-09-26 23:31:27 +02:00
|
|
|
func TestSessionStateSerializationNoCipher(t *testing.T) {
|
2019-05-05 14:33:13 +02:00
|
|
|
s := &sessions.SessionState{
|
2020-03-01 17:02:51 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
PreferredUsername: "user",
|
|
|
|
AccessToken: "token1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: timePtr(time.Now()),
|
|
|
|
ExpiresOn: timePtr(time.Now().Add(time.Duration(1) * time.Hour)),
|
2020-03-01 17:02:51 +02:00
|
|
|
RefreshToken: "refresh4321",
|
2015-06-23 13:23:39 +02:00
|
|
|
}
|
|
|
|
encoded, err := s.EncodeSessionState(nil)
|
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
|
|
|
|
// only email should have been serialized
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err := sessions.DecodeSessionState(encoded, nil)
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, nil, err)
|
2020-05-12 17:04:51 +02:00
|
|
|
assert.Equal(t, "", ss.User)
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, s.Email, ss.Email)
|
2020-03-01 17:02:51 +02:00
|
|
|
assert.Equal(t, s.PreferredUsername, ss.PreferredUsername)
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, "", ss.AccessToken)
|
|
|
|
assert.Equal(t, "", ss.RefreshToken)
|
|
|
|
}
|
|
|
|
|
2017-09-26 23:31:27 +02:00
|
|
|
func TestSessionStateSerializationNoCipherWithUser(t *testing.T) {
|
2019-05-05 14:33:13 +02:00
|
|
|
s := &sessions.SessionState{
|
2020-03-01 17:02:51 +02:00
|
|
|
User: "just-user",
|
|
|
|
Email: "user@domain.com",
|
|
|
|
PreferredUsername: "user",
|
|
|
|
AccessToken: "token1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: timePtr(time.Now()),
|
|
|
|
ExpiresOn: timePtr(time.Now().Add(time.Duration(1) * time.Hour)),
|
2020-03-01 17:02:51 +02:00
|
|
|
RefreshToken: "refresh4321",
|
2017-09-26 23:31:27 +02:00
|
|
|
}
|
|
|
|
encoded, err := s.EncodeSessionState(nil)
|
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
|
|
|
|
// only email should have been serialized
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err := sessions.DecodeSessionState(encoded, nil)
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, nil, err)
|
|
|
|
assert.Equal(t, s.User, ss.User)
|
|
|
|
assert.Equal(t, s.Email, ss.Email)
|
2020-03-01 17:02:51 +02:00
|
|
|
assert.Equal(t, s.PreferredUsername, ss.PreferredUsername)
|
2017-09-26 23:31:27 +02:00
|
|
|
assert.Equal(t, "", ss.AccessToken)
|
|
|
|
assert.Equal(t, "", ss.RefreshToken)
|
|
|
|
}
|
2015-06-23 13:23:39 +02:00
|
|
|
|
|
|
|
func TestExpired(t *testing.T) {
|
2020-05-30 09:53:38 +02:00
|
|
|
s := &sessions.SessionState{ExpiresOn: timePtr(time.Now().Add(time.Duration(-1) * time.Minute))}
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, true, s.IsExpired())
|
|
|
|
|
2020-05-30 09:53:38 +02:00
|
|
|
s = &sessions.SessionState{ExpiresOn: timePtr(time.Now().Add(time.Duration(1) * time.Minute))}
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, false, s.IsExpired())
|
|
|
|
|
2019-05-05 14:33:13 +02:00
|
|
|
s = &sessions.SessionState{}
|
2015-06-23 13:23:39 +02:00
|
|
|
assert.Equal(t, false, s.IsExpired())
|
|
|
|
}
|
2019-03-20 15:59:24 +02:00
|
|
|
|
|
|
|
type testCase struct {
|
2019-05-05 14:33:13 +02:00
|
|
|
sessions.SessionState
|
2019-03-20 15:59:24 +02:00
|
|
|
Encoded string
|
2020-05-10 02:01:51 +02:00
|
|
|
Cipher encryption.Cipher
|
2019-03-20 15:59:24 +02:00
|
|
|
Error bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestEncodeSessionState tests EncodeSessionState with the test vector
|
|
|
|
//
|
|
|
|
// Currently only tests without cipher here because we have no way to mock
|
|
|
|
// the random generator used in EncodeSessionState.
|
|
|
|
func TestEncodeSessionState(t *testing.T) {
|
2019-05-07 16:32:46 +02:00
|
|
|
c := time.Now()
|
2019-03-20 15:59:24 +02:00
|
|
|
e := time.Now().Add(time.Duration(1) * time.Hour)
|
|
|
|
|
|
|
|
testCases := []testCase{
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
},
|
|
|
|
Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
|
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
AccessToken: "token1234",
|
|
|
|
IDToken: "rawtoken1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: &c,
|
|
|
|
ExpiresOn: &e,
|
2019-03-20 15:59:24 +02:00
|
|
|
RefreshToken: "refresh4321",
|
|
|
|
},
|
|
|
|
Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
|
|
|
encoded, err := tc.EncodeSessionState(tc.Cipher)
|
2019-05-05 14:33:13 +02:00
|
|
|
t.Logf("i:%d Encoded:%#vsessions.SessionState:%#v Error:%#v", i, encoded, tc.SessionState, err)
|
2019-03-20 15:59:24 +02:00
|
|
|
if tc.Error {
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Empty(t, encoded)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.JSONEq(t, tc.Encoded, encoded)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-05 14:33:13 +02:00
|
|
|
// TestDecodeSessionState testssessions.DecodeSessionState with the test vector
|
2019-03-20 15:59:24 +02:00
|
|
|
func TestDecodeSessionState(t *testing.T) {
|
2019-05-07 16:32:46 +02:00
|
|
|
created := time.Now()
|
|
|
|
createdJSON, _ := created.MarshalJSON()
|
|
|
|
createdString := string(createdJSON)
|
2019-03-20 15:59:24 +02:00
|
|
|
e := time.Now().Add(time.Duration(1) * time.Hour)
|
|
|
|
eJSON, _ := e.MarshalJSON()
|
|
|
|
eString := string(eJSON)
|
|
|
|
|
2019-05-24 18:06:48 +02:00
|
|
|
c, err := encryption.NewCipher([]byte(secret))
|
2019-03-20 15:59:24 +02:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
testCases := []testCase{
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
},
|
|
|
|
Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
|
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
2020-05-12 17:04:51 +02:00
|
|
|
User: "",
|
2019-03-20 15:59:24 +02:00
|
|
|
},
|
|
|
|
Encoded: `{"Email":"user@domain.com"}`,
|
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
User: "just-user",
|
|
|
|
},
|
|
|
|
Encoded: `{"User":"just-user"}`,
|
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
},
|
2019-05-07 16:32:46 +02:00
|
|
|
Encoded: fmt.Sprintf(`{"Email":"user@domain.com","User":"just-user","AccessToken":"I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==","IDToken":"xojNdyyjB1HgYWh6XMtXY/Ph5eCVxa1cNsklJw==","RefreshToken":"qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K","CreatedAt":%s,"ExpiresOn":%s}`, createdString, eString),
|
2019-03-20 15:59:24 +02:00
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
AccessToken: "token1234",
|
|
|
|
IDToken: "rawtoken1234",
|
2020-05-30 09:53:38 +02:00
|
|
|
CreatedAt: &created,
|
|
|
|
ExpiresOn: &e,
|
2019-03-20 15:59:24 +02:00
|
|
|
RefreshToken: "refresh4321",
|
|
|
|
},
|
2019-05-07 16:32:46 +02:00
|
|
|
Encoded: fmt.Sprintf(`{"Email":"FsKKYrTWZWrxSOAqA/fTNAUZS5QWCqOBjuAbBlbVOw==","User":"rT6JP3dxQhxUhkWrrd7yt6c1mDVyQCVVxw==","AccessToken":"I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==","IDToken":"xojNdyyjB1HgYWh6XMtXY/Ph5eCVxa1cNsklJw==","RefreshToken":"qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K","CreatedAt":%s,"ExpiresOn":%s}`, createdString, eString),
|
2019-03-20 15:59:24 +02:00
|
|
|
Cipher: c,
|
|
|
|
},
|
|
|
|
{
|
2019-05-05 14:33:13 +02:00
|
|
|
SessionState: sessions.SessionState{
|
2019-03-20 15:59:24 +02:00
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "just-user",
|
|
|
|
},
|
2019-04-09 13:55:33 +02:00
|
|
|
Encoded: `{"Email":"EGTllJcOFC16b7LBYzLekaHAC5SMMSPdyUrg8hd25g==","User":"rT6JP3dxQhxUhkWrrd7yt6c1mDVyQCVVxw=="}`,
|
2019-03-20 15:59:24 +02:00
|
|
|
Cipher: c,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Encoded: `{"Email":"user@domain.com","User":"just-user","AccessToken":"X"}`,
|
|
|
|
Cipher: c,
|
|
|
|
Error: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Encoded: `{"Email":"user@domain.com","User":"just-user","IDToken":"XXXX"}`,
|
|
|
|
Cipher: c,
|
|
|
|
Error: true,
|
|
|
|
},
|
2020-06-02 21:53:33 +02:00
|
|
|
{
|
|
|
|
SessionState: sessions.SessionState{
|
|
|
|
Email: "user@domain.com",
|
|
|
|
User: "YmFzZTY0LWVuY29kZWQtdXNlcgo=", // Base64 encoding of base64-encoded-user
|
|
|
|
},
|
|
|
|
Error: true,
|
|
|
|
Cipher: c,
|
|
|
|
},
|
2019-03-20 15:59:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for i, tc := range testCases {
|
2019-05-05 14:33:13 +02:00
|
|
|
ss, err := sessions.DecodeSessionState(tc.Encoded, tc.Cipher)
|
|
|
|
t.Logf("i:%d Encoded:%#vsessions.SessionState:%#v Error:%#v", i, tc.Encoded, ss, err)
|
2019-03-20 15:59:24 +02:00
|
|
|
if tc.Error {
|
|
|
|
assert.Error(t, err)
|
|
|
|
assert.Nil(t, ss)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
assert.NoError(t, err)
|
|
|
|
if assert.NotNil(t, ss) {
|
|
|
|
assert.Equal(t, tc.User, ss.User)
|
|
|
|
assert.Equal(t, tc.Email, ss.Email)
|
|
|
|
assert.Equal(t, tc.AccessToken, ss.AccessToken)
|
|
|
|
assert.Equal(t, tc.RefreshToken, ss.RefreshToken)
|
|
|
|
assert.Equal(t, tc.IDToken, ss.IDToken)
|
2020-05-30 09:53:38 +02:00
|
|
|
if tc.ExpiresOn != nil {
|
|
|
|
assert.NotEqual(t, nil, ss.ExpiresOn)
|
|
|
|
assert.Equal(t, tc.ExpiresOn.Unix(), ss.ExpiresOn.Unix())
|
|
|
|
}
|
2019-03-20 15:59:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 16:32:46 +02:00
|
|
|
|
|
|
|
func TestSessionStateAge(t *testing.T) {
|
|
|
|
ss := &sessions.SessionState{}
|
|
|
|
|
|
|
|
// Created at unset so should be 0
|
|
|
|
assert.Equal(t, time.Duration(0), ss.Age())
|
|
|
|
|
|
|
|
// Set CreatedAt to 1 hour ago
|
2020-05-30 09:53:38 +02:00
|
|
|
ss.CreatedAt = timePtr(time.Now().Add(-1 * time.Hour))
|
2019-05-07 16:32:46 +02:00
|
|
|
assert.Equal(t, time.Hour, ss.Age().Round(time.Minute))
|
|
|
|
}
|