예제 #1
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);
        }
        public static bool HasExpired(this PKCETokenResponse token)
        {
            var created        = token.CreatedAt;
            var expirationTime = token.ExpiresIn;

            return(created.AddSeconds(expirationTime) < DateTime.UtcNow);
        }
예제 #3
0
    public void StartAuthentification()
    {
        // Check if previous auth
        if (HasPreviousAuthentification())
        {
            // Load local pkce saved token
            _pkceToken = LoadPKCEToken();
            if (_pkceToken != null)
            {
                // Set API authenticator
                SetAuthenticator(_pkceToken);

                // if not expired, output expire time
                if (!_pkceToken.IsExpired)
                {
                    DateTime expireDT = S4UUtility.GetTokenExpiry(_pkceToken.CreatedAt, _pkceToken.ExpiresIn);
                    Debug.Log($"PKCE token loaded | Expires at '{expireDT.ToLocalTime()}'");
                }
            }
        }
        else
        {
            // No previous auth, first time, get new
            GetFreshAuth();
        }
    }
 public void SerializeConfig(PKCETokenResponse data, string path, RSACryptoServiceProvider rsaKey)
 {
     try
     {
         // Serialize
         using (StreamWriter file = new StreamWriter(path, false))
         {
             XmlSerializer controlsDefaultsSerializer = new XmlSerializer(typeof(PKCETokenResponse));
             controlsDefaultsSerializer.Serialize(file, data);
             file.Close();
         }
     }
     catch (Exception e)
     {
         Console.WriteLine(e.Message);
     }
     finally
     {
         // Encrypt
         XmlDocument xmlDoc = new XmlDocument();
         xmlDoc.PreserveWhitespace = true;
         xmlDoc.Load(path);
         Encrypt(xmlDoc, "AccessToken", "AccessToken", rsaKey, "rsaKey");
         Encrypt(xmlDoc, "RefreshToken", "RefreshToken", _rsaKey, "rsaKey");
         xmlDoc.Save(path);
     }
 }
예제 #5
0
        public static async Task SaveAsync(this PKCETokenResponse token, string path)
        {
            var serializedToken =
                JsonSerializer.Serialize(token);

            await File.WriteAllTextAsync(path, serializedToken);
        }
예제 #6
0
    private void SetAuthenticator(PKCETokenResponse token)
    {
        // Set API authentification once recieved
        _pkceAuthenticator = new PKCEAuthenticator(_clientID, token);
        _pkceAuthenticator.TokenRefreshed += this.OnTokenRefreshed;

        OnAuthenticatorComplete?.Invoke(_pkceAuthenticator);
    }
예제 #7
0
파일: CreateClient.cs 프로젝트: garyng/Tss
        private async Task SaveToken(PKCETokenResponse token)
        {
            EnsureDirectoryExist(_config.CredentialsPath);
            var json = JsonConvert.SerializeObject(token);
            await File.WriteAllTextAsync(_config.CredentialsPath, json);

            _logger.LogInformation("Token saved to '{filename}'", _config.CredentialsPath);
        }
예제 #8
0
 public bool HasPreviousAuthentification()
 {
     if (PKCEConfig != null)
     {
         _pkceToken = LoadPKCEToken();
         return(_pkceToken != null);
     }
     return(false);
 }
예제 #9
0
    public void DeauthorizeUser()
    {
        // Dispose server
        if (_server != null)
        {
            _server.Dispose();
        }

        _pkceToken = null;
    }
예제 #10
0
        public async Task SaveTokens(PKCETokenResponse tokenReponse)
        {
            _tokens = tokenReponse;

            Configuration configuration = GetConfiguration();

            configuration.Tokens = tokenReponse;
            string jsonData = JsonSerializer.Serialize <Configuration>(configuration);

            await File.WriteAllLinesAsync(_filePath, new[] { jsonData });
        }
예제 #11
0
        public AppConfig(IOutputHandler outputHandler)
        {
            string location = AppDomain.CurrentDomain.BaseDirectory;

            _directoryPath = $"{location}/.config/";
            _filePath      = $"{location}/.config/appConfig.json";
            _outputHandler = outputHandler;

            Configuration configData = Initialise();

            _clientId = configData.ClientId;
            _tokens   = configData.Tokens;
        }
