package main import ( "crypto/rand" "database/sql" "encoding/base64" "fmt" "log" _ "github.com/go-sql-driver/mysql" "github.com/go-webauthn/webauthn/webauthn" ) type InMem struct { // TODO: it would be nice to have a mutex here // TODO: use pointers to avoid copying users map[string]PasskeyUser sessions map[string]webauthn.SessionData log* log.Logger db* sql.DB } func (i *InMem) GenSessionID() (string, error) { b := make([]byte, 32) _, err := rand.Read(b) if err != nil { return "", err } return base64.URLEncoding.EncodeToString(b), nil } func NewInMem(log *log.Logger, db *sql.DB) *InMem { return &InMem{ users: make(map[string]PasskeyUser), sessions: make(map[string]webauthn.SessionData), log: log, db: db, } } func (i *InMem) GetSession(token string) (webauthn.SessionData, bool) { i.log.Printf("[DEBUG] GetSession: %v", i.sessions[token]) val, ok := i.sessions[token] return val, ok } func (i *InMem) SaveSession(token string, data webauthn.SessionData) { i.log.Printf("[DEBUG] SaveSession: %s - %v", token, data) i.sessions[token] = data } func (i *InMem) DeleteSession(token string) { i.log.Printf("[DEBUG] DeleteSession: %v", token) delete(i.sessions, token) } func (i *InMem) GetOrCreateUser(userName string) PasskeyUser { i.log.Printf("[DEBUG] GetOrCreateUser: %v", userName) if _, ok := i.users[userName]; !ok { i.log.Printf("[DEBUG] GetOrCreateUser: creating new user: %v", userName) i.users[userName] = &User{ ID: []byte(userName), DisplayName: userName, Name: userName, } } return i.users[userName] } func (i *InMem) SaveUser(user PasskeyUser) { username := user.WebAuthnName() rpid := "oworganizer.com" kid := base64.StdEncoding.EncodeToString(user.WebAuthnCredentials()[0].Descriptor().CredentialID) aaguid := base64.StdEncoding.EncodeToString(user.WebAuthnCredentials()[0].Authenticator.AAGUID) publicKey := base64.StdEncoding.EncodeToString(user.WebAuthnCredentials()[0].PublicKey) attestationType := user.WebAuthnCredentials()[0].AttestationType attestationFormat := user.WebAuthnCredentials()[0].AttestationFormat attestation := user.WebAuthnCredentials()[0].Attestation.ClientDataJSON _, err = i.db.Exec("INSERT INTO users (username, rpid, kid, aaguid, public_key, attestation_type, attestation_format, attestation) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", username, rpid, kid, aaguid, publicKey, attestationType, attestationFormat, attestation) if err != nil { panic(err.Error()) } fmt.Println("Yay, values added!") i.log.Printf("[DEBUG] SaveUser: %v", user.WebAuthnName()) i.users[user.WebAuthnName()] = user }