Exemplo n.º 1
0
        private async UniTaskVoid StartServer()
        {
            try
            {
                Uri baseUri = SpotifyConfiguration.ServerConfiguration.Uri;
                int port    = SpotifyConfiguration.ServerConfiguration.Port;

                EmbedIOAuthServer server = new EmbedIOAuthServer(baseUri, port);
                await server.Start();

                server.AuthorizationCodeReceived += (sender, response) =>
                {
                    server.Stop();
                    server.Dispose();
                    responseCode = response.Code;
                    return(null);
                };

                OnServerInitialized.Raise();

                await UniTask.WaitUntil(() => !string.IsNullOrEmpty(responseCode));

                Client.FromAuthorizationCode(responseCode).Forget();
                Destroy(gameObject);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }
Exemplo n.º 2
0
 public SpotifyState(string loginUri, string clientId, int port, int playerRefreshTime)
 {
     _loginUrl          = new Uri(loginUri);
     _clientId          = clientId;
     _playerRefreshTime = playerRefreshTime;
     _server            = new EmbedIOAuthServer(_loginUrl, port);
 }
Exemplo n.º 3
0
        public static async Task Main()
        {
            _server = new EmbedIOAuthServer(
                new Uri("http://localhost:5000/callback"),
                5000,
                Assembly.GetExecutingAssembly(),
                "Example.CLI.CustomHTML.Resources.custom_site"
                );
            await _server.Start();

            _server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;

            var request = new LoginRequest(_server.BaseUri, clientId, LoginRequest.ResponseType.Code)
            {
                Scope = new List <string> {
                    UserReadEmail
                }
            };

            Uri uri = request.ToUri();

            try
            {
                BrowserUtil.Open(uri);
            }
            catch (Exception)
            {
                Console.WriteLine("Unable to open URL, manually open: {0}", uri);
            }

            Console.ReadKey();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Encapsulate the login flow with <see cref="EmbedIOAuthServer"/>, useful for console application.
        /// </summary>
        public async Task Login()
        {
            var server = new EmbedIOAuthServer(new Uri(_config.CallbackUrl), _config.CallbackPort);
            await server.Start();

            var auth = new TaskCompletionSource();

            server.AuthorizationCodeReceived += async(_, response) =>
            {
                await CompleteLogin(response.Code);

                auth.SetResult();
            };

            var result = await TryLogin();

            await result.IfSomeAsync(async url =>
            {
                BrowserUtil.Open(new Uri(url));
                await auth.Task;
            });

            await server.Stop();

            server.Dispose();
        }
Exemplo n.º 5
0
        private async Task LoginToSpotify(TaskCompletionSource <bool> tcs)
        {
            Server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
            await Server.Start();

            Server.ImplictGrantReceived += async(object sender, ImplictGrantResponse response) =>
            {
                await Server.Stop();

                if (response.AccessToken != null)
                {
                    Spotify = new SpotifyClient(response.AccessToken);
                    Profile = await Spotify.UserProfile.Current();

                    tcs.SetResult(Spotify != null);
                }
                else
                {
                    Log("Error when attempting to log in");
                    tcs.SetResult(false);
                }
            };

            var request = new LoginRequest(Server.BaseUri, SpotifySecrets.CLIENT_ID, LoginRequest.ResponseType.Token)
            {
                Scope = new List <string>
                {
                    Scopes.UserLibraryRead,
                    Scopes.PlaylistModifyPublic
                }
            };

            BrowserUtil.Open(request.ToUri());
        }
Exemplo n.º 6
0
    public async void StartAuthentification()
    {
        // Validate config values
        if (_authConfig.RedirectUri == string.Empty && _authConfig.ServerPort <= 0)
        {
            // Problem with user's config, use default values
            _authConfig.RedirectUri = "http://localhost:5000/callback";
            _authConfig.ServerPort  = 5000;
            return;
        }

        // Start server
        _server = new EmbedIOAuthServer(new Uri(_authConfig.RedirectUri), _authConfig.ServerPort);
        await _server.Start();

        // Await token recieved
        _server.ImplictGrantReceived += this.OnImplicitGrantReceived;

        // Create request
        LoginRequest request = new LoginRequest(_server.BaseUri, _authConfig.ClientID, LoginRequest.ResponseType.Token)
        {
            Scope = _authConfig.APIScopes,
        };

        BrowserUtil.Open(request.ToUri());
    }
        private async Task Authorize()
        {
            Logger.LogInformation("Started the Spotify authorization process...");
            Server = new EmbedIOAuthServer(new Uri(RedirectUri), SpotifyOptions.Value.AuthServerPort);
            await Server.Start();

            Server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;

            var loginRequest = new LoginRequest(Server.BaseUri, SpotifyOptions.Value.ClientId, LoginRequest.ResponseType.Code)
            {
                CodeChallengeMethod = "S256",
                CodeChallenge       = Challenge,
                Scope = new[] { Scopes.UserReadCurrentlyPlaying }
            };

            var uri = loginRequest.ToUri();

            try
            {
                BrowserUtil.Open(uri);
            }
            catch (Exception)
            {
                Logger.LogCritical("Unable to open a browser.  Please manually open: {0}", uri);
            }
        }
Exemplo n.º 8
0
        public static async Task StartRemote(Action <SpotifyClient> onComplete)
        {
            (string verifier, string challenge) = PKCEUtil.GenerateCodes();

            m_AuthServer = new EmbedIOAuthServer(m_CallbackUri, 5000);
            await m_AuthServer.Start();

            m_AuthServer.AuthorizationCodeReceived += async(sender, response) =>
            {
                await m_AuthServer.Stop();

                PKCETokenResponse token = await new OAuthClient().RequestToken(
                    new PKCETokenRequest(m_ClientId, response.Code, m_AuthServer.BaseUri, verifier)
                    );

                File.WriteAllText(m_TokenPath, JsonConvert.SerializeObject(token));
                StartCached(onComplete);
            };

            var request = new LoginRequest(m_AuthServer.BaseUri, m_ClientId, LoginRequest.ResponseType.Code)
            {
                CodeChallenge       = challenge,
                CodeChallengeMethod = "S256",
                Scope = new List <string> {
                    Scopes.PlaylistModifyPublic
                }
            };

            Uri uri = request.ToUri();

            BrowserUtil.Open(uri);
        }
Exemplo n.º 9
0
        private static async Task StartAuthentication()
        {
            _server = new EmbedIOAuthServer(new Uri("http://localhost:5050/callback"), 5050);

            await _server.Start();

            _server.AuthorizationCodeReceived += OnAuthorizationCodeReceived;

            var request = new LoginRequest(_server.BaseUri, clientId !, LoginRequest.ResponseType.Code)
            {
                Scope = new List <string> {
                    UserReadEmail, UserReadPrivate, PlaylistReadPrivate, PlaylistReadCollaborative, UserLibraryRead, UserLibraryModify, UserReadCurrentlyPlaying, UserReadPlaybackPosition, UserReadPlaybackState
                }
            };

            Uri uri = request.ToUri();

            try
            {
                BrowserUtil.Open(uri);
            }
            catch (Exception)
            {
                Console.WriteLine("[AUTH] Unable to open URL, manually open: {0}", uri);
            }
        }
Exemplo n.º 10
0
        public Task <string?> WaitForLogin(Uri address, int port, TimeSpan timeout, string state)
        {
            var tcs = new TaskCompletionSource <string?>();

            var server = new EmbedIOAuthServer(address, port);

            server.AuthorizationCodeReceived += async(sender, response) =>
            {
                await server.Stop();

                if (response.State != state)
                {
                    tcs.SetResult("Given state parameter was not correct.");
                    return;
                }

                var tokenResponse = await _spotifyService.OAuth.RequestToken(
                    new AuthorizationCodeTokenRequest(
                        _appConfig.SpotifyApp.ClientId !,
                        _appConfig.SpotifyApp.ClientSecret !,
                        response.Code,
                        server.BaseUri
                        )
                    );

                _appConfig.SpotifyToken.AccessToken  = tokenResponse.AccessToken;
                _appConfig.SpotifyToken.RefreshToken = tokenResponse.RefreshToken;
                _appConfig.SpotifyToken.CreatedAt    = tokenResponse.CreatedAt;
                _appConfig.SpotifyToken.ExpiresIn    = tokenResponse.ExpiresIn;
                _appConfig.SpotifyToken.TokenType    = tokenResponse.TokenType;

                // Create a temporary spotify with access token to fetch user
                var spotify = new SpotifyClient(_spotifyService.Config.WithToken(tokenResponse.AccessToken));
                var me      = await spotify.UserProfile.Current();

                _appConfig.Account.Id          = me.Id;
                _appConfig.Account.DisplayName = me.DisplayName;
                _appConfig.Account.Uri         = me.Uri;

                await _appConfig.Save();

                server.Dispose();
                tcs.SetResult(null);
            };

            var ct = new CancellationTokenSource(timeout);

            ct.Token.Register(() =>
            {
                server.Stop();
                server.Dispose();
                tcs.TrySetCanceled();
            }, useSynchronizationContext: false);

            server.Start();

            return(tcs.Task);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Creates the server and handles the authorisation request
        /// </summary>
        private async Task AuthoriseAsync()
        {
            // create the callback server on localhost:8888, start it and bind the ImplictGrantReceived event to the method
            Server = new EmbedIOAuthServer(new Uri("http://localhost:8888/callback"), 8888);
            await Server.Start();

            Server.ImplictGrantReceived += OnImplicitGrantReceivedAsync;

            // set up our request with the scopes etc, then open the browser for authorisation
            ObtainToken();

            await Task.Delay(-1); // prevents the program from closing
        }
Exemplo n.º 12
0
    public void Configure(object config)
    {
        if (config is AuthorizationConfig authConfig)
        {
            _clientID = authConfig.ClientID;

            // Start server with config values
            _server = new EmbedIOAuthServer(new Uri(authConfig.RedirectUri), authConfig.ServerPort);
        }

        if (config is PKCE_AuthConfig pkceConfig)
        {
            PKCEConfig = pkceConfig;
        }
    }
Exemplo n.º 13
0
        private async Task AuthorizeSpotifyAsync()
        {
            Server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
            await Server.Start();

            Server.AuthorizationCodeReceived += OnAuthorizationCodeReceivedAsync;

            var loginRequest = new LoginRequest(Server.BaseUri, CLIENT_ID, LoginRequest.ResponseType.Code)
            {
                Scope = new[] { Scopes.UserModifyPlaybackState, Scopes.UserReadCurrentlyPlaying, Scopes.UserReadPlaybackPosition, Scopes.UserReadPlaybackState, Scopes.AppRemoteControl }
            };
            var uri = loginRequest.ToUri();

            BrowserUtil.Open(uri);
        }
Exemplo n.º 14
0
        public async Task Auth()
        {
            _server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
            await _server.Start().ConfigureAwait(false);

            _server.ImplictGrantReceived += OnImplicitGrantReceived;

            var request = new LoginRequest(_server.BaseUri, "46f6cbff0b5e4bd1845f35f7c661c6b1", LoginRequest.ResponseType.Token)
            {
                Scope = new List <string> {
                    Scopes.UserLibraryRead, Scopes.PlaylistModifyPrivate, Scopes.PlaylistModifyPublic
                }
            };

            BrowserUtil.Open(request.ToUri());
        }
Exemplo n.º 15
0
        public static async Task Authorize()
        {
            _server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
            await _server.Start();

            _server.ImplictGrantReceived += OnImplicitGrantReceived;

            LoginRequest request = new LoginRequest(_server.BaseUri, Properties.Settings.Default.ClientID, LoginRequest.ResponseType.Token)
            {
                Scope = new List <string> {
                    Scopes.UserLibraryModify, Scopes.PlaylistModifyPrivate, Scopes.PlaylistModifyPublic
                }
            };

            BrowserUtil.Open(request.ToUri());
        }
Exemplo n.º 16
0
        public async Task StartAuthorization()
        {
            this.server = new EmbedIOAuthServer(new Uri(Constants.CallbackUri), Constants.CallbackPort);

            await this.server.Start();

            this.server.AuthorizationCodeReceived += this.OnAuthorizationCodeReceived;

            var loginRequest = new LoginRequest(this.server.BaseUri, this.clientId, LoginRequest.ResponseType.Code)
            {
                Scope = new List <string> {
                    UserLibraryRead, PlaylistModifyPublic
                }
            };

            BrowserUtil.Open(loginRequest.ToUri());
        }
Exemplo n.º 17
0
        private async Task StartStreamMode()
        {
            try
            {
                Log.Instance.PrintMessage("Trying to connect Spotify account", MessageType.Info, "Spotify.StartStreamMode()");
                Kernel.InternetAvaliable(false);
                Stopwatch crono = Stopwatch.StartNew();
                if (!File.Exists(AuthPath))
                {
                    var(verifier, challenge) = PKCEUtil.GenerateCodes();
                    var server = new EmbedIOAuthServer(new Uri("http://localhost:4002/callback"), 4002);
                    await server.Start();

                    server.AuthorizationCodeReceived += async(sender, response) =>
                    {
                        await server.Stop();

                        PKCETokenResponse token = await new OAuthClient().RequestToken(new PKCETokenRequest(PublicKey, response.Code, server.BaseUri, verifier));
                        await File.WriteAllTextAsync(AuthPath, JsonConvert.SerializeObject(token));
                        await StartLoginSpotify(crono);

                        server.Dispose();
                    };
                    var login = new LoginRequest(server.BaseUri, PublicKey, LoginRequest.ResponseType.Code)
                    {
                        CodeChallenge       = challenge,
                        CodeChallengeMethod = "S256",
                        Scope = new List <string> {
                            Scopes.UserReadEmail, Scopes.UserReadPrivate, Scopes.Streaming, Scopes.PlaylistReadPrivate, Scopes.UserReadPlaybackState, Scopes.UserLibraryRead
                        }
                    };
                    BrowserUtil.Open(login.ToUri());
                }
                else
                {
                    await StartLoginSpotify(crono);
                }
            }
            catch (APIException e)
            {
                Kernel.InternetAvaliable(false);
                Log.Instance.PrintMessage(e.Message, MessageType.Error);
                System.Windows.Forms.MessageBox.Show(Kernel.LocalTexts.GetString("error_internet"));
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Start the authroization code flow or request for an access token if a refresh token is present and the scopes match.
        /// </summary>
        /// <param name="cancel">A <see cref="CancellationToken"/> to cancel the wait for users to authorize on their browsers</param>
        /// <exception cref="OperationCanceledException">Thrown if the wait is canceled</exception>
        public override async Task Authorize(CancellationToken cancel = default)
        {
            AuthorizationCodeTokenResponse tokenResponse;

            if (RefreshToken.IsNullOrEmpty() || !requiredScopes.IsSubsetOf(AuthorizedScopes))
            {
                var taskCompletionSource = new TaskCompletionSource <AuthorizationCodeResponse>();

                EmbedIOAuthServer _server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);
                await _server.Start();

                _server.AuthorizationCodeReceived += (_, response) =>
                {
                    taskCompletionSource.SetResult(response);
                    return(Task.CompletedTask);
                };

                var request = new SpotifyAPI.Web.LoginRequest(_server.BaseUri, ClientId, SpotifyAPI.Web.LoginRequest.ResponseType.Code)
                {
                    Scope = requiredScopes
                };
                Helper.OpenUri(request.ToUri());

                while (!taskCompletionSource.Task.IsCompleted)
                {
                    cancel.ThrowIfCancellationRequested();
                    await Task.Delay(500);
                }

                await _server.Stop();

                var response = taskCompletionSource.Task.Result;
                tokenResponse = await new OAuthClient().RequestToken(
                    new AuthorizationCodeTokenRequest(
                        ClientId, ClientSecret, response.Code, new Uri("http://localhost:5000/callback")
                        )
                    );
                RefreshToken = tokenResponse.RefreshToken;
            }
            else
            {
                var response = await new OAuthClient().RequestToken(new AuthorizationCodeRefreshRequest(ClientId, ClientSecret, RefreshToken));
                tokenResponse = new AuthorizationCodeTokenResponse()
                {
                    RefreshToken = RefreshToken,
                    AccessToken  = response.AccessToken,
                    CreatedAt    = response.CreatedAt,
                    ExpiresIn    = response.ExpiresIn,
                    Scope        = response.Scope,
                    TokenType    = response.TokenType
                };
            }
            AccessToken      = tokenResponse.AccessToken;
            AuthorizedScopes = tokenResponse.Scope.Split(' ').ToList();
            var config = SpotifyClientConfig
                         .CreateDefault()
                         .WithAuthenticator(new AuthorizationCodeAuthenticator(ClientId, ClientSecret, tokenResponse));

            spotify = new SpotifyClient(tokenResponse.AccessToken);
            RaiseConfigUpdated(EventArgs.Empty);
        }
        async void SpotifyWebAuth()
        {
            try
            {
                if (File.Exists(_path))
                {
                    var token_response = DeserializeConfig(_path, _rsaKey);

                    var authenticator = new PKCEAuthenticator(_clientID, token_response, _path);

                    var config = SpotifyClientConfig.CreateDefault()
                                 .WithAuthenticator(authenticator);
                    _spotify = new SpotifyClient(config);

                    SerializeConfig(token_response, _path, _rsaKey);


                    // This appears to be the easiest way to check if the Spotify client works, but it's not great:
                    try
                    {
                        await _spotify.Search.Item(new SearchRequest(SearchRequest.Types.Track, "fasdofimasdofiasdnfaosnf"));

                        _auth = 1;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Spotify agent dead: " + e);
                        throw new System.NullReferenceException();
                    }
                }
                else
                {
                    throw new System.NullReferenceException("Token.xml not found!");
                }
            }
            catch (System.NullReferenceException)
            {
                var(verifier, challenge) = PKCEUtil.GenerateCodes(120);

                var loginRequest = new LoginRequest(
                    new Uri("http://localhost:5000/callback"), _clientID, LoginRequest.ResponseType.Code)
                {
                    CodeChallengeMethod = "S256",
                    CodeChallenge       = challenge,
                    Scope = new[] { Scopes.UserLibraryModify, Scopes.UserFollowModify, Scopes.UserFollowRead, Scopes.UserLibraryRead }
                };
                var uri = loginRequest.ToUri();

                var server = new EmbedIOAuthServer(new Uri("http://localhost:5000/callback"), 5000);

                server.PkceReceived += async(sender, response) =>
                {
                    await server.Stop();

                    var initialResponse = await new OAuthClient().RequestToken(
                        new PKCETokenRequest(_clientID, response.Code, server.BaseUri, verifier)
                        );

                    //WriteOutput(initialResponse);

                    var authenticator = new PKCEAuthenticator(_clientID, initialResponse, _path);

                    var config = SpotifyClientConfig.CreateDefault()
                                 .WithAuthenticator(authenticator);
                    _spotify = new SpotifyClient(config);

                    //WriteOutput(initialResponse);
                    SerializeConfig(initialResponse, _path, _rsaKey);
                };
                await server.Start();

                try
                {
                    BrowserUtil.Open(uri);
                }
                catch (Exception)
                {
                    Console.WriteLine("Unable to open URL, manually open: {0}", uri);
                }

                _auth = 1;
            }
            catch (System.Net.WebException)
            {
                _auth = 0;
            }
            finally
            {
                mbApiInterface.MB_RefreshPanels();
                panel.Invalidate();
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Start the authroization code flow or request for an access token if a refresh token is present and the scopes match.
        /// </summary>
        /// <param name="cancel">A <see cref="CancellationToken"/> to cancel the wait for users to authorize on their browsers</param>
        /// <exception cref="OperationCanceledException">Thrown if the wait is canceled</exception>
        public override async Task Authorize(CancellationToken cancel = default)
        {
            OsuTokenResponse tokenResponse;

            if (RefreshToken.IsNullOrEmpty() || !requiredScopes.IsSubsetOf(AuthorizedScopes))
            {
                var taskCompletionSource = new TaskCompletionSource <AuthorizationCodeResponse>();

                EmbedIOAuthServer _server = new EmbedIOAuthServer(new Uri("http://localhost:5001/callback"), 5001);
                await _server.Start();

                _server.AuthorizationCodeReceived += (_, response) =>
                {
                    taskCompletionSource.SetResult(response);
                    return(Task.CompletedTask);
                };

                var request = new LoginRequest(new Uri("https://osu.ppy.sh/oauth/authorize"), _server.BaseUri, ClientId, LoginRequest.ResponseType.Code)
                {
                    Scope = requiredScopes
                };
                Helper.OpenUri(request.ToUri());

                while (!taskCompletionSource.Task.IsCompleted)
                {
                    cancel.ThrowIfCancellationRequested();
                    await Task.Delay(500);
                }

                await _server.Stop();

                var response = taskCompletionSource.Task.Result;

                IRestClient osuAuthClient = new RestClient("https://osu.ppy.sh/").UseNewtonsoftJson();

                osuAuthClient.AddHandler("application/json", () => new JsonDeserializer());

                var tokenRequest = new RestRequest("oauth/token/", Method.POST);
                tokenRequest.AddParameter("client_id", ClientId);
                tokenRequest.AddParameter("client_secret", ClientSecret);
                tokenRequest.AddParameter("code", response.Code);
                tokenRequest.AddParameter("grant_type", "authorization_code");
                tokenRequest.AddParameter("redirect_uri", "http://localhost:5001/callback");

                var codeResponse = await osuAuthClient.ExecuteAsync <OsuTokenResponse>(tokenRequest);

                tokenResponse = codeResponse.Data;
            }
            else
            {
                IRestClient osuAuthClient = new RestClient("https://osu.ppy.sh/").UseNewtonsoftJson();

                osuAuthClient.AddHandler("application/json", () => new JsonDeserializer());

                var tokenRequest = new RestRequest("oauth/token/", Method.POST);
                tokenRequest.AddParameter("client_id", ClientId);
                tokenRequest.AddParameter("client_secret", ClientSecret);
                tokenRequest.AddParameter("refresh_token", RefreshToken);
                tokenRequest.AddParameter("grant_type", "refresh_token");

                var codeResponse = await osuAuthClient.ExecuteAsync <OsuTokenResponse>(tokenRequest);

                tokenResponse = codeResponse.Data;
            }

            RefreshToken     = tokenResponse.refresh_token;
            AccessToken      = tokenResponse.access_token;
            AuthorizedScopes = new List <string>(requiredScopes);

            osu = new RestClient("https://osu.ppy.sh/").UseNewtonsoftJson();
            osu.AddDefaultHeader("Authorization", "Bearer " + tokenResponse.access_token);

            RaiseConfigUpdated(EventArgs.Empty);
        }
        public async Task ConnectWebClient(bool keepRefreshToken = true)
        {
            _securityStore = SecurityStore.Load(pluginDirectory);

            EmbedIOAuthServer _server = new EmbedIOAuthServer(new Uri("http://localhost:4002/callback"), 4002);

            if (_securityStore.HasRefreshToken && keepRefreshToken)
            {
                var refreshRequest = new AuthorizationCodeRefreshRequest(_securityStore.ClientId,
                                                                         _securityStore.ClientSecret,
                                                                         _securityStore.RefreshToken);
                var refreshResponse = await new OAuthClient().RequestToken(refreshRequest);
                lock (_lock)
                {
                    _spotifyClient = new SpotifyClient(refreshResponse.AccessToken);
                }
            }
            else
            {
                await _server.Start();

                _server.AuthorizationCodeReceived += async(object sender, AuthorizationCodeResponse response) =>
                {
                    await _server.Stop();

                    AuthorizationCodeTokenResponse token = await new OAuthClient().RequestToken(
                        new AuthorizationCodeTokenRequest(_securityStore.ClientId,
                                                          _securityStore.ClientSecret,
                                                          response.Code,
                                                          _server.BaseUri));
                    lock (_lock)
                    {
                        _securityStore.RefreshToken = token.RefreshToken;
                        _securityStore.Save(pluginDirectory);
                        _spotifyClient = new SpotifyClient(token.AccessToken);
                    }
                };

                _server.ErrorReceived += async(object sender, string error, string state) =>
                {
                    Console.WriteLine($"Aborting authorization, error received: {error}");
                    await _server.Stop();
                };

                var request = new LoginRequest(_server.BaseUri, _securityStore.ClientId, LoginRequest.ResponseType.Code)
                {
                    Scope = new List <string> {
                        UserLibraryRead,
                        UserReadEmail,
                        UserReadPrivate,
                        UserReadPlaybackPosition,
                        UserReadCurrentlyPlaying,
                        UserReadPlaybackState,
                        UserModifyPlaybackState,
                        AppRemoteControl,
                        PlaylistReadPrivate
                    }
                };

                Uri uri = request.ToUri();
                try {
                    BrowserUtil.Open(uri);
                } catch (Exception) {
                    Console.WriteLine("Unable to open URL, manually open: {0}", uri);
                };
            };
        }