37 lines
825 B
Go
37 lines
825 B
Go
package handler
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// csrfToken returns an HMAC token valid for the current and previous hour.
|
|
func csrfToken() string {
|
|
return csrfTokenForTime(time.Now().UTC())
|
|
}
|
|
|
|
func csrfTokenForTime(t time.Time) string {
|
|
bucket := t.Truncate(time.Hour).Unix()
|
|
mac := hmac.New(sha256.New, sessionSecret())
|
|
mac.Write([]byte(fmt.Sprintf("csrf:%d", bucket)))
|
|
return hex.EncodeToString(mac.Sum(nil))
|
|
}
|
|
|
|
// csrfValid returns true if token matches the current or previous hour's token.
|
|
func csrfValid(token string) bool {
|
|
if token == "" {
|
|
return false
|
|
}
|
|
now := time.Now().UTC()
|
|
for _, t := range []time.Time{now, now.Add(-time.Hour)} {
|
|
expected := csrfTokenForTime(t)
|
|
if hmac.Equal([]byte(token), []byte(expected)) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|