go-mockid/mockid/nonce.go

65 lines
1.1 KiB
Go

package mockid
import (
"crypto/rand"
"encoding/base64"
"net/http"
"sync"
"time"
)
//var nonces map[string]int64
//var nonCh chan string
var nonces sync.Map
func issueNonce(w http.ResponseWriter, r *http.Request) {
b := make([]byte, 16)
_, _ = rand.Read(b)
nonce := base64.RawURLEncoding.EncodeToString(b)
//nonCh <- nonce
nonces.Store(nonce, time.Now())
w.Header().Set("Replay-Nonce", nonce)
}
func requireNonce(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
nonce := r.Header.Get("Replay-Nonce")
// TODO expire nonces every so often
//t := nonces[nonce]
if !useNonce(nonce) {
http.Error(
w,
`{ "error": "invalid or expired nonce", "error_code": "ENONCE" }`,
http.StatusBadRequest,
)
return
}
issueNonce(w, r)
next(w, r)
}
}
func checkNonce(nonce string) bool {
var t time.Time
tmp, ok := nonces.Load(nonce)
if ok {
t = tmp.(time.Time)
}
if ok && time.Now().Sub(t) <= 15*time.Minute {
return true
}
return false
}
func useNonce(nonce string) bool {
if checkNonce(nonce) {
//delete(nonces, nonce)
nonces.Delete(nonce)
return true
}
return false
}