public AuthenticationService(UriString host, IKeychain keychain,
                              IProcessManager processManager, ITaskManager taskManager,
                              IEnvironment environment
                              )
 {
     client = new ApiClient(keychain, processManager, taskManager, environment, host);
 }
Пример #2
0
        public GitHubCredentialProvider(IKeychain keychain, [Import(AllowDefault = true)] JoinableTaskContext joinableTaskContext)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));

            this.keychain       = keychain;
            JoinableTaskContext = joinableTaskContext ?? ThreadHelper.JoinableTaskContext;
        }
Пример #3
0
        public OctorunTask(CancellationToken token, IKeychain keychain, IEnvironment environment,
                           string arguments,
                           IOutputProcessor <OctorunResult> processor = null)
            : base(token, processor ?? new OctorunResultOutputProcessor())
        {
            this.clientId        = ApplicationInfo.ClientId;
            this.clientSecret    = ApplicationInfo.ClientSecret;
            this.pathToNodeJs    = environment.NodeJsExecutablePath;
            this.pathToOctorunJs = environment.OctorunScriptPath;
            this.arguments       = $"\"{pathToOctorunJs}\" {arguments}";

            var cloneUrl = environment.Repository?.CloneUrl;
            var host     = String.IsNullOrEmpty(cloneUrl)
                ? UriString.ToUriString(HostAddress.GitHubDotComHostAddress.WebUri)
                : new UriString(cloneUrl.ToRepositoryUri()
                                .GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));

            var adapter = keychain.Connect(host);

            if (adapter.Credential?.Token != null)
            {
                userToken = adapter.Credential.Token;
            }
            else
            {
                // use a cached adapter if there is one filled out
                adapter = keychain.LoadFromSystem(host);
                if (adapter != null)
                {
                    userToken = adapter.Credential.Token;
                }
            }
        }
Пример #4
0
 public SessionFactory(AbstractLogger logger, ICoroutineManager coroutineManager, IStopwatch pollCountdownStopwatch, IEpochTime epochTime, DatabaseCorruptionHandler databaseCorruptionHandler, INotificationQueue notificationQueue, INotificationDispatcher notificationDispatcher, ISessionStatus sessionStatus, IMixWebCallFactoryFactory mixWebCallFactoryFactory, IWebCallEncryptorFactory webCallEncryptorFactory, IMixSessionStarter mixSessionStarter, IKeychain keychain, ISessionRefresherFactory sessionRefresherFactory, IGuestControllerClientFactory guestControllerClientFactory, IRandom random, IEncryptor encryptor, IFileSystem fileSystem, IWwwCallFactory wwwCallFactory, string localStorageDirPath, string clientVersion, IDatabaseDirectoryCreator databaseDirectoryCreator, IDocumentCollectionFactory documentCollectionFactory, IDatabase database)
 {
     this.logger                       = logger;
     this.coroutineManager             = coroutineManager;
     this.pollCountdownStopwatch       = pollCountdownStopwatch;
     this.epochTime                    = epochTime;
     this.databaseCorruptionHandler    = databaseCorruptionHandler;
     this.notificationQueue            = notificationQueue;
     this.notificationDispatcher       = notificationDispatcher;
     this.sessionStatus                = sessionStatus;
     this.mixWebCallFactoryFactory     = mixWebCallFactoryFactory;
     this.webCallEncryptorFactory      = webCallEncryptorFactory;
     this.mixSessionStarter            = mixSessionStarter;
     this.keychain                     = keychain;
     this.sessionRefresherFactory      = sessionRefresherFactory;
     this.guestControllerClientFactory = guestControllerClientFactory;
     this.random                       = random;
     this.encryptor                    = encryptor;
     this.fileSystem                   = fileSystem;
     this.wwwCallFactory               = wwwCallFactory;
     this.localStorageDirPath          = localStorageDirPath;
     this.clientVersion                = clientVersion;
     this.databaseDirectoryCreator     = databaseDirectoryCreator;
     this.documentCollectionFactory    = documentCollectionFactory;
     this.database                     = database;
 }
