117 lines
2.6 KiB
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()
|
|
}
|
|
}
|