예제 #12
0
 /// <summary>
 /// Refreshes Spotify authentication to continue having access to Spotify music controls
 /// </summary>
 /// <returns>Task for refreshing token</returns>
 private async Task RefreshAuthentication()
 {
     if (token == null)
     {
         await Task.Run(Init);
     }
     else if (token != null && token.IsExpired)
     {
         PKCETokenRefreshRequest refreshRequest  = new PKCETokenRefreshRequest("<INSERT_CLIENT_ID>", token.RefreshToken);
         PKCETokenResponse       refreshResponse = await new OAuthClient().RequestToken(refreshRequest);
         client = new SpotifyClient(refreshResponse.AccessToken);
     }
 }
예제 #13
0
        /// <summary>
        /// Completes the Spotify authorization process
        /// </summary>
        public async Task Init()
        {
            var(v, c) = PKCEUtil.GenerateCodes();
            await server.Start();

            challenge = (v, c).c;
            verifier  = (v, c).v;

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

                token = await new OAuthClient().RequestToken(
                    new PKCETokenRequest("<INSERT_CLIENT_ID>", response.Code, server.BaseUri, verifier));
                client          = new SpotifyClient(token);
                IsAuthenticated = true;
                bool hasPremium = await HasPremium();

                MessagingCenter.Send(new SpotifyLoginMessage("LoginSuccess", hasPremium), "LoginSuccess");
            };

            var loginRequest = new LoginRequest(
                new Uri("http://localhost:5000/callback"),
                "<INSERT_CLIENT_ID>",
                LoginRequest.ResponseType.Code)
            {
                CodeChallengeMethod = "S256",
                CodeChallenge       = challenge,
                Scope = new[]
                {
                    Scopes.UserModifyPlaybackState,
                    Scopes.AppRemoteControl,
                    Scopes.UserReadCurrentlyPlaying,
                    Scopes.UserReadPlaybackState,
                    Scopes.UserLibraryRead,
                    Scopes.UserReadRecentlyPlayed,
                    Scopes.UserReadPrivate,
                },
            };

            var uri = loginRequest.ToUri();

            try
            {
                await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
            }
            catch (Exception)
            {
                // TODO: log error to app center.
            }
        }
예제 #14
0
        public void Token_expiration_should_be_correct()
        {
            // Arrange
            var sut = new PKCETokenResponse();

            sut.CreatedAt = DateTime.UtcNow.AddDays(-14);
            sut.ExpiresIn = 1;

            // Act
            var result = sut.HasExpired();

            // Assert
            result.Should().BeTrue();
        }
예제 #15
0
        public async Task <ISpotifyClient> CreateSpotifyClientAsync()
        {
            PKCETokenResponse tokenResponse = _config.Tokens;

            if (String.IsNullOrEmpty(tokenResponse.AccessToken) || String.IsNullOrEmpty(tokenResponse.RefreshToken))
            {
                tokenResponse = await UseNewTokens();
            }
            else if (tokenResponse.HasExpired())
            {
                tokenResponse = await RefreshTokens();
            }

            var config = SpotifyClientConfig.CreateDefault().WithAuthenticator(new PKCEAuthenticator(_config.ClientId, tokenResponse));

            return(new SpotifyClient(config));
        }
예제 #16
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"));
            }
        }
예제 #17
0
    private async Task OnAuthCodeRecieved(object sender, AuthorizationCodeResponse response, string verifier)
    {
        // Check response and & is valid
        if (response != null && !string.IsNullOrEmpty(response.Code))
        {
            await _server.Stop();

            _pkceToken = await new OAuthClient().RequestToken(
                new PKCETokenRequest(_clientID, response.Code, _server.BaseUri, verifier)
                );

            // Save PKCE token first
            SavePKCEToken(_pkceToken);

            Debug.Log("PKCE: Recieved Auth Code");
            SetAuthenticator(_pkceToken);
        }
    }
예제 #18
0
 /// <summary>
 /// Saves the PKCE token using the current PKECTokenSaveType in config
 /// </summary>
 /// <param name="token">Current token to save</param>
 private void SavePKCEToken(PKCETokenResponse token)
 {
     if (token != null)
     {
         string json = JsonConvert.SerializeObject(token);
         if (PKCEConfig.TokenSaveType == PKCETokenSaveType.File)
         {
             File.WriteAllText(PKCEConfig.TokenPath, json);
         }
         else if (PKCEConfig.TokenSaveType == PKCETokenSaveType.PlayerPrefs)
         {
             // Save to player prefs on main thread
             _dispatcher.Add(() =>
             {
                 PlayerPrefs.SetString(PKCEConfig.PlayerPrefsKey, json);
             });
         }
     }
 }