Пример #5
0
 public Session(AbstractLogger logger, IInternalLocalUser localUser, string guestControllerAccessToken, bool pushNotificationsEnabled, INotificationPoller notificationPoller, ICoroutineManager coroutineManager, IDatabase database, IUserDatabase userDatabase, IGuestControllerClient guestControllerClient, IMixWebCallFactory mixWebCallFactory, IEpochTime epochTime, DatabaseCorruptionHandler databaseCorruptionHandler, ISessionStatus sessionStatus, IKeychain keychain, IGetStateResponseParser getStateResponseParser, string clientVersion, INotificationQueue notificationQueue)
 {
     this.logger                                     = logger;
     this.localUser                                  = localUser;
     this.notificationPoller                         = notificationPoller;
     this.coroutineManager                           = coroutineManager;
     this.database                                   = database;
     this.userDatabase                               = userDatabase;
     this.guestControllerClient                      = guestControllerClient;
     this.mixWebCallFactory                          = mixWebCallFactory;
     this.epochTime                                  = epochTime;
     this.databaseCorruptionHandler                  = databaseCorruptionHandler;
     this.sessionStatus                              = sessionStatus;
     this.keychain                                   = keychain;
     this.getStateResponseParser                     = getStateResponseParser;
     this.clientVersion                              = clientVersion;
     this.notificationQueue                          = notificationQueue;
     GuestControllerAccessToken                      = guestControllerAccessToken;
     guestControllerClient.OnAccessTokenChanged     += HandleGuestControllerAccessTokenChanged;
     guestControllerClient.OnAuthenticationLost     += HandleAuthenticationLost;
     mixWebCallFactory.OnAuthenticationLost         += HandleAuthenticationLost;
     localUser.OnPushNotificationsToggled           += HandlePushNotificationsToggled;
     localUser.OnPushNotificationReceived           += HandlePushNotificationReceived;
     localUser.OnDisplayNameUpdated                 += HandleDisplayNameUpdated;
     databaseCorruptionHandler.OnCorruptionDetected += HandleCorruptionDetected;
     updateEnumerator                                = Update();
     coroutineManager.Start(updateEnumerator);
     notificationPoller.OnNotificationsPolled += HandleNotificationsPolled;
     notificationPoller.UsePollIntervals       = !pushNotificationsEnabled;
     this.sessionStatus.IsPaused = true;
     notificationPoller.OnSynchronizationError += HandleNotificationPollerSynchronizationError;
 }
Пример #6
0
 public static void StoreSecret(
     this IKeychain keychain,
     string serviceName,
     string accountName,
     string secret,
     bool updateExisting = true)
 => keychain.StoreSecret(
Пример #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="keychain">The keychain in which to store credentials.</param>
        /// <param name="twoFactorChallengeHandler">The handler for 2FA challenges.</param>
        /// <param name="oauthListener">The callback listener to signal successful login.</param>
        /// <param name="clientId">The application's client API ID.</param>
        /// <param name="clientSecret">The application's client API secret.</param>
        /// <param name="minimumScopes">The minimum acceptable scopes.</param>
        /// <param name="requestedScopes">The scopes to request when logging in.</param>
        /// <param name="authorizationNote">An note to store with the authorization.</param>
        /// <param name="fingerprint">The machine fingerprint.</param>
        public LoginManager(
            IKeychain keychain,
            Lazy <ITwoFactorChallengeHandler> twoFactorChallengeHandler,
            IOAuthCallbackListener oauthListener,
            string clientId,
            string clientSecret,
            IReadOnlyList <string> minimumScopes,
            IReadOnlyList <string> requestedScopes,
            string authorizationNote = null,
            string fingerprint       = null)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNull(twoFactorChallengeHandler, nameof(twoFactorChallengeHandler));
            Guard.ArgumentNotEmptyString(clientId, nameof(clientId));
            Guard.ArgumentNotEmptyString(clientSecret, nameof(clientSecret));

            this.keychain = keychain;
            this.twoFactorChallengeHandler = twoFactorChallengeHandler;
            this.oauthListener             = oauthListener;
            this.clientId          = clientId;
            this.clientSecret      = clientSecret;
            this.minimumScopes     = minimumScopes;
            this.requestedScopes   = requestedScopes;
            this.authorizationNote = authorizationNote;
            this.fingerprint       = fingerprint;
        }
