Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Creating a Dragon6Client

Albie edited this page Aug 5, 2020 · 1 revision

Overview

Ubisoft uses a JWT-based ticket system as an access code for accessing user information. These are time limited to something like 2 hours so we need a system to get them when they have expired.

We can get a token with the d6Client.GetUbiToken(username, password) extension. Because the Dragon6Client depends on this to get the stats and people might have different methods for storing the token (redis, memory, file, etc.), we've made the Dragon6Client abstract, allowing you to inherit it into your own version (could be named StatsClient) with a function that accepts the token (see below for an example).

Notes

  • The login must be a Ubisoft Club login, usually with the email address as the username. Social logins probably won't work for this
  • 2FA may or may not interfere with this: YMMV
  • This ticket is now passed as the authentication header instead of the email and password in the form: Ubi_v1 t={Ticket} for any future requests. The token variable in Dragon6 functions represents the Ticket string.
  • You can create a second Ubisoft Account and use that, even if it doesn't have a copy of the game registered to it
  • They Expire: Please cache the token and don't generate too many in a short time - your account will become locked and every time you request a key, the account's cooldown will be reset. They last approx. 2 hours, so you should be good.

Example

This code is an example of an inheritance of the Dragon6Client class, with a method for getting and setting a token using a file-backed serivce.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using DragonFruit.Common.Data.Services;
using DragonFruit.Six.API;
using DragonFruit.Six.API.Data;
using DragonFruit.Six.API.Data.Tokens;
using DragonFruit.Six.API.Extensions;

namespace DragonFruit.Six.Web.Services
{
    public class StatsClient : Dragon6Client
    {
        // change this to whatever you want
        private readonly string _tokenFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DragonFruit Network", "ubi.token");
        
        public StatsClient()
        {
            Directory.CreateDirectory(Path.GetDirectoryName(_tokenFile));
        }

        /// <summary>
        /// Tells the Dragon6 Client how to get a token in the case it's restarted or expired
        /// </summary>
        protected override TokenBase GetToken()
        {
            if (File.Exists(_tokenFile))
            {
                // if we have a file with some potentially valid keys, try that first
                var token = FileServices.ReadFile<UbisoftToken>(_tokenFile);

                if (!token.Expired)
                    return token;
            }

            // store logins somewhere that is NOT in the code (this will lookup ubi_user and ubi_password in the user env vars on windows)
            var username = Environment.GetEnvironmentVariable("ubi_user", EnvironmentVariableTarget.User);
            var password = Environment.GetEnvironmentVariable("ubi_password", EnvironmentVariableTarget.User);
            var newToken = this.GetUbiToken(username, password);

            // write new token to disk async (non-blocking)
            _ = Task.Run(() => FileServices.WriteFile(_tokenFile, newToken));
            
            // return to keep going
            return newToken;
        }
    }
}