@@ -2,7 +2,6 @@ package providers
22
33import (
44 "fmt"
5− "strings"
65 "testing"
76 "time"
87
@@ -27,7 +26,6 @@ func TestSessionStateSerialization(t *testing.T) {
2726 }
2827 encoded, err := s.EncodeSessionState(c)
2928 assert.Equal(t, nil, err)
30− assert.Equal(t, 4, strings.Count(encoded, "|"))
3129
3230 ss, err := DecodeSessionState(encoded, c)
3331 t.Logf("%#v", ss)
@@ -65,7 +63,6 @@ func TestSessionStateSerializationWithUser(t *testing.T) {
6563 }
6664 encoded, err := s.EncodeSessionState(c)
6765 assert.Equal(t, nil, err)
68− assert.Equal(t, 4, strings.Count(encoded, "|"))
6966
7067 ss, err := DecodeSessionState(encoded, c)
7168 t.Logf("%#v", ss)
@@ -96,8 +93,6 @@ func TestSessionStateSerializationNoCipher(t *testing.T) {
9693 }
9794 encoded, err := s.EncodeSessionState(nil)
9895 assert.Equal(t, nil, err)
99− expected := fmt.Sprintf("email:%s user:", s.Email)
100− assert.Equal(t, expected, encoded)
10196
10297 // only email should have been serialized
10398 ss, err := DecodeSessionState(encoded, nil)
@@ -118,8 +113,6 @@ func TestSessionStateSerializationNoCipherWithUser(t *testing.T) {
118113 }
119114 encoded, err := s.EncodeSessionState(nil)
120115 assert.Equal(t, nil, err)
121− expected := fmt.Sprintf("email:%s user:%s", s.Email, s.User)
122− assert.Equal(t, expected, encoded)
123116
124117 // only email should have been serialized
125118 ss, err := DecodeSessionState(encoded, nil)
@@ -130,19 +123,6 @@ func TestSessionStateSerializationNoCipherWithUser(t *testing.T) {
130123 assert.Equal(t, "", ss.RefreshToken)
131124}
132125
133−func TestSessionStateAccountInfo(t *testing.T) {
134− s := &SessionState{
135− Email: "user@domain.com",
136− User: "just-user",
137− }
138− expected := fmt.Sprintf("email:%v user:%v", s.Email, s.User)
139− assert.Equal(t, expected, s.accountInfo())
140−
141− s.Email = ""
142− expected = fmt.Sprintf("email:%v user:%v", s.Email, s.User)
143− assert.Equal(t, expected, s.accountInfo())
144−}
145−
146126func TestExpired(t *testing.T) {
147127 s := &SessionState{ExpiresOn: time.Now().Add(time.Duration(-1) * time.Minute)}
148128 assert.Equal(t, true, s.IsExpired())
@@ -153,3 +133,185 @@ func TestExpired(t *testing.T) {
153133 s = &SessionState{}
154134 assert.Equal(t, false, s.IsExpired())
155135}
136+
137+type testCase struct {
138+ SessionState
139+ Encoded string
140+ Cipher *cookie.Cipher
141+ Error bool
142+}
143+
144+// TestEncodeSessionState tests EncodeSessionState with the test vector
145+//
146+// Currently only tests without cipher here because we have no way to mock
147+// the random generator used in EncodeSessionState.
148+func TestEncodeSessionState(t *testing.T) {
149+ e := time.Now().Add(time.Duration(1) * time.Hour)
150+
151+ testCases := []testCase{
152+ {
153+ SessionState: SessionState{
154+ Email: "user@domain.com",
155+ User: "just-user",
156+ },
157+ Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
158+ },
159+ {
160+ SessionState: SessionState{
161+ Email: "user@domain.com",
162+ User: "just-user",
163+ AccessToken: "token1234",
164+ IDToken: "rawtoken1234",
165+ ExpiresOn: e,
166+ RefreshToken: "refresh4321",
167+ },
168+ Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
169+ },
170+ }
171+
172+ for i, tc := range testCases {
173+ encoded, err := tc.EncodeSessionState(tc.Cipher)
174+ t.Logf("i:%d Encoded:%#v SessionState:%#v Error:%#v", i, encoded, tc.SessionState, err)
175+ if tc.Error {
176+ assert.Error(t, err)
177+ assert.Empty(t, encoded)
178+ continue
179+ }
180+ assert.NoError(t, err)
181+ assert.JSONEq(t, tc.Encoded, encoded)
182+ }
183+}
184+
185+// TestDecodeSessionState tests DecodeSessionState with the test vector
186+func TestDecodeSessionState(t *testing.T) {
187+ e := time.Now().Add(time.Duration(1) * time.Hour)
188+ eJSON, _ := e.MarshalJSON()
189+ eString := string(eJSON)
190+ eUnix := e.Unix()
191+
192+ c, err := cookie.NewCipher([]byte(secret))
193+ assert.NoError(t, err)
194+
195+ testCases := []testCase{
196+ {
197+ SessionState: SessionState{
198+ Email: "user@domain.com",
199+ User: "just-user",
200+ },
201+ Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
202+ },
203+ {
204+ SessionState: SessionState{
205+ Email: "user@domain.com",
206+ User: "user",
207+ },
208+ Encoded: `{"Email":"user@domain.com"}`,
209+ },
210+ {
211+ SessionState: SessionState{
212+ User: "just-user",
213+ },
214+ Encoded: `{"User":"just-user"}`,
215+ },
216+ {
217+ SessionState: SessionState{
218+ Email: "user@domain.com",
219+ User: "just-user",
220+ },
221+ Encoded: fmt.Sprintf(`{"Email":"user@domain.com","User":"just-user","AccessToken":"I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==","IDToken":"xojNdyyjB1HgYWh6XMtXY/Ph5eCVxa1cNsklJw==","RefreshToken":"qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K","ExpiresOn":%s}`, eString),
222+ },
223+ {
224+ SessionState: SessionState{
225+ Email: "user@domain.com",
226+ User: "just-user",
227+ AccessToken: "token1234",
228+ IDToken: "rawtoken1234",
229+ ExpiresOn: e,
230+ RefreshToken: "refresh4321",
231+ },
232+ Encoded: fmt.Sprintf(`{"Email":"user@domain.com","User":"just-user","AccessToken":"I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==","IDToken":"xojNdyyjB1HgYWh6XMtXY/Ph5eCVxa1cNsklJw==","RefreshToken":"qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K","ExpiresOn":%s}`, eString),
233+ Cipher: c,
234+ },
235+ {
236+ SessionState: SessionState{
237+ Email: "user@domain.com",
238+ User: "just-user",
239+ },
240+ Encoded: `{"Email":"user@domain.com","User":"just-user"}`,
241+ Cipher: c,
242+ },
243+ {
244+ Encoded: `{"Email":"user@domain.com","User":"just-user","AccessToken":"X"}`,
245+ Cipher: c,
246+ Error: true,
247+ },
248+ {
249+ Encoded: `{"Email":"user@domain.com","User":"just-user","IDToken":"XXXX"}`,
250+ Cipher: c,
251+ Error: true,
252+ },
253+ {
254+ SessionState: SessionState{
255+ User: "just-user",
256+ Email: "user@domain.com",
257+ },
258+ Encoded: "email:user@domain.com user:just-user",
259+ },
260+ {
261+ Encoded: "email:user@domain.com user:just-user||||",
262+ Error: true,
263+ },
264+ {
265+ Encoded: "email:user@domain.com user:just-user",
266+ Cipher: c,
267+ Error: true,
268+ },
269+ {
270+ Encoded: "email:user@domain.com user:just-user|||99999999999999999999|",
271+ Cipher: c,
272+ Error: true,
273+ },
274+ {
275+ SessionState: SessionState{
276+ Email: "user@domain.com",
277+ User: "just-user",
278+ AccessToken: "token1234",
279+ ExpiresOn: e,
280+ RefreshToken: "refresh4321",
281+ },
282+ Encoded: fmt.Sprintf("email:user@domain.com user:just-user|I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==|%d|qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K", eUnix),
283+ Cipher: c,
284+ },
285+ {
286+ SessionState: SessionState{
287+ Email: "user@domain.com",
288+ User: "just-user",
289+ AccessToken: "token1234",
290+ IDToken: "rawtoken1234",
291+ ExpiresOn: e,
292+ RefreshToken: "refresh4321",
293+ },
294+ Encoded: fmt.Sprintf("email:user@domain.com user:just-user|I6s+ml+/MldBMgHIiC35BTKTh57skGX24w==|xojNdyyjB1HgYWh6XMtXY/Ph5eCVxa1cNsklJw==|%d|qEX0x6RmASxo4dhlBG6YuRs9Syn/e9sHu/+K", eUnix),
295+ Cipher: c,
296+ },
297+ }
298+
299+ for i, tc := range testCases {
300+ ss, err := DecodeSessionState(tc.Encoded, tc.Cipher)
301+ t.Logf("i:%d Encoded:%#v SessionState:%#v Error:%#v", i, tc.Encoded, ss, err)
302+ if tc.Error {
303+ assert.Error(t, err)
304+ assert.Nil(t, ss)
305+ continue
306+ }
307+ assert.NoError(t, err)
308+ if assert.NotNil(t, ss) {
309+ assert.Equal(t, tc.User, ss.User)
310+ assert.Equal(t, tc.Email, ss.Email)
311+ assert.Equal(t, tc.AccessToken, ss.AccessToken)
312+ assert.Equal(t, tc.RefreshToken, ss.RefreshToken)
313+ assert.Equal(t, tc.IDToken, ss.IDToken)
314+ assert.Equal(t, tc.ExpiresOn.Unix(), ss.ExpiresOn.Unix())
315+ }
316+ }
317+}