Пример #8
0
        public static IApiClient Create(UriString repositoryUrl, IKeychain keychain)
        {
            var credentialStore = keychain.Connect(repositoryUrl);
            var hostAddress     = HostAddress.Create(repositoryUrl);

            return(new ApiClient(repositoryUrl, keychain,
                                 new GitHubClient(AppConfiguration.ProductHeader, credentialStore, hostAddress.ApiUri)));
        }
        public GraphQLKeychainCredentialStore(IKeychain keychain, HostAddress address)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNull(address, nameof(keychain));

            this.keychain = keychain;
            this.address  = address;
        }
Пример #10
0
        private void initCPKeyValueDatabase(IKeychain keychainData)
        {
            string localStorageDirPath = Path.Combine(Application.persistentDataPath, "KeyValueDatabase");

            byte[] localStorageKey = keychainData.LocalStorageKey;
            DocumentCollectionFactory documentCollectionFactory = new DocumentCollectionFactory();

            CPKeyValueDatabase = new CPKeyValueDatabase(localStorageKey, localStorageDirPath, documentCollectionFactory);
        }
Пример #11
0
        public static IApiClient Create(UriString repositoryUrl, IKeychain keychain, IProcessManager processManager, ITaskManager taskManager, NPath nodeJsExecutablePath, NPath octorunScriptPath)
        {
            logger.Trace("Creating ApiClient: {0}", repositoryUrl);

            var credentialStore = keychain.Connect(repositoryUrl);
            var hostAddress     = HostAddress.Create(repositoryUrl);

            return(new ApiClient(repositoryUrl, keychain,
                                 processManager, taskManager, nodeJsExecutablePath, octorunScriptPath));
        }
Пример #12
0
 public SimpleApiClientFactory(
     IProgram program,
     IKeychain keychain,
     Lazy <IEnterpriseProbe> enterpriseProbe,
     Lazy <IWikiProbe> wikiProbe)
 {
     this.keychain       = keychain;
     productHeader       = program.ProductHeader;
     lazyEnterpriseProbe = enterpriseProbe;
     lazyWikiProbe       = wikiProbe;
 }
Пример #13
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="keychain"></param>
        /// <param name="processManager"></param>
        /// <param name="taskManager"></param>
        /// <param name="nodeJsExecutablePath"></param>
        /// <param name="octorunScript"></param>
        public LoginManager(
            IKeychain keychain, IProcessManager processManager, ITaskManager taskManager,
            IEnvironment environment)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));

            this.keychain       = keychain;
            this.processManager = processManager;
            this.taskManager    = taskManager;
            this.environment    = environment;
        }
Пример #14
0
        public GraphQLClientFactory(IKeychain keychain, IProgram program)
        {
            this.keychain = keychain;
            this.program  = program;

            var cachePath = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                ApplicationInfo.ApplicationName,
                "GraphQLCache");

            cache = new FileCache(cachePath);
        }
Пример #15
0
		public MixSessionStarter(AbstractLogger logger, IRsaEncryptor rsaEncryptor, IDatabase database, IWebCallEncryptorFactory webCallEncryptorFactory, IWebCallEncryptor sessionStartEncryptor, IMixWebCallFactoryFactory mixWebCallFactoryFactory, IKeychain keychain, ICoroutineManager coroutineManager, ISessionRefresherFactory sessionRefresherFactory)
		{
			this.logger = logger;
			this.rsaEncryptor = rsaEncryptor;
			this.database = database;
			this.webCallEncryptorFactory = webCallEncryptorFactory;
			this.sessionStartEncryptor = sessionStartEncryptor;
			this.mixWebCallFactoryFactory = mixWebCallFactoryFactory;
			this.keychain = keychain;
			this.coroutineManager = coroutineManager;
			this.sessionRefresherFactory = sessionRefresherFactory;
		}
