Skip to content

Commit

Permalink
xsrftoken: add custom timeout support for valid func
Browse files Browse the repository at this point in the history
Added new function 'ValidFor' with custom token timeout support.
Function 'Valid' will use default token timeout.

Fixes golang/go#41438

Change-Id: I5cf0388aeed7ca34edcb0d3493c3e79c8ce19938
GitHub-Last-Rev: 3e3b581
GitHub-Pull-Request: #86
Reviewed-on: https://go-review.googlesource.com/c/net/+/260317
Run-TryBot: Ian Lance Taylor <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
Trust: Filippo Valsorda <[email protected]>
  • Loading branch information
bynov authored and ianlancetaylor committed Oct 8, 2020
1 parent a7d1128 commit 59f7323
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
13 changes: 10 additions & 3 deletions xsrftoken/xsrf.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,19 @@ func generateTokenAtTime(key, userID, actionID string, now time.Time) string {
}

// Valid reports whether a token is a valid, unexpired token returned by Generate.
// The token is considered to be expired and invalid if it is older than the default Timeout.
func Valid(token, key, userID, actionID string) bool {
return validTokenAtTime(token, key, userID, actionID, time.Now())
return validTokenAtTime(token, key, userID, actionID, time.Now(), Timeout)
}

// ValidFor reports whether a token is a valid, unexpired token returned by Generate.
// The token is considered to be expired and invalid if it is older than the timeout duration.
func ValidFor(token, key, userID, actionID string, timeout time.Duration) bool {
return validTokenAtTime(token, key, userID, actionID, time.Now(), timeout)
}

// validTokenAtTime reports whether a token is valid at the given time.
func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
func validTokenAtTime(token, key, userID, actionID string, now time.Time, timeout time.Duration) bool {
if len(key) == 0 {
panic("zero length xsrf secret key")
}
Expand All @@ -75,7 +82,7 @@ func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
issueTime := time.Unix(0, millis*1e6)

// Check that the token is not expired.
if now.Sub(issueTime) >= Timeout {
if now.Sub(issueTime) >= timeout {
return false
}

Expand Down
31 changes: 21 additions & 10 deletions xsrftoken/xsrf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,22 @@ var (

func TestValidToken(t *testing.T) {
tok := generateTokenAtTime(key, userID, actionID, now)
if !validTokenAtTime(tok, key, userID, actionID, oneMinuteFromNow) {
if !validTokenAtTime(tok, key, userID, actionID, oneMinuteFromNow, Timeout) {
t.Error("One second later: Expected token to be valid")
}
if !validTokenAtTime(tok, key, userID, actionID, now.Add(Timeout-1*time.Nanosecond)) {
if !validTokenAtTime(tok, key, userID, actionID, now.Add(Timeout-1*time.Nanosecond), Timeout) {
t.Error("Just before timeout: Expected token to be valid")
}
if !validTokenAtTime(tok, key, userID, actionID, now.Add(-1*time.Minute+1*time.Millisecond)) {
if !validTokenAtTime(tok, key, userID, actionID, now.Add(-1*time.Minute+1*time.Millisecond), Timeout) {
t.Error("One minute in the past: Expected token to be valid")
}
if !validTokenAtTime(tok, key, userID, actionID, oneMinuteFromNow, time.Hour) {
t.Error("One second later: Expected token to be valid")
}
if !validTokenAtTime(tok, key, userID, actionID, now.Add(time.Minute-1*time.Nanosecond), time.Minute) {
t.Error("Just before timeout: Expected token to be valid")
}
if !validTokenAtTime(tok, key, userID, actionID, now.Add(-1*time.Minute+1*time.Millisecond), time.Hour) {
t.Error("One minute in the past: Expected token to be valid")
}
}
Expand Down Expand Up @@ -69,17 +78,19 @@ func TestInvalidToken(t *testing.T) {
invalidTokenTests := []struct {
name, key, userID, actionID string
t time.Time
timeout time.Duration
}{
{"Bad key", "foobar", userID, actionID, oneMinuteFromNow},
{"Bad userID", key, "foobar", actionID, oneMinuteFromNow},
{"Bad actionID", key, userID, "foobar", oneMinuteFromNow},
{"Expired", key, userID, actionID, now.Add(Timeout + 1*time.Millisecond)},
{"More than 1 minute from the future", key, userID, actionID, now.Add(-1*time.Nanosecond - 1*time.Minute)},
{"Bad key", "foobar", userID, actionID, oneMinuteFromNow, Timeout},
{"Bad userID", key, "foobar", actionID, oneMinuteFromNow, Timeout},
{"Bad actionID", key, userID, "foobar", oneMinuteFromNow, Timeout},
{"Expired", key, userID, actionID, now.Add(Timeout + 1*time.Millisecond), Timeout},
{"More than 1 minute from the future", key, userID, actionID, now.Add(-1*time.Nanosecond - 1*time.Minute), Timeout},
{"Expired with 1 minute timeout", key, userID, actionID, now.Add(time.Minute + 1*time.Millisecond), time.Minute},
}

tok := generateTokenAtTime(key, userID, actionID, now)
for _, itt := range invalidTokenTests {
if validTokenAtTime(tok, itt.key, itt.userID, itt.actionID, itt.t) {
if validTokenAtTime(tok, itt.key, itt.userID, itt.actionID, itt.t, itt.timeout) {
t.Errorf("%v: Expected token to be invalid", itt.name)
}
}
Expand All @@ -98,7 +109,7 @@ func TestValidateBadData(t *testing.T) {
}

for _, bdt := range badDataTests {
if validTokenAtTime(bdt.tok, key, userID, actionID, oneMinuteFromNow) {
if validTokenAtTime(bdt.tok, key, userID, actionID, oneMinuteFromNow, Timeout) {
t.Errorf("%v: Expected token to be invalid", bdt.name)
}
}
Expand Down

0 comments on commit 59f7323

Please sign in to comment.