178 lines
4.3 KiB
Go
178 lines
4.3 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
argon2 "github.com/alexedwards/argon2id"
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-gonic/gin"
|
|
"reichard.io/bbank/database"
|
|
)
|
|
|
|
// KOSync API Auth Headers
|
|
type authHeader struct {
|
|
AuthUser string `header:"x-auth-user"`
|
|
AuthKey string `header:"x-auth-key"`
|
|
}
|
|
|
|
func (api *API) authorizeCredentials(username string, password string) (authorized bool) {
|
|
user, err := api.DB.Queries.GetUser(api.DB.Ctx, username)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
if match, err := argon2.ComparePasswordAndHash(password, *user.Pass); err != nil || match != true {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (api *API) authAPIMiddleware(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
|
|
// Utilize Session Token
|
|
if authorizedUser := session.Get("authorizedUser"); authorizedUser != nil {
|
|
c.Set("AuthorizedUser", authorizedUser)
|
|
c.Header("Cache-Control", "private")
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
var rHeader authHeader
|
|
if err := c.ShouldBindHeader(&rHeader); err != nil {
|
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Incorrect Headers"})
|
|
return
|
|
}
|
|
if rHeader.AuthUser == "" || rHeader.AuthKey == "" {
|
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization Headers"})
|
|
return
|
|
}
|
|
|
|
if authorized := api.authorizeCredentials(rHeader.AuthUser, rHeader.AuthKey); authorized != true {
|
|
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
|
|
return
|
|
}
|
|
|
|
// Set Session Cookie
|
|
session.Set("authorizedUser", rHeader.AuthUser)
|
|
session.Save()
|
|
|
|
c.Set("AuthorizedUser", rHeader.AuthUser)
|
|
c.Next()
|
|
}
|
|
|
|
func (api *API) authWebAppMiddleware(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
|
|
// Utilize Session Token
|
|
if authorizedUser := session.Get("authorizedUser"); authorizedUser != nil {
|
|
c.Set("AuthorizedUser", authorizedUser)
|
|
c.Header("Cache-Control", "private")
|
|
c.Next()
|
|
return
|
|
}
|
|
|
|
c.Redirect(http.StatusFound, "/login")
|
|
c.Abort()
|
|
}
|
|
|
|
func (api *API) authFormLogin(c *gin.Context) {
|
|
username := strings.TrimSpace(c.PostForm("username"))
|
|
rawPassword := strings.TrimSpace(c.PostForm("password"))
|
|
|
|
if username == "" || rawPassword == "" {
|
|
c.HTML(http.StatusUnauthorized, "login", gin.H{
|
|
"RegistrationEnabled": api.Config.RegistrationEnabled,
|
|
"Error": "Invalid Credentials",
|
|
})
|
|
return
|
|
}
|
|
|
|
// MD5 - KOSync Compatiblity
|
|
password := fmt.Sprintf("%x", md5.Sum([]byte(rawPassword)))
|
|
if authorized := api.authorizeCredentials(username, password); authorized != true {
|
|
c.HTML(http.StatusUnauthorized, "login", gin.H{
|
|
"RegistrationEnabled": api.Config.RegistrationEnabled,
|
|
"Error": "Invalid Credentials",
|
|
})
|
|
return
|
|
}
|
|
|
|
session := sessions.Default(c)
|
|
|
|
// Set Session Cookie
|
|
session.Set("authorizedUser", username)
|
|
session.Save()
|
|
|
|
c.Redirect(http.StatusFound, "/")
|
|
}
|
|
|
|
func (api *API) authFormRegister(c *gin.Context) {
|
|
if !api.Config.RegistrationEnabled {
|
|
c.AbortWithStatus(http.StatusConflict)
|
|
}
|
|
|
|
username := strings.TrimSpace(c.PostForm("username"))
|
|
rawPassword := strings.TrimSpace(c.PostForm("password"))
|
|
|
|
if username == "" || rawPassword == "" {
|
|
c.HTML(http.StatusBadRequest, "login", gin.H{
|
|
"Register": true,
|
|
"Error": "Registration Disabled or User Already Exists",
|
|
})
|
|
return
|
|
}
|
|
password := fmt.Sprintf("%x", md5.Sum([]byte(rawPassword)))
|
|
|
|
hashedPassword, err := argon2.CreateHash(password, argon2.DefaultParams)
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "login", gin.H{
|
|
"Register": true,
|
|
"Error": "Registration Disabled or User Already Exists",
|
|
})
|
|
return
|
|
}
|
|
|
|
rows, err := api.DB.Queries.CreateUser(api.DB.Ctx, database.CreateUserParams{
|
|
ID: username,
|
|
Pass: &hashedPassword,
|
|
})
|
|
|
|
// SQL Error
|
|
if err != nil {
|
|
c.HTML(http.StatusBadRequest, "login", gin.H{
|
|
"Register": true,
|
|
"Error": "Registration Disabled or User Already Exists",
|
|
})
|
|
return
|
|
}
|
|
|
|
// User Already Exists
|
|
if rows == 0 {
|
|
c.HTML(http.StatusBadRequest, "login", gin.H{
|
|
"Register": true,
|
|
"Error": "Registration Disabled or User Already Exists",
|
|
})
|
|
return
|
|
}
|
|
|
|
session := sessions.Default(c)
|
|
|
|
// Set Session Cookie
|
|
session.Set("authorizedUser", username)
|
|
session.Save()
|
|
|
|
c.Redirect(http.StatusFound, "/")
|
|
}
|
|
|
|
func (api *API) authLogout(c *gin.Context) {
|
|
session := sessions.Default(c)
|
|
session.Clear()
|
|
session.Save()
|
|
c.Redirect(http.StatusFound, "/login")
|
|
}
|