diff --git a/aid/token.go b/aid/token.go
index 9454b60..a69d3a7 100644
--- a/aid/token.go
+++ b/aid/token.go
@@ -2,10 +2,13 @@ package aid
import (
"fmt"
+ "regexp"
"github.com/golang-jwt/jwt/v5"
)
+var JWTCompile = regexp.MustCompile(`eg1~(.*)`)
+
func JWTSign(m JSON) (string, error) {
claims := jwt.MapClaims{}
@@ -18,6 +21,11 @@ func JWTSign(m JSON) (string, error) {
}
func JWTVerify(tokenString string) (JSON, error) {
+ compiled := JWTCompile.FindStringSubmatch(tokenString)
+ if len(compiled) > 0 {
+ tokenString = compiled[1]
+ }
+
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(Config.JWT.Secret), nil
})
@@ -41,4 +49,22 @@ func JWTVerify(tokenString string) (JSON, error) {
}
return json, nil
+}
+
+func GetSnowFromToken(token string) (string, error) {
+ claims, err := JWTVerify(token)
+ if err != nil {
+ return "", err
+ }
+
+ if claims["snow_id"] == nil {
+ return "", fmt.Errorf("invalid access token")
+ }
+
+ snowId, ok := claims["snow_id"].(string)
+ if !ok {
+ return "", fmt.Errorf("invalid access token")
+ }
+
+ return snowId, nil
}
\ No newline at end of file
diff --git a/go.mod b/go.mod
index bed7af3..90c8f74 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module github.com/ectrc/snow
go 1.21.3
require (
+ github.com/beevik/etree v1.3.0
github.com/bwmarrin/discordgo v0.27.1
github.com/goccy/go-json v0.10.2
github.com/gofiber/contrib/websocket v1.3.0
diff --git a/go.sum b/go.sum
index 9c410d2..4d8a81e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/beevik/etree v1.3.0 h1:hQTc+pylzIKDb23yYprodCWWTt+ojFfUZyzU09a/hmU=
+github.com/beevik/etree v1.3.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
diff --git a/handlers/auth.go b/handlers/auth.go
index 1d6e6bb..cf5c5f5 100644
--- a/handlers/auth.go
+++ b/handlers/auth.go
@@ -177,26 +177,11 @@ func PostTokenPassword(c *fiber.Ctx, body *FortniteTokenBody) error {
}
func GetTokenVerify(c *fiber.Ctx) error {
- auth := c.Get("Authorization")
- if auth == "" {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
- }
- real := strings.ReplaceAll(auth, "bearer eg1~", "")
-
- claims, err := aid.JWTVerify(real)
+ snowId, err := aid.GetSnowFromToken(c.Get("Authorization"))
if err != nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
}
- if claims["snow_id"] == nil {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
- snowId, ok := claims["snow_id"].(string)
- if !ok {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
person := p.Find(snowId)
if person == nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
@@ -204,7 +189,7 @@ func GetTokenVerify(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).JSON(aid.JSON{
"app": "fortnite",
- "token": real,
+ "token": strings.ReplaceAll(c.Get("Authorization"), "bearer eg1~", ""),
"token_type": "bearer",
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
"expires_in": 86400,
@@ -226,26 +211,11 @@ func DeleteToken(c *fiber.Ctx) error {
}
func MiddlewareFortnite(c *fiber.Ctx) error {
- auth := c.Get("Authorization")
- if auth == "" {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
- }
- real := strings.ReplaceAll(auth, "bearer eg1~", "")
-
- claims, err := aid.JWTVerify(real)
+ snowId, err := aid.GetSnowFromToken(c.Get("Authorization"))
if err != nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
}
- if claims["snow_id"] == nil {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
- snowId, ok := claims["snow_id"].(string)
- if !ok {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
person := p.Find(snowId)
if person == nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
@@ -256,29 +226,11 @@ func MiddlewareFortnite(c *fiber.Ctx) error {
}
func MiddlewareWeb(c *fiber.Ctx) error {
- auth := c.Get("Authorization")
- if auth == "" {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
- }
-
- claims, err := aid.JWTVerify(auth)
+ snowId, err := aid.GetSnowFromToken(c.Get("Authorization"))
if err != nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
}
- if claims["snow_id"] == nil {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
- if claims["frontend"] == nil {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Claims"))
- }
-
- snowId, ok := claims["snow_id"].(string)
- if !ok {
- return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
- }
-
person := p.Find(snowId)
if person == nil {
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
diff --git a/socket/jabber.go b/socket/jabber.go
index 64a7eb5..9fb01e8 100644
--- a/socket/jabber.go
+++ b/socket/jabber.go
@@ -1,12 +1,94 @@
package socket
-import "github.com/ectrc/snow/aid"
+import (
+ "fmt"
+
+ "github.com/beevik/etree"
+ "github.com/ectrc/snow/aid"
+ "github.com/ectrc/snow/person"
+ "github.com/gofiber/contrib/websocket"
+)
+
+type JabberData struct {
+ JabberID string
+}
+
+var jabberHandlers = map[string]func(*Socket[JabberData], *etree.Document) error {
+ "open": jabberOpenHandler,
+ "iq": jabberIqRootHandler,
+}
func HandleNewJabberSocket(identifier string) {
- _, ok := JabberSockets.Get(identifier)
+ socket, ok := JabberSockets.Get(identifier)
if !ok {
return
}
+ defer JabberSockets.Delete(identifier)
- aid.Print("New jabber socket: " + identifier)
+ for {
+ _, message, failed := socket.Connection.ReadMessage()
+ if failed != nil {
+ break
+ }
+
+ aid.Print(string(message))
+
+ parsed := etree.NewDocument()
+ if err := parsed.ReadFromBytes(message); err != nil {
+ return
+ }
+
+ if handler, ok := jabberHandlers[parsed.Root().Tag]; ok {
+ if err := handler(socket, parsed); err != nil {
+ socket.Connection.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, err.Error()))
+ return
+ }
+ }
+ }
+}
+
+func jabberOpenHandler(socket *Socket[JabberData], parsed *etree.Document) error {
+ socket.Connection.WriteMessage(websocket.TextMessage, []byte(``))
+ socket.Connection.WriteMessage(websocket.TextMessage, []byte(``))
+
+ return nil
+}
+
+func jabberIqRootHandler(socket *Socket[JabberData], parsed *etree.Document) error {
+ redirect := map[string]func(*Socket[JabberData], *etree.Document) error {
+ "set": jabberIqSetHandler,
+ "get": jabberIqGetHandler,
+ }
+
+ if handler, ok := redirect[parsed.Root().SelectAttr("type").Value]; ok {
+ if err := handler(socket, parsed); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func jabberIqSetHandler(socket *Socket[JabberData], parsed *etree.Document) error {
+ snowId, err := aid.GetSnowFromToken(parsed.FindElement("/iq/query/password").Text())
+ if err != nil {
+ return err
+ }
+
+ person := person.Find(snowId)
+ if person == nil {
+ return fmt.Errorf("person not found")
+ }
+
+ socket.Data.JabberID = snowId + "@prod.ol.epicgames.com/" + parsed.FindElement("/iq/query/resource").Text()
+ socket.Person = person
+
+ socket.Connection.WriteMessage(websocket.TextMessage, []byte(``))
+ return nil
+}
+
+
+func jabberIqGetHandler(socket *Socket[JabberData], parsed *etree.Document) error {
+ socket.Connection.WriteMessage(websocket.TextMessage, []byte(``))
+ return nil
}
\ No newline at end of file
diff --git a/socket/socket.go b/socket/socket.go
index 6696f5d..989149f 100644
--- a/socket/socket.go
+++ b/socket/socket.go
@@ -7,34 +7,19 @@ import (
"github.com/google/uuid"
)
-type SocketType int
-
-var (
- SocketTypeJabber SocketType = 1
- SocketTypeMatchmaking SocketType = 2
-)
-
-type JabberData struct {
- JabberID string
-}
-
type MatchmakerData struct {
PlaylistID string
Region string
}
-type data interface {
- JabberData | MatchmakerData
-}
-
-type Socket[T data] struct {
+type Socket[T JabberData | MatchmakerData] struct {
ID string
Connection *websocket.Conn
Data *T
Person *person.Person
}
-func newSocket[T data](conn *websocket.Conn, data ...T) *Socket[T] {
+func newSocket[T JabberData | MatchmakerData](conn *websocket.Conn, data ...T) *Socket[T] {
additional := data[0]
return &Socket[T]{