package main import ( "fmt" "strings" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/pquerna/otp/totp" "gorm.io/gorm" ) type Signup struct { Username string `form:"username"` } func signup(c *gin.Context) { var s Signup c.Bind(&s) key, err := totp.Generate(totp.GenerateOpts{AccountName: s.Username, Issuer: "me"}) if err != nil { c.Status(502) return } var user User if db.First(&user, "username = ?", s.Username).Error == gorm.ErrRecordNotFound { user.Username = s.Username user.Secret = key.Secret() user.Token = uuid.New() db.Create(&user) c.SetCookie("auth", fmt.Sprint("Bearer ", user.Token), 10000, "/", "localhost", true, false) c.Header("Authorization", fmt.Sprint("Bearer ", user.Token)) c.String(200, "%s", key.Secret()) } else { c.String(404, "username already used") } } type Login struct { Username string `form:"username"` Code string `form:"code"` } func login(c *gin.Context) { var login Login var user User c.Bind(&login) if err := db.Where("username = ?", login.Username).First(&user).Error; err != nil { c.String(404, "something went wrong") return } correct := totp.Validate(login.Code, user.Secret) if correct { c.SetCookie("auth", fmt.Sprint("Bearer ", user.Token), 10000, "/", "localhost", true, false) c.Redirect(200, "/") } else { c.String(404, "wrong code") } } func reset_token(c *gin.Context) { user := c.MustGet("user").(User) user.Token = uuid.New() db.Update("token", &user) } func check_auth(c *gin.Context) { cookie, _ := c.Cookie("auth") token, _ := strings.CutPrefix(cookie, "Bearer ") user := User{} auth := db.First(&user, "token = ?", token).Error == nil c.Set("authorized", auth) if auth { c.Set("user", user) } c.Next() }