Пример #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="keychain"></param>
        /// <param name="processManager"></param>
        /// <param name="taskManager"></param>
        /// <param name="nodeJsExecutablePath"></param>
        /// <param name="octorunScript"></param>
        public LoginManager(
            IKeychain keychain, IProcessManager processManager = null, ITaskManager taskManager = null,
            NPath?nodeJsExecutablePath = null, NPath?octorunScript = null)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));

            this.keychain             = keychain;
            this.processManager       = processManager;
            this.taskManager          = taskManager;
            this.nodeJsExecutablePath = nodeJsExecutablePath;
            this.octorunScript        = octorunScript;
        }
Пример #17
0
        public ApiClient(UriString hostUrl, IKeychain keychain, IGitHubClient githubClient)
        {
            Guard.ArgumentNotNull(hostUrl, nameof(hostUrl));
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNull(githubClient, nameof(githubClient));

            HostAddress       = HostAddress.Create(hostUrl);
            OriginalUrl       = hostUrl;
            this.keychain     = keychain;
            this.githubClient = githubClient;
            loginManager      = new LoginManager(keychain, ApplicationInfo.ClientId, ApplicationInfo.ClientSecret);
        }
Пример #18
0
        public ApiClient(UriString hostUrl, IKeychain keychain, IProcessManager processManager, ITaskManager taskManager, NPath nodeJsExecutablePath, NPath octorunScriptPath)
        {
            Guard.ArgumentNotNull(hostUrl, nameof(hostUrl));
            Guard.ArgumentNotNull(keychain, nameof(keychain));

            HostAddress               = HostAddress.Create(hostUrl);
            OriginalUrl               = hostUrl;
            this.keychain             = keychain;
            this.processManager       = processManager;
            this.taskManager          = taskManager;
            this.nodeJsExecutablePath = nodeJsExecutablePath;
            this.octorunScriptPath    = octorunScriptPath;
            loginManager              = new LoginManager(keychain, processManager, taskManager, nodeJsExecutablePath, octorunScriptPath);
        }
Пример #19
0
		public MixLoginCreateService()
		{
			keychainData = Service.Get<IKeychain>();
			sessionStarter = new SessionStarter();
			coroutineManager = new MixCoroutineManager();
			logger = new MixLogger();
			localizer = Service.Get<Localizer>();
			Localizer obj = localizer;
			obj.TokensUpdated = (Localizer.TokensUpdatedDelegate)Delegate.Combine(obj.TokensUpdated, new Localizer.TokensUpdatedDelegate(onLanguageChanged));
			overrideCountryCode = new DevCacheableType<string>("mix.OverrideCountryCode", "");
			spoofedGeoIp = new DevCacheableType<string>("mix.SpoofedGeoIP", null);
			Service.Get<ICommonGameSettings>().RegisterSetting(overrideCountryCode, canBeReset: true);
			Service.Get<ICommonGameSettings>().RegisterSetting(spoofedGeoIp, canBeReset: true);
		}
Пример #20
0
 public UsageTracker(ITaskManager taskManager, IGitClient gitClient, IProcessManager processManager,
                     ISettings userSettings,
                     IEnvironment environment,
                     IKeychain keychain,
                     string instanceId)
     : base(userSettings,
            new UsageLoader(environment.UserCachePath.Combine(Constants.UsageFile)),
            environment.UnityVersion, instanceId)
 {
     TaskManager    = taskManager;
     Environment    = environment;
     GitClient      = gitClient;
     ProcessManager = processManager;
     Keychain       = keychain;
 }
Пример #21
0
        public static bool TryGetSecret(
            this IKeychain keychain,
            string serviceName,
            string accountName,
            out string secret)
        {
            if (keychain.TryGetSecret(((serviceName, accountName)), out var fullSecret))
            {
                secret = fullSecret.GetUtf8StringValue();
                return(true);
            }

            secret = null;
            return(false);
        }
Пример #22
0
 public OSKeychain()
 {
     if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
     {
         keychain = new AppleKeychain();
     }
     else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
     {
         keychain = new DPAPIKeychain();
     }
     else
     {
         keychain = new ManagedProtectionKeychain();
     }
 }
