trydis / FIFA-Ultimate-Team-Toolkit

FIFA Ultimate Team Toolkit
MIT License
231 stars 111 forks source link

New ut/auth #420

Open m-jacob opened 3 years ago

m-jacob commented 3 years ago

I'm updating this project for FIFA 22. I've updated a lot of things already, but last thing for the auth having problem(

For the ut/auth we have new payload { "isReadOnly": false, "sku": "FUT22WEB", "clientVersion": 1, "locale": "en-US", "method": "authcode", "priorityLevel": 4, "identification": { "authCode": "QUOwAD9I1Fx0vbFLAZid3I59dRdfsJ2WspUp8W0wAQ", "redirectUrl": "nucleus:rest" }, "nucleusPersonaId": myId, "gameSku": "FFA22PS4", "ds": "aa9eb50afbea60f4efe7daf703c20c679fc5c6df89ac967915d9e81bc4f27b77/dbd8" }

You can see new parameter like - ds. I assume that dataSource, but I'm not sure. Also I don't know how to create value for the ds. Every time it's new value. Also js file is obfuscated from EA.

Does someone have ideas what is it? Let me know if you are working on this project, please. My discord : jacob#6151

marlonespindola commented 2 years ago

@m-jacob do you have any tips on how to use fiddler to get the requests from web app?? I cannot get the requests

pawanluodi commented 7 months ago

hello,I am also facing the same problem. Have you resolved it?

tringler commented 3 months ago

Sorry for the delay 😄 I reworked it for FUT24 (and .NET8) in a branch, but I also didn't find a way to craft the "ds": value.

DjTrilogic commented 3 months ago

I was able to compute the ds back in FUT 21, using a weird method:

I'll post the code when I find it back.

tringler commented 3 months ago

@DjTrilogic How you find out by Selenium which javascript is responsible in order to compute it?

DjTrilogic commented 3 months ago

using Microsoft.Extensions.Options;
using Octofut.SDK.UltimateTeam.Constants;
using Octofut.SDK.UltimateTeam.Services;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.Extensions;
using Serilog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Octofut.SDK.UltimateTeam.DigitalSignatureProvider
{
    public class DigitalSignatureProvider : IDigitalSignatureProvider, IDisposable
    {
        // the magic string is computed by the function inside services['authentication'] (it can be isolated from the code)
        //private const string MagicString = "JzGpKhsbYC0GPpan9EfNYxWgTQJ9YZEZl7zd8Rv2CdiiYUKjk0c3q6k4qnUoxolW"; // 2020
        private const string MagicString = "8J2PS6X4wwtyWpoXCz5BrUv74mFNlG67pk1CNicz2IaBOhbBZsjzLdjITH6wYK2y"; // 2021
        private const string ChromeDriverVersion = "86.0.4240.22";

        private bool isReady = false;
        private bool errored = false;
        private ChromeDriver driver;
        private readonly string driverLocation;

        public DigitalSignatureProvider(IOptions<ChromeDriverSettings> driverSettings)
        {
            this.driverLocation = driverSettings.Value?.DriverPath ?? $@"F:\hosting\chrome-drivers\{ChromeDriverVersion}";
        }

        public void Initialize()
        {
            try
            {
                Log.Information("Initializing the DigitalSignatureProvider...");
                var options = new ChromeOptions();
                options.AddArguments("start-maximized");
                options.AddArguments("headless");
                options.AddArgument($"--user-agent={Resources.UserAgent}");
                driver = new ChromeDriver(driverLocation, options);
                driver.Navigate().GoToUrl(Resources.WebAppLink);
                driver.WaitForElementPresent(By.ClassName("ut-login-content"), 30);
                isReady = true;
            }
            catch (Exception e)
            {
                Log.Error(e, "Failed to initialize the DigitalSignatureProvider");
                var screenShot = driver.TakeScreenshot();
                var failuresFolder = Path.Join(this.driverLocation, "failures");
                if (!Directory.Exists(failuresFolder))
                {
                    Directory.CreateDirectory(failuresFolder);
                }
                screenShot.SaveAsFile(Path.Join(failuresFolder, $"{Guid.NewGuid()}.png"));
                errored = true;
            }
        }

        public string Compute(string authCode, string sku, string custom)
        {
            if (driver == null || errored || !isReady)
            {
                throw new InvalidOperationException("The 'ds' provider is not ready");
            }
            var toHash = "{\"authCode\":\"" + authCode + "\"}, {\"sku\":\"" + sku + "\"}, {\"custom\":\"" + custom + "\"}";
            var response = ((IJavaScriptExecutor)driver).ExecuteScript($"return utils['eval']['get']('{toHash}','{MagicString}');");
            if (response == null || !(response is IReadOnlyCollection<object> parts) || parts.Count != 2)
            {
                throw new InvalidOperationException("Unable to compute the 'ds' parameter [1]");
            }

            var lParts = parts.ToArray();
            if (!(lParts[0] is string hash) || !(lParts[1] is long crc))
            {
                throw new InvalidOperationException("Unable to compute the 'ds' parameter [2]");
            }

            return $"{hash}/{Convert.ToString(crc, 16)}";
        }

        public void Dispose()
        {
            driver?.Dispose();
        }
    }
}

I had to find the magic string from the js, i don't remember the exact method, but it should not be difficult