This repository has been archived on 2023-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
dex/vendor/github.com/ericchiang/oidc/oidcproxy/nonce.go
2016-07-26 15:51:24 -07:00

73 lines
1.2 KiB
Go

package main
import (
"crypto/rand"
"encoding/base64"
"errors"
"io"
"sync"
"time"
"golang.org/x/net/context"
)
var (
gcInterval = time.Minute
expiresIn = time.Minute * 10
)
type memNonceSource struct {
mu sync.Mutex
nonces map[string]time.Time
}
func newNonceSource(ctx context.Context) *memNonceSource {
s := &memNonceSource{nonces: make(map[string]time.Time)}
go s.garbageCollect(ctx)
return s
}
func (s *memNonceSource) Nonce() (string, error) {
buff := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, buff); err != nil {
return "", err
}
nonce := base64.RawURLEncoding.EncodeToString(buff)
s.mu.Lock()
defer s.mu.Unlock()
s.nonces[nonce] = time.Now().Add(expiresIn)
return nonce, nil
}
func (s *memNonceSource) ClaimNonce(nonce string) error {
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.nonces[nonce]; ok {
delete(s.nonces, nonce)
return nil
}
return errors.New("invalid nonce")
}
func (s *memNonceSource) garbageCollect(ctx context.Context) {
for {
select {
case <-ctx.Done():
case <-time.After(gcInterval):
s.mu.Lock()
now := time.Now()
for nonce, exp := range s.nonces {
if now.After(exp) {
delete(s.nonces, nonce)
}
}
s.mu.Unlock()
}
}
}