예제 #19
0
        public async Task RequestToken()
        {
            if (TokenResponse == null)
            {
                return;
            }

            try
            {
                var newResponse = await new OAuthClient().RequestToken(
                    new PKCETokenRefreshRequest(_clientId, TokenResponse.RefreshToken)
                    );

                TokenResponse = newResponse;
            }
            catch (Exception)
            {
                // Ignored
            }
        }
예제 #20
0
        public static bool StartCached(Action <SpotifyClient> onComplete)
        {
            if (!File.Exists(m_TokenPath))
            {
                return(false);
            }

            string            json  = File.ReadAllText(m_TokenPath);
            PKCETokenResponse token = JsonConvert.DeserializeObject <PKCETokenResponse>(json);

            PKCEAuthenticator authenticator = new PKCEAuthenticator(m_ClientId, token);

            authenticator.TokenRefreshed += (sender, refreshedToken) => File.WriteAllText(m_TokenPath, JsonConvert.SerializeObject(refreshedToken));

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

            onComplete(client);
            return(true);
        }
예제 #21
0
        /// <inheritdoc/>
        public async Task <JsonResult> GetSpotifyAuthenticationToken()
        {
            var authToken = string.Empty;

            var(verifier, challenge) = PKCEUtil.GenerateCodes();
            await SpotifyAuthServer.Start();

            // Temporary auth server lsitens for Spotify callback.
            SpotifyAuthServer.AuthorizationCodeReceived += async(sender, response) =>
            {
                await SpotifyAuthServer.Stop();

                PKCETokenResponse token = await new OAuthClient().RequestToken(
                    new PKCETokenRequest(SpotifyClientId, response.Code, SpotifyAuthServer.BaseUri, verifier));
                authToken = JsonConvert.SerializeObject(token);
            };

            // Make spotify auth call.
            var request = new LoginRequest(SpotifyAuthServer.BaseUri, SpotifyClientId, LoginRequest.ResponseType.Code)
            {
                CodeChallenge       = challenge,
                CodeChallengeMethod = "S256",
                Scope = new List <string> {
                    UserReadPrivate, UserReadRecentlyPlayed
                }
            };

            Uri uri = request.ToUri();

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

            return(new JsonResult(authToken));
        }
예제 #22
0
    private void OnTokenRefreshed(object sender, PKCETokenResponse token)
    {
        DateTime expireDT = S4UUtility.GetTokenExpiry(token.CreatedAt, token.ExpiresIn);

        Debug.Log($"PKCE token refreshed | Expires at '{expireDT.ToLocalTime()}'");

        bool triggerEvent = _pkceToken.IsExpired && !token.IsExpired;

        _pkceToken = token;

        if (PKCEConfig != null)
        {
            SavePKCEToken(_pkceToken);
        }

        if (triggerEvent)
        {
            Debug.Log("PKCE: Success in refreshing expired token into new token");
            OnAuthenticatorComplete?.Invoke(_pkceAuthenticator);
        }
    }
예제 #23
0
        public async void StartAuth()
        {
            GenerateCode();

            await _server.Start();

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

                TokenResponse = await new OAuthClient().RequestToken(
                    new PKCETokenRequest(_clientId !, response.Code, _server.BaseUri, _verifier)
                    );

                Start();
            };

            CreateLoginRequest();
            var uri = _loginRequest.ToUri();

            BrowserUtil.Open(uri);
        }