Пример #23
0
        public static bool TryGetSecretBytes(
            this IKeychain keychain,
            string serviceName,
            string accountName,
            out byte [] secret)
        {
            if (keychain.TryGetSecret(((serviceName, accountName)), out var fullSecret))
            {
                secret = (byte [])fullSecret.Value;
                return(true);
            }

            secret = null;
            return(false);
        }
Пример #24
0
        public NewAccountValidator(IKeychain keychain, AbstractLogger logger, string localStorageDirPath, string guestControllerHostUrl, string guestControllerSpoofedIpAddress, string oneIdClientId, ICoroutineManager coroutineManager)
        {
            this.logger = logger;
            SystemStopwatchFactory    stopwatchFactory          = new SystemStopwatchFactory();
            SystemWwwFactory          wwwFactory                = new SystemWwwFactory();
            WwwCallFactory            wwwCallFactory            = new WwwCallFactory(logger, coroutineManager, stopwatchFactory, wwwFactory);
            FileSystem                fileSystem                = new FileSystem();
            DatabaseDirectoryCreator  directoryCreator          = new DatabaseDirectoryCreator(fileSystem, localStorageDirPath);
            DocumentCollectionFactory documentCollectionFactory = new DocumentCollectionFactory();
            SystemRandom              random = new SystemRandom();
            DatabaseCorruptionHandler databaseCorruptionHandler = new DatabaseCorruptionHandler(logger, fileSystem, localStorageDirPath);
            SystemEpochTime           epochTime = new SystemEpochTime();
            Database database = new Database(keychain.LocalStorageKey, random, epochTime, directoryCreator, documentCollectionFactory, databaseCorruptionHandler);

            guestControllerClient = new GuestControllerClient(wwwCallFactory, guestControllerSpoofedIpAddress, database, string.Empty, guestControllerHostUrl, oneIdClientId, logger);
        }
    public NonRegisteredTransactorUpgradeSender(IKeychain keychain, AbstractLogger logger, string localStorageDirPath, string guestControllerHostUrl, string guestControllerSpoofedIpAddress, string oneIdClientId, ICoroutineManager coroutineManager)
    {
        SystemStopwatchFactory    stopwatchFactory          = new SystemStopwatchFactory();
        SystemWwwFactory          wwwFactory                = new SystemWwwFactory();
        WwwCallFactory            wwwCallFactory            = new WwwCallFactory(logger, coroutineManager, stopwatchFactory, wwwFactory);
        FileSystem                fileSystem                = new FileSystem();
        DatabaseDirectoryCreator  directoryCreator          = new DatabaseDirectoryCreator(fileSystem, localStorageDirPath);
        DocumentCollectionFactory documentCollectionFactory = new DocumentCollectionFactory();
        SystemRandom              random = new SystemRandom();
        DatabaseCorruptionHandler databaseCorruptionHandler = new DatabaseCorruptionHandler(logger, fileSystem, localStorageDirPath);
        SystemEpochTime           epochTime = new SystemEpochTime();
        Database database = new Database(keychain.LocalStorageKey, random, epochTime, directoryCreator, documentCollectionFactory, databaseCorruptionHandler);
        GuestControllerClient guestControllerClient = new GuestControllerClient(wwwCallFactory, guestControllerSpoofedIpAddress, database, "NoSWID", guestControllerHostUrl, oneIdClientId, logger);

        nrtUpgradeSender = new NrtUpgradeSender(logger, guestControllerClient);
    }
Пример #26
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="loginCache">The cache in which to store login details.</param>
        /// <param name="twoFactorChallengeHandler">The handler for 2FA challenges.</param>
        /// <param name="clientId">The application's client API ID.</param>
        /// <param name="clientSecret">The application's client API secret.</param>
        /// <param name="authorizationNote">An note to store with the authorization.</param>
        /// <param name="fingerprint">The machine fingerprint.</param>
        public LoginManager(
            IKeychain keychain,
            string clientId,
            string clientSecret,
            string authorizationNote = null,
            string fingerprint       = null)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNullOrWhiteSpace(clientId, nameof(clientId));
            Guard.ArgumentNotNullOrWhiteSpace(clientSecret, nameof(clientSecret));

            this.keychain          = keychain;
            this.clientId          = clientId;
            this.clientSecret      = clientSecret;
            this.authorizationNote = authorizationNote;
            this.fingerprint       = fingerprint;
        }
