public async Task <AccessAuthToken> AssertValidLogin(AccessAuthToken token, Boolean loopUntilSuccess)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            if (token.RefreshToken == null || token.RefreshToken.Length <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(token));
            }

            using HttpClient c = ClientFactory.CreateClient("spotify-accounts");

            string clientHeader = Convert.ToBase64String(
                Encoding.ASCII.GetBytes(
                    $"{ClientId}:{ClientSecret}"
                    )
                ); // Encode the Client ID and Client Secret to Base 64

            c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                clientHeader
                ); // Add the Authorization Header, now that it exists.

            do
            {     // While the token is invalid, repeat.
                using FormUrlEncodedContent formContent = new FormUrlEncodedContent(new[]
                { // See https://developer.spotify.com/documentation/general/guides/authorization-guide/
                    new KeyValuePair <string, string>("grant_type", "refresh_token"),
                    new KeyValuePair <string, string>("refresh_token", token.RefreshToken)
                }); // Create a new FormContent to send over to spotify.

                HttpResponseMessage response = await c.PostAsync(
                    new Uri("token", UriKind.Relative), // This is a Uri object instead of a string so VS can stop complaining.
                    formContent
                    ).ConfigureAwait(false);            // Post it over to spotify.

                String x = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                { // If the response is successful, deserialize it to a AccessToken and return that.
                    string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                    AccessAuthToken tok = JsonConvert.DeserializeObject <AccessAuthToken>(responseString);
                    tok.RefreshToken = token.RefreshToken;

                    return(tok);
                }

                // If not successful, sleep for 500 milliseconds, and retry.
                Thread.Sleep(500);
            } while (loopUntilSuccess); // POTENTIAL INFINITE LOOP CONDITION. If spotify never returns a succesful response AND loopUntilSuccess is true, this code will loop forever.

            throw new InvalidAuthTokenRecievedException("Unable to assert authentication is valid");
        }
        public void AssertThatAssertValidLoginHandlesNonNullTokenButNullValues()
        {
            AccessAuthToken token = new AccessAuthToken()
            {
                AccessToken  = null,
                RefreshToken = null,
                TokenType    = "",
                CreateDate   = DateTime.Now,
                Scope        = ""
            };

            Assert.ThrowsAsync <ArgumentOutOfRangeException>(async() => await authHelper.AssertValidLogin(token, false).ConfigureAwait(false));
        }
        public async Task <AccessAuthToken> TransmutAuthCode(string code)
        {
            if (code == null)
            { // If the code is null, throw a Arg Nil.
                throw new ArgumentNullException(nameof(code));
            }

            if (code.Length <= 0)
            { // If the code is empty, throw a Arg Out of Range.
                throw new ArgumentOutOfRangeException(nameof(code));
            }

            using HttpClient c = ClientFactory.CreateClient("spotify-accounts");
            string clientHeader = Convert.ToBase64String(
                Encoding.ASCII.GetBytes(
                    $"{ClientId}:{ClientSecret}"
                    )
                ); // Encode the Client ID and Client Secret to Base 64

            c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                clientHeader
                ); // Add the Authorization Header, now that it exists.

            using FormUrlEncodedContent formContent = new FormUrlEncodedContent(new[]
            { // See https://developer.spotify.com/documentation/general/guides/authorization-guide/
                new KeyValuePair <string, string>("grant_type", "authorization_code"),
                new KeyValuePair <string, string>("redirect_uri", RedirectUrl),
                new KeyValuePair <string, string>("code", code),
            }); // Create a new FormContent to give to spotify.

            HttpResponseMessage r = await c.PostAsync(
                new Uri("token", UriKind.Relative),                                       // This is a Uri object instead of a string so VS can stop complaining.
                formContent
                ).ConfigureAwait(false);                                                  // Post it over to spotify.

            string s = await r.Content.ReadAsStringAsync().ConfigureAwait(false);         // Await the result response.

            AccessAuthToken content = JsonConvert.DeserializeObject <AccessAuthToken>(s); // Deserialize it to a AccessToken.

            return(content);
        }
        public async Task <ActionResult <string> > Callback([FromQuery] SpotifyLogin login)
        {
            if (login == null)
            { // If login is nil, throw a nil arg expection.
                _logger.LogError("Spotify Login Model is NULL", login);
                return(BadRequest("Input body is null"));
            }

            AccessAuthToken tok = await _auth.TransmutAuthCode(login.Code).ConfigureAwait(false); // Change that login code to an access token and refresh token.

            tok = await _auth.AssertValidLogin(tok, false).ConfigureAwait(false);                 // Make sure its valid.

            using HttpClient c = _cf.CreateClient("spotify");                                     // Create a new client to spotify.

            c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Bearer",
                tok.AccessToken
                );                                                                                            // Now you are thinking with Bearers.

            HttpResponseMessage me = await c.GetAsync(new Uri("me", UriKind.Relative)).ConfigureAwait(false); // Get the Auth Users information.

            string response = await me.Content.ReadAsStringAsync().ConfigureAwait(false);                     // Make it a string.

            SpotifyIdentity identify = JsonConvert.DeserializeObject <SpotifyIdentity>(response);             // Make it a SpotifyIdentity.

            User host = await _userManager.GetUserAsync(HttpContext.User).ConfigureAwait(false);

            if (host == null)
            { // If not, reject
                return(BadRequest(new { Success = false, Error = "User has not yet registered with the Identity Provider." }));
            }

            // If so, update the tokens.
            host.Token = tok;

            if (host.IsHost())
            {
                if (host.Party == null)
                {
                    host.Party = _context.Parties.Where(p => p.PartyHost == host || p.PartyHostId == host.Id).FirstOrDefault();
                }

                // Disband Party.
                host.Party.PartyMembers.Clear();
                host.Party.KickedMembers.Clear();
                _context.Parties.Remove(host.Party);
                host.Party   = null;
                host.PartyId = null;
            }

            if (host.IsInParty())
            {
                // Leave Party.
                host.Party.PartyMembers.Remove(host);
                host.Party   = null;
                host.PartyId = null;
            }

            Party party = new Party
            { // Create a new party with this user as a host.
                JoinCode      = _rand.Next(0, 100000).ToString(CultureInfo.InvariantCulture).PadLeft(6, '0'),
                PartyHost     = host,
                AllowExplicit = true
                                // PartyMembers = new List<User> { host },
            };

            host.Party   = party;
            host.PartyId = party.Id;

            _context.Parties.Add(party);

            _context.SaveChanges(); // Kommit to DB.

            if (!await _playback.BeginPlayback(host).ConfigureAwait(false))
            {
                return(Ok(new { Success = false, Error = "Cannot start the party on Spotify" }));
            }

            return(Ok(new { Success = true, party.JoinCode })); // Return Party Join Code.
        }