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. }