package auth import ( "net/http" "time" "github.com/labstack/echo/v4" ) type SessionStore struct { s map[TokenID]*Token lastCull time.Time } type TokenID string type Token struct { // TODO: jwt bro ID TokenID Ctime time.Time Expires time.Time Addr string } func (ss *SessionStore) init() { ss.s = make(map[TokenID]*Token) } const cullInterval = 5 * time.Minute func (ss *SessionStore) cull() { if now := time.Now(); now.Sub(ss.lastCull) > cullInterval { for k, v := range ss.s { if now.After(v.Expires) { delete(ss.s, k) } } } } func (ss *SessionStore) register(t *Token) { ss.cull() ss.s[t.ID] = t } func (ss *SessionStore) verify(tr *TokenRequest, r *http.Request) bool { if t, hasToken := ss.s[tr.Code]; hasToken { // TODO: JWT if t.Expires.After(time.Now()) { return true } } return false } const defaultExpiration = 2 * time.Hour func (a *Authenticator) NewToken(r *http.Request, f *Flow) TokenID { id := TokenID(genUUID()) t := &Token{ ID: id, Ctime: time.Now(), Expires: time.Now().Add(defaultExpiration), Addr: r.RemoteAddr, } a.sessions.register(t) return id } type TokenRequest struct { ClientID string `query:"client_id"` // TODO: validate this? Code TokenID `query:"code"` GrantType string `query:"grant_type"` } func (a *Authenticator) TokenHandler(c echo.Context) error { var rq TokenRequest err := c.Bind(&rq) if err != nil { return err } if a.sessions.verify(&rq, c.Request()) { // TODO: success return c.String(http.StatusOK, "token good I guess") } return c.String(http.StatusUnauthorized, "token bad I guess") }