예제 #1
0
        private async Task <Uri> GetRelativeUriAsync(IEnumerable <object> additionalRouteValues, object queryParams, CancellationToken cancellationToken)
        {
            var routeValues             = this.routeValues.Concat(additionalRouteValues ?? Enumerable.Empty <object>()).ToList();
            var destructuredQueryParams = this.DestructureQueryParamsObjectRecursively(queryParams).Where(item => item.Value != null).ToList();

            bool transformRouteValues    = false;
            bool transformQueryParamters = false;

            if ((transformRouteValues = routeValues.Any(x => x is CurrentUserIdPlaceholder)) || (transformQueryParamters = destructuredQueryParams.Any(x => x.Value is CurrentUserIdPlaceholder)))
            {
                var currentUser = await this.contextData.CurrentUserProvider.GetAsync(cancellationToken).ConfigureAwait(false);

                if (transformRouteValues)
                {
                    routeValues = routeValues.Select(x => x is CurrentUserIdPlaceholder ? currentUser.Id : x).ToList();
                }

                if (transformQueryParamters)
                {
                    destructuredQueryParams = destructuredQueryParams
                                              .Select(x => x.Value is CurrentUserIdPlaceholder ? new KeyValuePair <string, object>(x.Key, currentUser.Id) : x)
                                              .ToList();
                }
            }

            var result = SpotifyUriUtils.GetRelativeUri(routeValues, destructuredQueryParams);

            return(result);
        }
        private async Task <AuthorizationResult> AuthorizeInnerAsync(string codeChallenge, CancellationToken cancellationToken)
        {
            var authorizationOptions = this.authorizationOptionsProvider.Get();
            var originalCsrfToken    = this.csfrTokenProvider.Get();
            var redirectUri          = this.authorizationRedirectUriProvider.Get();

            var queryParams = new List <KeyValuePair <string, object> >
            {
                new KeyValuePair <string, object>("client_id", authorizationOptions.ClientId),
                new KeyValuePair <string, object>("response_type", "code"),
                new KeyValuePair <string, object>("scope", string.Join(" ", authorizationOptions.Scopes ?? Enumerable.Empty <string>())),
                new KeyValuePair <string, object>("show_dialog", authorizationOptions.ShowDialog),
                new KeyValuePair <string, object>("state", originalCsrfToken),
                new KeyValuePair <string, object>("redirect_uri", redirectUri)
            };

            if (codeChallenge != null)
            {
                queryParams.Add(new KeyValuePair <string, object>("code_challenge_method", "S256"));
                queryParams.Add(new KeyValuePair <string, object>("code_challenge", codeChallenge));
            }

            var authenticationUriBuilder = new UriBuilder(authorizationOptions.AuthorizationEndpoint)
            {
                Query = SpotifyUriUtils.GetQueryString(queryParams)
            };

            var enrichedRedirectUri = await this.authorizationInteractionClient.AuthorizeAsync(
                authenticationUriBuilder.Uri,
                redirectUri,
                cancellationToken).ConfigureAwait(false);

            var redirectQueryParams = HttpUtility.ParseQueryString(enrichedRedirectUri.Query);

            var states = redirectQueryParams.GetValues("state") ?? Array.Empty <string>();

            if (states.Length != 1 || states.First() != originalCsrfToken)
            {
                throw new SpotifyAuthorizationException("Invalid state has been returned from the Spotify Accounts Service.");
            }

            var error = redirectQueryParams.GetValues("error")?.FirstOrDefault();

            if (!string.IsNullOrEmpty(error))
            {
                throw new SpotifyAuthorizationException($"Error '{error}' has been returned from the Spotify Accounts Service.");
            }

            var codes = redirectQueryParams.GetValues("code") ?? Array.Empty <string>();

            if (codes.Length != 1 || string.IsNullOrEmpty(codes.First()))
            {
                throw new SpotifyAuthorizationException("An invalid authorization code has been returned from the Spotify Accounts Service.");
            }

            return(new AuthorizationResult(codes.First(), redirectUri));
        }
        private string GetCodeChallenge(string codeVerifier)
        {
            byte[] hash;
            using (var sha256 = SHA256.Create())
            {
                hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
            }

            return(SpotifyUriUtils.ConvertToBase64UriString(hash));
        }
예제 #4
0
        public string Get()
        {
            var bytes = new byte[32];

            using (var rng = new RNGCryptoServiceProvider())
            {
                rng.GetBytes(bytes);
            }

            return(SpotifyUriUtils.ConvertToBase64UriString(bytes));
        }
예제 #5
0
        public void ShouldGetRelativeUri()
        {
            // Arrange
            var routeValues = new object[] { "value1", 123, "value?2" };

            var queryParams = new List <KeyValuePair <string, object> >
            {
                new KeyValuePair <string, object>("key1", "value1"),
                new KeyValuePair <string, object>("ke 1", new Uri("http://localhost/te%20st?ke%201=test%20value&key2=value2"))
            };

            // Act
            var result = SpotifyUriUtils.GetRelativeUri(routeValues, queryParams);

            // Assert
            result.Should().Be("value1/123/value%3F2?key1=value1&ke%201=http%3A%2F%2Flocalhost%2Fte%2520st%3Fke%25201%3Dtest%2520value%26key2%3Dvalue2");
        }
예제 #6
0
 public void ShouldConvertToBase64UriString()
 {
     // Arrange + Act + Assert
     SpotifyUriUtils.ConvertToBase64UriString(Encoding.UTF8.GetBytes("Test")).Should().Be("VGVzdA");
 }