public static OAuth2InitialAccessToken NewToken(string loginServerId)
        {
            ParsingHelper.ServerDetails?loginServerDetails = ParsingHelper.ExtractServerDetailsFromAccountServerId(loginServerId);
            if (loginServerDetails == null)
            {
                throw new Exception();
            }

            OAuth2InitialAccessToken result = new OAuth2InitialAccessToken()
            {
                _loginServerDetails = loginServerDetails.Value,
                _id         = null,
                _softwareId = null,
                _accountId  = null,
                _timeUpdatedInUnixMicroseconds = null,
                _isCached = false,
            };

            return(result);
        }
        public static async Task <OAuth2InitialAccessToken> LoadInitialAccessTokenAsync(string tokenId, LoadTokenOptions options)
        {
            if ((options & LoadTokenOptions.LocalTokens) == LoadTokenOptions.LocalTokens)
            {
                if (_redisClient == null)
                {
                    _redisClient = await Singletons.GetRedisClientAsync();
                }

                string fullyQualifiedTokenKey = REDIS_PREFIX_OAUTH2_TOKEN + REDIS_PREFIX_SEPARATOR + tokenId;
                bool   localTokenExists       = (await _redisClient.ExistsAsync(new string[] { fullyQualifiedTokenKey }) > 0);
                if (localTokenExists)
                {
                    Dictionary <string, string> tokenDictionary = await _redisClient.HashGetAllASync <string, string, string>(fullyQualifiedTokenKey);

                    string tokenType = tokenDictionary.ContainsKey("type") ? tokenDictionary["type"] : null;
                    if (tokenType == null || tokenType != TOKEN_TYPE_INITIAL_ACCESS_TOKEN)
                    {
                        return(null);
                    }

                    string tokenIsCachedAsString = tokenDictionary.ContainsKey("cached") ? tokenDictionary["cached"] : null;
                    bool   tokenIsCached         = (tokenIsCachedAsString != null && tokenIsCachedAsString != "0");

                    string timeCreatedAsString           = tokenDictionary.ContainsKey("time-created") ? tokenDictionary["time-created"] : null;
                    Int64? timeCreatedInUnixMicroseconds = null;
                    Int64  timeCreatedAsInt64;
                    if (timeCreatedAsString != null && Int64.TryParse(timeCreatedAsString, out timeCreatedAsInt64))
                    {
                        timeCreatedInUnixMicroseconds = timeCreatedAsInt64;
                    }

                    string timeUpdatedAsString           = tokenDictionary.ContainsKey("time-updated") ? tokenDictionary["time-updated"] : null;
                    Int64? timeUpdatedInUnixMicroseconds = null;
                    Int64  timeUpdatedAsInt64;
                    if (timeUpdatedAsString != null && Int64.TryParse(timeUpdatedAsString, out timeUpdatedAsInt64))
                    {
                        timeUpdatedInUnixMicroseconds = timeUpdatedAsInt64;
                    }

                    OAuth2InitialAccessToken resultToken = new OAuth2InitialAccessToken();
                    resultToken._softwareId = tokenDictionary.ContainsKey("software-id") ? tokenDictionary["software-id"] : null;
                    if (resultToken._softwareId == null)
                    {
                        return(null);
                    }
                    resultToken._accountId = tokenDictionary.ContainsKey("account-id") ? tokenDictionary["account-id"] : null;

                    // if our result token could be loaded, populate the default fields common to all OAuth2Tokens.
                    resultToken._id = tokenId;
                    ParsingHelper.ServerDetails?loginServerDetails = ParsingHelper.ExtractServerDetailsFromAccountServerIdIdentifier(tokenId);
                    if (loginServerDetails == null)
                    {
                        throw new Exception();
                    }
                    resultToken._loginServerDetails            = loginServerDetails.Value;
                    resultToken._isCached                      = tokenIsCached;
                    resultToken._timeCreatedInUnixMicroseconds = timeCreatedInUnixMicroseconds;
                    resultToken._timeUpdatedInUnixMicroseconds = timeUpdatedInUnixMicroseconds;

                    return(resultToken);
                }
            }

            // valid token could not be found
            return(null);
        }