diff --git a/aggregator/clean.go b/aggregator/clean.go
index 71a3fe93fb933b7babda87c21885c64a20137895..f37f93008d0af750bc9d29365cc1ea9ffd2ae42a 100644
--- a/aggregator/clean.go
+++ b/aggregator/clean.go
@@ -3,7 +3,7 @@ package aggregator
 import "time"
 
 func clean() {
-	t := time.Now().Unix() % (bucket * 2)
+	t := getTime() % (bucket * 2)
 	for i := (t + 2) % (bucket * 2); i != (t+bucket/2)%(bucket*2); i = (i + 1) % (bucket * 2) {
 		for k := range data[i] {
 			delete(data[i], k)
diff --git a/aggregator/collect.go b/aggregator/collect.go
index b0c8843b7f8341e554ae348f814cfd1b9ad41e97..9695ea663e27bdbed3931153435007d7efcf1078 100644
--- a/aggregator/collect.go
+++ b/aggregator/collect.go
@@ -1,13 +1,24 @@
 package aggregator
 
 import (
-	"sync"
+	"flag"
 	"time"
 )
 
-const bucket = 10
+var bucketFlag = flag.Int64("bucket", 10000, "Bucket size")
 
-// data[time][user] = choice
+var bucket int64 = 10000
+
+func init() {
+	flag.Parse()
+	bucket = *bucketFlag
+}
+
+func getTime() int64 {
+	return time.Now().UnixNano() / 1e6
+}
+
+// data[getTime][user] = choice
 var data = make([]map[string]string, bucket*2)
 
 func init() {
@@ -16,9 +27,7 @@ func init() {
 	}
 }
 
-var createTeamMutex sync.Mutex
-
 func Vote(UserID, Choice string) {
-	t := time.Now().Unix() % (bucket * 2)
+	t := getTime() % (bucket * 2)
 	data[t][UserID] = Choice
 }
diff --git a/aggregator/serve.go b/aggregator/serve.go
index 0b23f7b507f7015ff7ee8e470aa089379f41104c..31bd5054611866c069b4afaf4ba47bfad51857b0 100644
--- a/aggregator/serve.go
+++ b/aggregator/serve.go
@@ -2,11 +2,10 @@ package aggregator
 
 import (
 	"git.sch.bme.hu/mikewashere/matrix-backend/db"
-	"time"
 )
 
 func GetCurrentChoices() (map[string]map[string]int, error) {
-	t := time.Now().Unix() % (bucket * 2)
+	t := getTime() % (bucket * 2)
 	ret := make(map[string]map[string]int)
 
 	teams, e := db.GetTeamsWithMembers()
diff --git a/db/methods.go b/db/methods.go
index c7b53441f5eb95ec1d7844d345711624fa5b9cf3..905698d41cc6338d0b9a2f830a33e0708e56fb48 100644
--- a/db/methods.go
+++ b/db/methods.go
@@ -34,3 +34,16 @@ func GetTeamsWithMembers() ([]*Team, error) {
 	e := db.Model(&t).Relation("Members").Select()
 	return t, e
 }
+
+func GetUser(ID string) (*User, error) {
+	var u = &User{
+		ID: ID,
+	}
+
+	e := db.Model(u).WherePK().First()
+	if e != nil {
+		return nil, e
+	}
+
+	return u, nil
+}
diff --git a/db/models.go b/db/models.go
index 138e68ebf4aef2ff70f3afb45b1c7c378d717c06..0feefe62e0516e3eeaa68377e3a65b7ab6a3e2cf 100644
--- a/db/models.go
+++ b/db/models.go
@@ -40,7 +40,7 @@ var db = pg.Connect(&pg.Options{
 })
 
 // special magic to run db init before other inits
-var _ = func() {
+var _ = func() error {
 	models := []interface{}{
 		(*Choice)(nil),
 		(*Team)(nil),
@@ -56,4 +56,5 @@ var _ = func() {
 			panic(err)
 		}
 	}
-}
+	return nil
+}()
diff --git a/input/ws.go b/input/ws.go
index 82f19d86695b2865cdc78e96689926af786d1d94..b321c9ca7e50bdedca9a31a62c7898d2b62e6565 100644
--- a/input/ws.go
+++ b/input/ws.go
@@ -6,11 +6,14 @@ import (
 	"git.sch.bme.hu/mikewashere/matrix-backend/aggregator"
 	"git.sch.bme.hu/mikewashere/matrix-backend/db"
 	"github.com/igm/sockjs-go/v3/sockjs"
+	"net/http"
 	"strings"
 )
 
 type SockState int
 
+const CookieName = "session"
+
 const (
 	Connected SockState = iota
 	Authenticated
@@ -21,27 +24,51 @@ type Message struct {
 	Msg  interface{} `json:"msg"`
 }
 
+func getUserFromCookie(r *http.Request) (*db.User, error) {
+	c, e := r.Cookie(CookieName)
+	if e != nil {
+		return nil, e
+	}
+
+	return db.GetUser(c.Value)
+}
+
 func InputHandler(session sockjs.Session) {
 	sendError := func(e error) {
-		session.Send(fmt.Sprintf(`{ "type": "error", "msg": "%s" }`, e.Error()))
+		_ = session.Send(fmt.Sprintf(`{ "type": "error", "msg": "%s" }`, e.Error()))
 	}
 
-	state := Connected
-	session.Send(`{ "type": "error", "msg": "team or user code needed" }`)
 	var u *db.User
+	var e error
+	state := Connected
+
+	u, e = getUserFromCookie(session.Request())
+	if e != nil && u != nil && u.TeamID != "" {
+		state = Authenticated
+	}
+
+	_ = session.Send(`{ "type": "error", "msg": "team or user code needed" }`)
+
 	for {
 		if msg, err := session.Recv(); err == nil {
 			msg = strings.TrimSpace(msg)
 			switch state {
 
 			case Connected:
-				var e error
-				u, e = db.CreateUser(msg)
-				if e != nil {
-					sendError(e)
-					continue
+				if len(msg) > 2 && msg[0:2] == "u " {
+					u, e = db.GetUser(msg[2:])
+					if e != nil {
+						sendError(e)
+						continue
+					}
+				} else {
+					u, e = db.CreateUser(msg)
+					if e != nil {
+						sendError(e)
+						continue
+					}
 				}
-				session.Send(fmt.Sprintf(`{ "type": "userid", "msg": "%v" }`, u.ID))
+				_ = session.Send(fmt.Sprintf(`{ "type": "userid", "msg": "%v" }`, u.ID))
 				state = Authenticated
 
 			case Authenticated:
@@ -63,10 +90,10 @@ func InputHandler(session sockjs.Session) {
 						continue
 					}
 
-					session.Send(string(b))
+					_ = session.Send(string(b))
 				} else {
 					aggregator.Vote(u.ID, msg)
-					session.Send(`{ "type": "success", "msg": "" }`)
+					_ = session.Send(`{ "type": "success", "msg": "" }`)
 				}
 
 			}