Пример #27
0
        public ApiClient(UriString hostUrl, IKeychain keychain, IProcessManager processManager, ITaskManager taskManager, IEnvironment environment)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));

            var host = String.IsNullOrEmpty(hostUrl)
                ? UriString.ToUriString(HostAddress.GitHubDotComHostAddress.WebUri)
                : new UriString(hostUrl.ToRepositoryUri()
                                .GetComponents(UriComponents.SchemeAndServer, UriFormat.SafeUnescaped));

            HostAddress         = HostAddress.Create(host);
            OriginalUrl         = host;
            this.keychain       = keychain;
            this.processManager = processManager;
            this.taskManager    = taskManager;
            this.environment    = environment;
            loginManager        = new LoginManager(keychain, processManager, taskManager, environment);
        }
Пример #28
0
 public ConnectionManager(
     IProgram program,
     IConnectionCache cache,
     IKeychain keychain,
     ILoginManager loginManager,
     IUsageTracker usageTracker)
 {
     this.program      = program;
     this.cache        = cache;
     this.keychain     = keychain;
     this.loginManager = loginManager;
     this.usageTracker = usageTracker;
     loaded            = new TaskCompletionSource <object>();
     connections       = new Lazy <ObservableCollectionEx <IConnection> >(
         this.CreateConnections,
         LazyThreadSafetyMode.ExecutionAndPublication);
 }
Пример #29
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="keychain"></param>
        /// <param name="clientId">The application's client API ID.</param>
        /// <param name="clientSecret">The application's client API secret.</param>
        /// <param name="processManager"></param>
        /// <param name="taskManager"></param>
        /// <param name="nodeJsExecutablePath"></param>
        /// <param name="octorunScript"></param>
        public LoginManager(
            IKeychain keychain,
            string clientId,
            string clientSecret,
            IProcessManager processManager = null, ITaskManager taskManager = null, NPath?nodeJsExecutablePath = null, NPath?octorunScript = null)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNullOrWhiteSpace(clientId, nameof(clientId));
            Guard.ArgumentNotNullOrWhiteSpace(clientSecret, nameof(clientSecret));

            this.keychain             = keychain;
            this.clientId             = clientId;
            this.clientSecret         = clientSecret;
            this.processManager       = processManager;
            this.taskManager          = taskManager;
            this.nodeJsExecutablePath = nodeJsExecutablePath;
            this.octorunScript        = octorunScript;
        }
Пример #30
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LoginManager"/> class.
        /// </summary>
        /// <param name="keychain">The keychain in which to store credentials.</param>
        /// <param name="twoFactorChallengeHandler">The handler for 2FA challenges.</param>
        /// <param name="clientId">The application's client API ID.</param>
        /// <param name="clientSecret">The application's client API secret.</param>
        /// <param name="authorizationNote">An note to store with the authorization.</param>
        /// <param name="fingerprint">The machine fingerprint.</param>
        public LoginManager(
            IKeychain keychain,
            Lazy <ITwoFactorChallengeHandler> twoFactorChallengeHandler,
            string clientId,
            string clientSecret,
            string authorizationNote = null,
            string fingerprint       = null)
        {
            Guard.ArgumentNotNull(keychain, nameof(keychain));
            Guard.ArgumentNotNull(twoFactorChallengeHandler, nameof(twoFactorChallengeHandler));
            Guard.ArgumentNotEmptyString(clientId, nameof(clientId));
            Guard.ArgumentNotEmptyString(clientSecret, nameof(clientSecret));

            this.keychain = keychain;
            this.twoFactorChallengeHandler = twoFactorChallengeHandler;
            this.clientId          = clientId;
            this.clientSecret      = clientSecret;
            this.authorizationNote = authorizationNote;
            this.fingerprint       = fingerprint;
        }