package db import ( "sync" "time" ) type oauthEntry struct { created time.Time callback string } type OAuthState struct { states map[string]oauthEntry m sync.Mutex } func NewOAuthState() *OAuthState { return &OAuthState{ states: make(map[string]oauthEntry), m: sync.Mutex{}, } } func (o *OAuthState) Create(callback string) string { o.m.Lock() defer o.m.Unlock() var state string ok := true for ok { state = createToken(32) _, ok = o.states[state] } o.states[state] = oauthEntry{ created: time.Now(), callback: callback, } return state } func (o *OAuthState) Validate(code string) (string, bool) { o.m.Lock() defer o.m.Unlock() entry, ok := o.states[code] return entry.callback, ok } func (o *OAuthState) Remove(code string) { o.m.Lock() defer o.m.Unlock() delete(o.states, code) } func (o *OAuthState) GarbageCycle(period time.Duration, duration time.Duration) { tick := time.NewTicker(period) clean := func() { o.m.Lock() defer o.m.Unlock() now := time.Now() for state, entry := range o.states { if now.After(entry.created.Add(duration)) { delete(o.states, state) } } } for { select { case <-tick.C: clean() } } }