2023-11-03 23:48:50 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ectrc/snow/aid"
|
|
|
|
p "github.com/ectrc/snow/person"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2023-12-09 15:35:33 +00:00
|
|
|
oauthTokenGrantTypes = map[string]func(c *fiber.Ctx, body *FortniteTokenBody) error{
|
2024-01-20 01:58:57 +00:00
|
|
|
"client_credentials": PostTokenClientCredentials, // spams the api?? like wtf
|
2023-12-09 15:35:33 +00:00
|
|
|
"password": PostTokenPassword,
|
2023-12-26 03:07:18 +00:00
|
|
|
"exchange_code": PostTokenExchangeCode,
|
2023-11-03 23:48:50 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2023-12-09 15:35:33 +00:00
|
|
|
type FortniteTokenBody struct {
|
2023-11-03 23:48:50 +00:00
|
|
|
GrantType string `form:"grant_type" binding:"required"`
|
2023-12-26 03:07:18 +00:00
|
|
|
ExchangeCode string `form:"exchange_code"`
|
2023-11-03 23:48:50 +00:00
|
|
|
Username string `form:"username"`
|
|
|
|
Password string `form:"password"`
|
2023-12-26 03:07:18 +00:00
|
|
|
TokenType string `form:"token_type"`
|
2023-11-03 23:48:50 +00:00
|
|
|
}
|
|
|
|
|
2023-12-09 15:35:33 +00:00
|
|
|
func PostFortniteToken(c *fiber.Ctx) error {
|
|
|
|
var body FortniteTokenBody
|
2023-11-03 23:48:50 +00:00
|
|
|
|
|
|
|
if err := c.BodyParser(&body); err != nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Request Body"))
|
|
|
|
}
|
|
|
|
|
2023-11-20 21:20:26 +00:00
|
|
|
if action, ok := oauthTokenGrantTypes[body.GrantType]; ok {
|
2023-11-03 23:48:50 +00:00
|
|
|
return action(c, &body)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Grant Type"))
|
|
|
|
}
|
|
|
|
|
2023-12-09 15:35:33 +00:00
|
|
|
func PostTokenClientCredentials(c *fiber.Ctx, body *FortniteTokenBody) error {
|
2023-11-03 23:48:50 +00:00
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
2024-01-20 01:58:57 +00:00
|
|
|
"access_token": "snow",
|
2023-11-03 23:48:50 +00:00
|
|
|
"token_type": "bearer",
|
2024-01-20 01:58:57 +00:00
|
|
|
"client_id": aid.Hash([]byte(c.IP())),
|
2023-12-16 22:08:37 +00:00
|
|
|
"client_service": "fortnite",
|
2023-11-03 23:48:50 +00:00
|
|
|
"internal_client": true,
|
|
|
|
"expires_in": 3600,
|
|
|
|
"expires_at": time.Now().Add(time.Hour).Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
func PostTokenExchangeCode(c *fiber.Ctx, body *FortniteTokenBody) error {
|
|
|
|
if body.ExchangeCode == "" {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Exchange Code is empty"))
|
|
|
|
}
|
|
|
|
|
|
|
|
codeParts := strings.Split(body.ExchangeCode, ".")
|
|
|
|
if len(codeParts) != 2 {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
code, failed := aid.KeyPair.DecryptAndVerifyB64(codeParts[0], codeParts[1])
|
|
|
|
if failed {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
personParts := strings.Split(string(code), "=")
|
|
|
|
if len(personParts) != 2 {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
personId := personParts[0]
|
|
|
|
expire, err := time.Parse("2006-01-02T15:04:05.999Z", personParts[1])
|
|
|
|
if err != nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if expire.Add(time.Hour).Before(time.Now()) {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
person := p.Find(personId)
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Exchange Code"))
|
|
|
|
}
|
|
|
|
|
|
|
|
access, err := aid.JWTSign(aid.JSON{
|
|
|
|
"snow_id": person.ID, // custom
|
|
|
|
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
|
|
|
}
|
|
|
|
|
|
|
|
refresh, err := aid.JWTSign(aid.JSON{
|
|
|
|
"snow_id": person.ID,
|
|
|
|
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
|
|
|
"access_token": "eg1~" + access,
|
|
|
|
"account_id": person.ID,
|
|
|
|
"client_id": c.IP(),
|
|
|
|
"client_service": "fortnite",
|
|
|
|
"app": "fortnite",
|
|
|
|
"device_id": "default",
|
|
|
|
"display_name": person.DisplayName,
|
|
|
|
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
"expires_in": 86400,
|
|
|
|
"internal_client": true,
|
|
|
|
"refresh_expires": 86400,
|
|
|
|
"refresh_expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
"refresh_token": "eg1~" + refresh,
|
|
|
|
"token_type": "bearer",
|
|
|
|
"product_id": "prod-fn",
|
|
|
|
"sandbox_id": "fn",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-09 15:35:33 +00:00
|
|
|
func PostTokenPassword(c *fiber.Ctx, body *FortniteTokenBody) error {
|
2023-11-03 23:48:50 +00:00
|
|
|
if body.Username == "" || body.Password == "" {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Username/Password is empty"))
|
|
|
|
}
|
|
|
|
|
|
|
|
person := p.FindByDisplay(strings.Split(body.Username, "@")[0])
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
|
|
|
}
|
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
access, err := aid.JWTSign(aid.JSON{
|
|
|
|
"snow_id": person.ID, // custom
|
|
|
|
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
2023-11-03 23:48:50 +00:00
|
|
|
}
|
2023-12-19 16:47:13 +00:00
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
refresh, err := aid.JWTSign(aid.JSON{
|
|
|
|
"snow_id": person.ID,
|
|
|
|
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
2023-11-03 23:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
2023-12-26 03:07:18 +00:00
|
|
|
"access_token": "eg1~" + access,
|
2023-11-03 23:48:50 +00:00
|
|
|
"account_id": person.ID,
|
|
|
|
"client_id": c.IP(),
|
2023-12-16 22:08:37 +00:00
|
|
|
"client_service": "fortnite",
|
|
|
|
"app": "fortnite",
|
2023-11-03 23:48:50 +00:00
|
|
|
"device_id": "default",
|
|
|
|
"display_name": person.DisplayName,
|
|
|
|
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
"expires_in": 86400,
|
|
|
|
"internal_client": true,
|
|
|
|
"refresh_expires": 86400,
|
|
|
|
"refresh_expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
2023-12-26 03:07:18 +00:00
|
|
|
"refresh_token": "eg1~" + refresh,
|
2023-11-03 23:48:50 +00:00
|
|
|
"token_type": "bearer",
|
2023-12-19 16:47:13 +00:00
|
|
|
"product_id": "prod-fn",
|
|
|
|
"sandbox_id": "fn",
|
2023-11-03 23:48:50 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-26 03:39:12 +00:00
|
|
|
func GetTokenVerify(c *fiber.Ctx) error {
|
2023-11-05 22:08:53 +00:00
|
|
|
auth := c.Get("Authorization")
|
|
|
|
if auth == "" {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
2023-12-26 03:07:18 +00:00
|
|
|
real := strings.ReplaceAll(auth, "bearer eg1~", "")
|
|
|
|
|
|
|
|
claims, err := aid.JWTVerify(real)
|
|
|
|
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"))
|
|
|
|
}
|
2023-11-05 22:08:53 +00:00
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
snowId, ok := claims["snow_id"].(string)
|
|
|
|
if !ok {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
person := p.Find(snowId)
|
|
|
|
if person == nil {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
|
|
|
|
2023-11-09 18:53:19 +00:00
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
|
|
|
"app": "fortnite",
|
2023-12-19 16:47:13 +00:00
|
|
|
"token": real,
|
2023-11-09 18:53:19 +00:00
|
|
|
"token_type": "bearer",
|
|
|
|
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
|
|
|
"expires_in": 86400,
|
|
|
|
"client_id": c.IP(),
|
|
|
|
"session_id": "0",
|
|
|
|
"device_id": "default",
|
|
|
|
"internal_client": true,
|
2023-12-16 22:08:37 +00:00
|
|
|
"client_service": "fortnite",
|
2023-11-09 18:53:19 +00:00
|
|
|
"in_app_id": person.ID,
|
|
|
|
"account_id": person.ID,
|
|
|
|
"displayName": person.DisplayName,
|
2023-12-19 16:47:13 +00:00
|
|
|
"product_id": "prod-fn",
|
|
|
|
"sandbox_id": "fn",
|
2023-11-09 18:53:19 +00:00
|
|
|
})
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
|
|
|
|
2023-12-26 03:39:12 +00:00
|
|
|
func DeleteToken(c *fiber.Ctx) error {
|
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{})
|
|
|
|
}
|
|
|
|
|
2023-12-19 21:48:01 +00:00
|
|
|
func MiddlewareFortnite(c *fiber.Ctx) error {
|
2023-11-05 22:08:53 +00:00
|
|
|
auth := c.Get("Authorization")
|
|
|
|
if auth == "" {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
2023-12-26 03:07:18 +00:00
|
|
|
real := strings.ReplaceAll(auth, "bearer eg1~", "")
|
2023-11-05 22:08:53 +00:00
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
claims, err := aid.JWTVerify(real)
|
|
|
|
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 {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
person := p.Find(snowId)
|
|
|
|
if person == nil {
|
2023-11-09 18:42:28 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
2023-11-05 22:08:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c.Locals("person", person)
|
2023-12-09 15:35:33 +00:00
|
|
|
return c.Next()
|
|
|
|
}
|
|
|
|
|
2023-12-19 21:48:01 +00:00
|
|
|
func MiddlewareWeb(c *fiber.Ctx) error {
|
2023-12-09 15:35:33 +00:00
|
|
|
auth := c.Get("Authorization")
|
|
|
|
if auth == "" {
|
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Authorization Header is empty"))
|
|
|
|
}
|
|
|
|
|
2023-12-26 03:07:18 +00:00
|
|
|
claims, err := aid.JWTVerify(auth)
|
|
|
|
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 {
|
2023-12-09 15:35:33 +00:00
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
|
|
|
}
|
2023-11-05 22:08:53 +00:00
|
|
|
|
2023-12-09 15:35:33 +00:00
|
|
|
person := p.Find(snowId)
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusForbidden).JSON(aid.ErrorBadRequest("Invalid Access Token"))
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Locals("person", person)
|
2023-11-05 22:08:53 +00:00
|
|
|
return c.Next()
|
|
|
|
}
|
|
|
|
|
2023-11-03 23:48:50 +00:00
|
|
|
func GetPublicAccount(c *fiber.Ctx) error {
|
|
|
|
person := p.Find(c.Params("accountId"))
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
|
|
|
"id": person.ID,
|
|
|
|
"displayName": person.DisplayName,
|
2023-11-09 18:42:28 +00:00
|
|
|
"externalAuths": []aid.JSON{},
|
2023-11-03 23:48:50 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-11-09 18:42:28 +00:00
|
|
|
func GetPublicAccounts(c *fiber.Ctx) error {
|
|
|
|
response := []aid.JSON{}
|
|
|
|
|
|
|
|
accountIds := c.Request().URI().QueryArgs().PeekMulti("accountId")
|
|
|
|
for _, accountIdSlice := range accountIds {
|
|
|
|
person := p.Find(string(accountIdSlice))
|
|
|
|
if person == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
response = append(response, aid.JSON{
|
|
|
|
"id": person.ID,
|
|
|
|
"displayName": person.DisplayName,
|
|
|
|
"externalAuths": []aid.JSON{},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON(response)
|
|
|
|
}
|
|
|
|
|
2023-11-03 23:48:50 +00:00
|
|
|
func GetPublicAccountExternalAuths(c *fiber.Ctx) error {
|
|
|
|
person := p.Find(c.Params("accountId"))
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON([]aid.JSON{})
|
2023-11-09 18:42:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetPublicAccountByDisplayName(c *fiber.Ctx) error {
|
|
|
|
person := p.FindByDisplay(c.Params("displayName"))
|
|
|
|
if person == nil {
|
|
|
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
|
|
|
"id": person.ID,
|
|
|
|
"displayName": person.DisplayName,
|
|
|
|
"externalAuths": []aid.JSON{},
|
|
|
|
})
|
2023-11-03 23:48:50 +00:00
|
|
|
}
|