databag/net/server/internal/authUtil.go

298 lines
8.2 KiB
Go
Raw Normal View History

2022-01-17 05:11:24 +00:00
package databag
import (
2022-07-22 19:28:14 +00:00
"databag/internal/store"
"encoding/base64"
"errors"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
2022-01-17 05:11:24 +00:00
"net/http"
2022-07-22 19:28:14 +00:00
"strings"
"time"
2022-01-17 05:11:24 +00:00
)
2022-03-08 21:31:04 +00:00
func AccountLogin(r *http.Request) (*store.Account, error) {
2022-01-18 05:48:42 +00:00
2022-07-22 19:28:14 +00:00
// extract request auth
username, password, ok := r.BasicAuth()
if !ok || username == "" || password == "" {
return nil, errors.New("invalid login")
}
2022-01-18 05:48:42 +00:00
2022-07-22 19:28:14 +00:00
// find account
account := &store.Account{}
if store.DB.Model(&store.Account{}).Where("Username = ?", username).First(&account).Error != nil {
return nil, errors.New("username not found")
}
2022-01-18 05:48:42 +00:00
2022-07-22 19:28:14 +00:00
// compare password
if bcrypt.CompareHashAndPassword(account.Password, []byte(password)) != nil {
return nil, errors.New("invalid password")
}
2022-01-18 05:48:42 +00:00
2022-07-22 19:28:14 +00:00
return account, nil
2022-01-18 05:48:42 +00:00
}
2022-03-11 07:57:27 +00:00
func BearerAccountToken(r *http.Request) (*store.AccountToken, error) {
2022-01-17 05:11:24 +00:00
2022-07-22 19:28:14 +00:00
// parse bearer authentication
auth := r.Header.Get("Authorization")
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer"))
// find token record
var accountToken store.AccountToken
if err := store.DB.Preload("Account").Where("token = ?", token).First(&accountToken).Error; err != nil {
return nil, err
}
if accountToken.Expires < time.Now().Unix() {
return nil, errors.New("expired token")
}
return &accountToken, nil
2022-01-17 05:11:24 +00:00
}
2022-06-08 08:25:41 +00:00
func AccessToken(r *http.Request) (*store.AccountToken, int, error) {
2022-07-22 19:28:14 +00:00
// parse authentication token
token := r.FormValue("token")
if token == "" {
return nil, http.StatusUnauthorized, errors.New("token not set")
}
// find token record
var accountToken store.AccountToken
if err := store.DB.Preload("Account").Where("token = ?", token).First(&accountToken).Error; err != nil {
return nil, http.StatusUnauthorized, err
}
if accountToken.Expires < time.Now().Unix() {
return nil, http.StatusUnauthorized, errors.New("expired token")
}
return &accountToken, http.StatusOK, nil
2022-06-08 08:25:41 +00:00
}
func ParamAdminToken(r *http.Request) (int, error) {
2022-07-22 19:28:14 +00:00
// parse authentication token
token := r.FormValue("token")
if token == "" {
return http.StatusUnauthorized, errors.New("token not set")
}
2022-07-22 19:28:14 +00:00
// nothing to do if not configured
if !getBoolConfigValue(CNFConfigured, false) {
return http.StatusUnauthorized, errors.New("node not configured")
}
2022-07-22 19:28:14 +00:00
// compare password
value := getStrConfigValue(CNFToken, "")
if value != token {
return http.StatusUnauthorized, errors.New("invalid admin token")
}
2022-07-22 19:28:14 +00:00
return http.StatusOK, nil
}
func ParamAgentToken(r *http.Request, detail bool) (*store.Account, int, error) {
2022-03-18 17:51:21 +00:00
2022-07-22 19:28:14 +00:00
// parse authentication token
target, access, err := ParseToken(r.FormValue("agent"))
if err != nil {
return nil, http.StatusBadRequest, err
}
// find token record
var app store.App
if detail {
if err := store.DB.Preload("Account.AccountDetail").Where("account_id = ? AND token = ?", target, access).First(&app).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
} else {
if err := store.DB.Preload("Account").Where("account_id = ? AND token = ?", target, access).First(&app).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
}
if app.Account.Disabled {
return nil, http.StatusGone, errors.New("account is inactive")
}
return &app.Account, http.StatusOK, nil
2022-03-18 17:51:21 +00:00
}
2022-01-20 23:19:26 +00:00
func BearerAppToken(r *http.Request, detail bool) (*store.Account, int, error) {
2022-07-22 19:28:14 +00:00
// parse bearer authentication
auth := r.Header.Get("Authorization")
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer"))
target, access, err := ParseToken(token)
if err != nil {
return nil, http.StatusBadRequest, err
}
// find token record
var app store.App
if detail {
if err := store.DB.Preload("Account.AccountDetail").Where("account_id = ? AND token = ?", target, access).First(&app).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
} else {
if err := store.DB.Preload("Account").Where("account_id = ? AND token = ?", target, access).First(&app).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
}
if app.Account.Disabled {
return nil, http.StatusGone, errors.New("account is inactive")
}
return &app.Account, http.StatusOK, nil
2022-01-22 19:04:29 +00:00
}
2022-01-22 18:45:39 +00:00
func ParseToken(token string) (string, string, error) {
2022-06-10 07:16:19 +00:00
2022-07-22 19:28:14 +00:00
split := strings.Split(token, ".")
if len(split) != 2 {
return "", "", errors.New("invalid token format")
}
return split[0], split[1], nil
2022-01-22 18:45:39 +00:00
}
func ParamTokenType(r *http.Request) string {
2022-07-22 19:28:14 +00:00
if r.FormValue(APPTokenContact) != "" {
return APPTokenContact
}
if r.FormValue(APPTokenAgent) != "" {
return APPTokenAgent
}
if r.FormValue(APPTokenAttach) != "" {
return APPTokenAttach
}
if r.FormValue(APPTokenCreate) != "" {
return APPTokenCreate
}
if r.FormValue(APPTokenReset) != "" {
return APPTokenReset
}
return ""
}
func ParamContactToken(r *http.Request, detail bool) (*store.Card, int, error) {
2022-07-22 19:28:14 +00:00
// parse authentication token
target, access, err := ParseToken(r.FormValue("contact"))
if err != nil {
return nil, http.StatusBadRequest, err
}
// find token record
var card store.Card
if detail {
if err := store.DB.Preload("CardSlot").Preload("Account.AccountDetail").Where("account_id = ? AND in_token = ?", target, access).First(&card).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
} else {
if err := store.DB.Preload("CardSlot").Preload("Account").Where("account_id = ? AND in_token = ?", target, access).First(&card).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
}
if card.Account.Disabled {
return nil, http.StatusGone, errors.New("account is inactive")
}
if card.Status != APPCardConnecting && card.Status != APPCardConnected {
return nil, http.StatusUnauthorized, errors.New("invalid connection state")
}
return &card, http.StatusOK, nil
}
2022-02-03 19:18:50 +00:00
func BearerContactToken(r *http.Request, detail bool) (*store.Card, int, error) {
2022-01-22 07:00:47 +00:00
2022-07-22 19:28:14 +00:00
// parse bearer authentication
auth := r.Header.Get("Authorization")
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer"))
target, access, err := ParseToken(token)
if err != nil {
return nil, http.StatusBadRequest, err
}
// find token record
var card store.Card
if detail {
if err := store.DB.Preload("Account.AccountDetail").Where("account_id = ? AND in_token = ?", target, access).First(&card).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
} else {
if err := store.DB.Preload("Account").Where("account_id = ? AND in_token = ?", target, access).First(&card).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, http.StatusNotFound, err
} else {
return nil, http.StatusInternalServerError, err
}
}
}
if card.Account.Disabled {
return nil, http.StatusGone, errors.New("account is inactive")
}
if card.Status != APPCardConnecting && card.Status != APPCardConnected {
return nil, http.StatusUnauthorized, errors.New("invalid connection state")
}
return &card, http.StatusOK, nil
2022-01-22 07:00:47 +00:00
}
2022-01-17 21:42:17 +00:00
func BasicCredentials(r *http.Request) (string, []byte, error) {
2022-01-17 05:11:24 +00:00
2022-07-22 19:28:14 +00:00
var username string
var password []byte
// parse bearer authentication
auth := r.Header.Get("Credentials")
token := strings.TrimSpace(strings.TrimPrefix(auth, "Basic"))
// decode basic auth
credentials, err := base64.StdEncoding.DecodeString(token)
if err != nil {
return username, password, err
}
// parse credentials
login := strings.Split(string(credentials), ":")
if login[0] == "" || login[1] == "" {
return username, password, errors.New("invalid credentials")
}
username = login[0]
// hash password
password, err = bcrypt.GenerateFromPassword([]byte(login[1]), bcrypt.DefaultCost)
if err != nil {
return username, password, err
}
return username, password, nil
2022-01-17 05:11:24 +00:00
}