ocbo-esign/backend/middleware/tokenChecker.go

117 lines
2.6 KiB
Go

package middleware
import (
"log"
"net/http"
"os"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/joho/godotenv"
)
func decrypt(encrypted string) (string, error) {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
privateKey := os.Getenv("PRIVATE_KEY")
cipherText, err := base64.StdEncoding.DecodeString(encrypted)
if err != nil {
return "", errors.New("cannot decode encrypted text")
}
block, _ := pem.Decode([]byte(privateKey))
if block == nil {
return "", errors.New("private key error")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", err
}
result, err := rsa.DecryptPKCS1v15(rand.Reader, priv, cipherText)
if err != nil {
return "", err
}
return string(result), nil
}
func TokenChecker() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("OCBO-Token")
start := strings.Index(token, "ocbo=") + len("ocbo=")
end := strings.LastIndex(token, "token")
if token == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "The request is missing an OCBO Token"})
c.Abort()
return
}
if start == -1 || end == -1 || start >= end {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid OCBO Token format"})
c.Abort()
return
}
extractedToken := token[start:end]
extractedToken = strings.ReplaceAll(extractedToken, "~", "/")
decrypted, err := decrypt(extractedToken)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid OCBO Token Value"})
c.Abort()
return
}
parts := strings.Split(decrypted, "-")
partCount := len(parts)
var finalRequest int
var finalExpiration int
if partCount == 4 {
requested := parts[2]
requestedNum, _ := strconv.Atoi(requested)
finalRequest = requestedNum
expiration := parts[3]
expirationNum, _ := strconv.Atoi(expiration)
finalExpiration = expirationNum
} else {
requested := parts[3]
requestedNum, _ := strconv.Atoi(requested)
finalRequest = requestedNum
expiration := parts[4]
expirationNum, _ := strconv.Atoi(expiration)
finalExpiration = expirationNum
}
unix := strconv.FormatInt(time.Now().UTC().Unix(), 10)
unixNum, _ := strconv.Atoi(unix)
if finalRequest > finalExpiration {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid OCBO Token Value"})
c.Abort()
return
}
if unixNum > finalExpiration {
c.JSON(http.StatusUnauthorized, gin.H{"error": "OCBO Token Expired"})
c.Abort()
return
}
c.Next()
}
}