예제 #24
0
        private void StartAuthentication()
        {
            var(verifier, challenge) = PKCEUtil.GenerateCodes();

            Task.WaitAll(_server.Start());

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

                PKCETokenResponse dataTask = await new OAuthClient().RequestToken(
                    new PKCETokenRequest(clientId, response.Code, _server.BaseUri, verifier)
                    );

                File.WriteAllText(CredentialsPath, JsonConvert.SerializeObject(dataTask));
                File.SetAttributes(CredentialsPath, FileAttributes.ReadOnly);
                Start();
            };

            var request = new LoginRequest(_server.BaseUri, clientId, LoginRequest.ResponseType.Code)
            {
                CodeChallenge       = challenge,
                CodeChallengeMethod = "S256",
                Scope = new List <string> {
                    UgcImageUpload, UserReadRecentlyPlayed, UserReadPlaybackPosition, UserTopRead, UserLibraryRead, UserLibraryModify, PlaylistModifyPrivate, PlaylistReadPrivate, UserFollowRead, PlaylistModifyPublic, UserReadPrivate, UserReadEmail, AppRemoteControl, Streaming, UserReadCurrentlyPlaying, UserModifyPlaybackState, UserReadPlaybackState, PlaylistReadCollaborative, UserFollowModify
                }
            };

            Uri uri = request.ToUri();

            try
            {
                BrowserUtil.Open(uri);
            }
            catch (Exception)
            {
                Console.WriteLine("Unable to open URL, manually open: {0}", uri);
            }
        }
예제 #25
0
        private static async Task StartAuthentication()
        {
            var(verifier, challenge) = PKCEUtil.GenerateCodes();

            await _server.Start();

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

                PKCETokenResponse token = await new OAuthClient().RequestToken(
                    new PKCETokenRequest(clientId !, response.Code, _server.BaseUri, verifier)
                    );

                await File.WriteAllTextAsync(CredentialsPath, JsonConvert.SerializeObject(token));
                await Start();
            };

            var request = new LoginRequest(_server.BaseUri, clientId !, LoginRequest.ResponseType.Code)
            {
                CodeChallenge       = challenge,
                CodeChallengeMethod = "S256",
                Scope = new List <string> {
                    UserReadEmail, UserReadPlaybackPosition, UserReadCurrentlyPlaying, UserModifyPlaybackState, UserReadPlaybackState, UserReadPlaybackState, UserReadPrivate, PlaylistReadPrivate, PlaylistModifyPublic, PlaylistModifyPrivate, Streaming, AppRemoteControl, PlaylistReadCollaborative
                }
            };

            Uri uri = request.ToUri();

            try
            {
                BrowserUtil.Open(uri);
            }
            catch (Exception)
            {
                Console.WriteLine("Unable to open URL, manually open: {0}", uri);
            }
        }
    }
예제 #26
0
        private void OnLoggedIn(PrivateUser privateUser, PKCETokenResponse tokenResponse)
        {
            var playerStateStruct = PlayerState;

            playerStateStruct.IsLoggedIn = true;
            PlayerState = playerStateStruct;

            _plugin.Configuration.SpotifySettings.TokenResponse = tokenResponse;

            if (_spotifyState.IsPremiumUser)
            {
                _plugin.Configuration.SpotifySettings.LimitedAccess = false;
            }

            if (!_spotifyState.IsPremiumUser)
            {
                if (!_plugin.Configuration.SpotifySettings.LimitedAccess
                    ) //Do a check to not spam the user, I don't want to force it down their throats. (f**k marketing)
                {
                    _plugin.PluginInterface.Framework.Gui.Chat.PrintError(
                        "Uh-oh, it looks like you're not premium on Spotify. Some features in Fantasy Player have been disabled.");
                }

                _plugin.Configuration.SpotifySettings.LimitedAccess = true;

                //Change configs
                if (_plugin.Configuration.PlayerSettings.CompactPlayer)
                {
                    _plugin.Configuration.PlayerSettings.CompactPlayer = false;
                }
                if (!_plugin.Configuration.PlayerSettings.NoButtons)
                {
                    _plugin.Configuration.PlayerSettings.NoButtons = true;
                }
            }

            _plugin.Configuration.Save();
        }
예제 #27
0
 /// <summary>
 /// Spotify Manager with Spotify Client
 /// </summary>
 /// <param name="client">a Spotify client for Spotify controls</param>
 public SpotifyManager(ISpotifyClient client)
 {
     this.token  = null;
     this.client = client;
 }
예제 #28
0
 private static void WriteOAuthCreds(PKCETokenResponse data)
 {
     Directory.CreateDirectory(dataPath);
     File.WriteAllText(dataPath + "\\oauth.json", JsonConvert.SerializeObject(data));
 }
예제 #29
0
 private async void OnTokenRefreshed(object sender, PKCETokenResponse token)
 {
     await token.SaveAsync(_credentialsPath);
 }