Beispiel #1
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            var queryBuilder = new QueryBuilder()
            {
                { "grant_type", "authorization_code" },
                { "code", code },
                { "redirect_uri", redirectUri },
                { "client_id", Options.AppId },
                { "client_secret", Options.AppSecret },
            };

            var response = await Backchannel.GetAsync(Options.TokenEndpoint + queryBuilder.ToString(), Context.RequestAborted);

            response.EnsureSuccessStatusCode();

            var form    = new FormCollection(FormReader.ReadForm(await response.Content.ReadAsStringAsync()));
            var payload = new JObject();

            foreach (string key in form.Keys)
            {
                payload.Add(string.Equals(key, "expires", StringComparison.OrdinalIgnoreCase) ? "expires_in" : key, (string)form[key]);
            }

            // The refresh token is not available.
            return(new OAuthTokenResponse(payload));
        }
Beispiel #2
0
    /// <inheritdoc />
    public Task <bool> HandleStubGenerationAsync(HttpRequestModel request, StubConditionsModel conditions)
    {
        var pair = request.Headers.FirstOrDefault(p =>
                                                  p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
        var contentType = pair.Value;

        if (string.IsNullOrWhiteSpace(contentType))
        {
            return(Task.FromResult(false));
        }

        var supportedContentTypes = new[] { Constants.UrlEncodedFormMime, Constants.MultipartFormDataMime };

        if (
            !supportedContentTypes.Any(sc => contentType.StartsWith(sc, StringComparison.OrdinalIgnoreCase)) ||
            string.IsNullOrWhiteSpace(request.Body))
        {
            return(Task.FromResult(false));
        }

        // If the body condition is already set, clear it here.
        conditions.Body = Array.Empty <string>();

        var reader = new FormReader(request.Body);
        var form   = reader.ReadForm();

        conditions.Form = form.Select(f => new StubFormModel
        {
            Key   = f.Key,
            Value = f.Value
        });

        return(Task.FromResult(true));
    }
Beispiel #3
0
        public Task <bool> HandleStubGenerationAsync(RequestResultModel request, StubModel stub)
        {
            var pair = request.RequestParameters.Headers.FirstOrDefault(p =>
                                                                        p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
            var contentType = pair.Value;

            if (string.IsNullOrWhiteSpace(contentType))
            {
                return(Task.FromResult(false));
            }

            if (!contentType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase))
            {
                return(Task.FromResult(false));
            }

            // If the body condition is already set, clear it here.
            stub.Conditions.Body = new string[0];

            var reader = new FormReader(request.RequestParameters.Body);
            var form   = reader.ReadForm();

            stub.Conditions.Form = form.Select(f => new StubFormModel
            {
                Key   = f.Key,
                Value = f.Value
            });

            return(Task.FromResult(true));
        }
Beispiel #4
0
 public static IDictionary <string, string> ReadFormString(string queryString, bool unescapeDataString = true)
 {
     using (FormReader reader = new FormReader(queryString))
     {
         var collection = new FormCollection(reader.ReadForm());
         Dictionary <string, string> result = new Dictionary <string, string>(collection.Count);
         foreach (var kv in collection)
         {
             result[kv.Key] = Uri.UnescapeDataString(kv.Value);
         }
         return(result);
     }
 }
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri)
        {
            log.LogDebug("ExchangeCodeAsync called with code " + code + " redirectUri " + redirectUri);
            //var queryBuilder = new QueryBuilder()
            //{
            //    { "grant_type", "authorization_code" },
            //    { "code", code },
            //    { "redirect_uri", redirectUri },
            //    { "client_id", Options.AppId },
            //    { "client_secret", Options.AppSecret },
            //};

            var currentSite = await GetSite();

            var tenantFbOptions
                = new MultiTenantFacebookOptionsResolver(
                      Options,
                      currentSite,
                      multiTenantOptions);


            var queryBuilder = new QueryBuilder()
            {
                { "grant_type", "authorization_code" },
                { "code", code },
                { "redirect_uri", tenantFbOptions.ResolveRedirectUrl(redirectUri) },
                { "client_id", tenantFbOptions.AppId },
                { "client_secret", tenantFbOptions.AppSecret },
            };

            var response = await Backchannel.GetAsync(Options.TokenEndpoint + queryBuilder.ToString(), Context.RequestAborted);

            response.EnsureSuccessStatusCode();

            var form    = new FormCollection(FormReader.ReadForm(await response.Content.ReadAsStringAsync()));
            var payload = new JObject();

            foreach (string key in form.Keys)
            {
                //payload.Add(string.Equals(key, "expires", StringComparison.OrdinalIgnoreCase) ? "expires_in" : key, form[key]);
                payload.Add(string.Equals(key, "expires", StringComparison.OrdinalIgnoreCase) ? "expires_in" : key, (string)form[key]);
            }

            // The refresh token is not available.
            return(new OAuthTokenResponse(payload));
        }
Beispiel #6
0
        private async Task <AccessToken> ObtainAccessTokenAsync(string consumerKey, string consumerSecret, RequestToken token, string verifier)
        {
            // https://dev.twitter.com/docs/api/1/post/oauth/access_token

            Logger.LogVerbose("ObtainAccessToken");

            var nonce = Guid.NewGuid().ToString("N");

            var authorizationParts = new SortedDictionary <string, string>
            {
                { "oauth_consumer_key", consumerKey },
                { "oauth_nonce", nonce },
                { "oauth_signature_method", "HMAC-SHA1" },
                { "oauth_token", token.Token },
                { "oauth_timestamp", GenerateTimeStamp() },
                { "oauth_verifier", verifier },
                { "oauth_version", "1.0" },
            };

            var parameterBuilder = new StringBuilder();

            foreach (var authorizationKey in authorizationParts)
            {
                parameterBuilder.AppendFormat("{0}={1}&", UrlEncoder.UrlEncode(authorizationKey.Key), UrlEncoder.UrlEncode(authorizationKey.Value));
            }
            parameterBuilder.Length--;
            var parameterString = parameterBuilder.ToString();

            var canonicalizedRequestBuilder = new StringBuilder();

            canonicalizedRequestBuilder.Append(HttpMethod.Post.Method);
            canonicalizedRequestBuilder.Append("&");
            canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(AccessTokenEndpoint));
            canonicalizedRequestBuilder.Append("&");
            canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(parameterString));

            var signature = ComputeSignature(consumerSecret, token.TokenSecret, canonicalizedRequestBuilder.ToString());

            authorizationParts.Add("oauth_signature", signature);
            authorizationParts.Remove("oauth_verifier");

            var authorizationHeaderBuilder = new StringBuilder();

            authorizationHeaderBuilder.Append("OAuth ");
            foreach (var authorizationPart in authorizationParts)
            {
                authorizationHeaderBuilder.AppendFormat(
                    "{0}=\"{1}\", ", authorizationPart.Key, UrlEncoder.UrlEncode(authorizationPart.Value));
            }
            authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2;

            var request = new HttpRequestMessage(HttpMethod.Post, AccessTokenEndpoint);

            request.Headers.Add("Authorization", authorizationHeaderBuilder.ToString());

            var formPairs = new Dictionary <string, string>()
            {
                { "oauth_verifier", verifier },
            };

            request.Content = new FormUrlEncodedContent(formPairs);

            var response = await _httpClient.SendAsync(request, Context.RequestAborted);

            if (!response.IsSuccessStatusCode)
            {
                Logger.LogError("AccessToken request failed with a status code of " + response.StatusCode);
                response.EnsureSuccessStatusCode(); // throw
            }

            var responseText = await response.Content.ReadAsStringAsync();

            var responseParameters = new FormCollection(FormReader.ReadForm(responseText));

            return(new AccessToken
            {
                Token = Uri.UnescapeDataString(responseParameters["oauth_token"]),
                TokenSecret = Uri.UnescapeDataString(responseParameters["oauth_token_secret"]),
                UserId = Uri.UnescapeDataString(responseParameters["user_id"]),
                ScreenName = Uri.UnescapeDataString(responseParameters["screen_name"])
            });
        }
Beispiel #7
0
        private async Task <RequestToken> ObtainRequestTokenAsync(string consumerKey, string consumerSecret, string callBackUri, AuthenticationProperties properties)
        {
            Logger.LogVerbose("ObtainRequestToken");

            var nonce = Guid.NewGuid().ToString("N");

            var authorizationParts = new SortedDictionary <string, string>
            {
                { "oauth_callback", callBackUri },
                { "oauth_consumer_key", consumerKey },
                { "oauth_nonce", nonce },
                { "oauth_signature_method", "HMAC-SHA1" },
                { "oauth_timestamp", GenerateTimeStamp() },
                { "oauth_version", "1.0" }
            };

            var parameterBuilder = new StringBuilder();

            foreach (var authorizationKey in authorizationParts)
            {
                parameterBuilder.AppendFormat("{0}={1}&", UrlEncoder.UrlEncode(authorizationKey.Key), UrlEncoder.UrlEncode(authorizationKey.Value));
            }
            parameterBuilder.Length--;
            var parameterString = parameterBuilder.ToString();

            var canonicalizedRequestBuilder = new StringBuilder();

            canonicalizedRequestBuilder.Append(HttpMethod.Post.Method);
            canonicalizedRequestBuilder.Append("&");
            canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(RequestTokenEndpoint));
            canonicalizedRequestBuilder.Append("&");
            canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(parameterString));

            var signature = ComputeSignature(consumerSecret, null, canonicalizedRequestBuilder.ToString());

            authorizationParts.Add("oauth_signature", signature);

            var authorizationHeaderBuilder = new StringBuilder();

            authorizationHeaderBuilder.Append("OAuth ");
            foreach (var authorizationPart in authorizationParts)
            {
                authorizationHeaderBuilder.AppendFormat(
                    "{0}=\"{1}\", ", authorizationPart.Key, UrlEncoder.UrlEncode(authorizationPart.Value));
            }
            authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2;

            var request = new HttpRequestMessage(HttpMethod.Post, RequestTokenEndpoint);

            request.Headers.Add("Authorization", authorizationHeaderBuilder.ToString());

            var response = await _httpClient.SendAsync(request, Context.RequestAborted);

            response.EnsureSuccessStatusCode();
            string responseText = await response.Content.ReadAsStringAsync();

            var responseParameters = new FormCollection(FormReader.ReadForm(responseText));

            if (string.Equals(responseParameters["oauth_callback_confirmed"], "true", StringComparison.Ordinal))
            {
                return(new RequestToken {
                    Token = Uri.UnescapeDataString(responseParameters["oauth_token"]), TokenSecret = Uri.UnescapeDataString(responseParameters["oauth_token_secret"]), CallbackConfirmed = true, Properties = properties
                });
            }

            return(new RequestToken());
        }
        public async Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var request = bindingContext.HttpContext.Request;

            if (request.ContentType != null)
            {
                var contentType = MediaTypeHeaderValue.Parse(request.ContentType);
                if (contentType.MediaType == BinarySerializer.MEDIA_TYPE)
                {
                    bindingContext.Result = ModelBindingResult.Success(await DeserializeBinary(request.Body, bindingContext));
                    return;
                }
                else if (contentType.MediaType == "multipart/form-data")
                {
                    object obj = null;

                    if (contentType.Boundary == null)
                    {
                        throw new InvalidOperationException("MultiPartBoundary not found");
                    }

                    var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary).Value;

                    var reader  = new MultipartReader(boundary, request.Body);
                    var section = await reader.ReadNextSectionAsync();

                    while (section != null)
                    {
                        ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                        MediaTypeHeaderValue.TryParse(section.ContentType, out contentType);

                        if (contentDisposition == null)
                        {
                            continue;
                        }

                        if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            //json body
                            if (contentType?.MediaType == "application/json")
                            {
                                var json = await section.ReadAsStringAsync();

                                obj = JsonConvert.DeserializeObject(json, bindingContext.ModelType);
                            }
                            else if (contentType?.MediaType == BinarySerializer.MEDIA_TYPE)
                            {
                                obj = await DeserializeBinary(section.Body, bindingContext);
                            }
                            else
                            {
                                obj ??= Activator.CreateInstance(bindingContext.ModelType);

                                //form value
                                var sectionValue = await section.AsFormDataSection().GetValueAsync();

                                var formReader = new FormReader(sectionValue);
                                var form       = formReader.ReadForm();

                                if (form.Count == 0)
                                {
                                    if (contentDisposition.Name != null)
                                    {
                                        SetValue(bindingContext, obj, sectionValue, contentDisposition.Name.Value);
                                    }
                                }
                                else
                                {
                                    foreach (var value in form)
                                    {
                                        SetValue(bindingContext, obj, value.Value.ToString(), value.Key);
                                    }
                                }
                            }
                        }
                        else if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            var stream = new MemoryStream();
                            await section.AsFileSection().FileStream.CopyToAsync(stream);

                            stream.Position = 0;

                            if (bindingContext.ModelType == typeof(Stream))
                            {
                                obj = stream;
                            }
                            else
                            {
                                obj ??= Activator.CreateInstance(bindingContext.ModelType);
                                SetValue(bindingContext, obj, stream, contentDisposition.Name.Value);
                            }
                        }

                        section = await reader.ReadNextSectionAsync();
                    }

                    bindingContext.Result = ModelBindingResult.Success(obj);
                    return;
                }
                else
                {
                    bindingContext.Result = ModelBindingResult.Failed();
                    return;
                }
            }
            else if (bindingContext.ModelType == typeof(Stream))
            {
                bindingContext.Result = ModelBindingResult.Success(request.Body);
                return;
            }

            bindingContext.Result = ModelBindingResult.Failed();
        }
    public async Task PkceSentToTokenEndpoint()
    {
        using var host = await CreateHost(o =>
        {
            o.ClientId               = "Test Client Id";
            o.ClientSecret           = "Test Client Secret";
            o.BackchannelHttpHandler = new TestHttpMessageHandler
            {
                Sender = req =>
                {
                    if (req.RequestUri.AbsoluteUri == "https://login.microsoftonline.com/common/oauth2/v2.0/token")
                    {
                        var body    = req.Content.ReadAsStringAsync().Result;
                        var form    = new FormReader(body);
                        var entries = form.ReadForm();
                        Assert.Equal("Test Client Id", entries["client_id"]);
                        Assert.Equal("https://example.com/signin-microsoft", entries["redirect_uri"]);
                        Assert.Equal("Test Client Secret", entries["client_secret"]);
                        Assert.Equal("TestCode", entries["code"]);
                        Assert.Equal("authorization_code", entries["grant_type"]);
                        Assert.False(string.IsNullOrEmpty(entries["code_verifier"]));

                        return(ReturnJsonResponse(new
                        {
                            access_token = "Test Access Token",
                            expire_in = 3600,
                            token_type = "Bearer",
                        }));
                    }
                    else if (req.RequestUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped) == "https://graph.microsoft.com/v1.0/me")
                    {
                        return(ReturnJsonResponse(new
                        {
                            id = "Test User ID",
                            displayName = "Test Name",
                            givenName = "Test Given Name",
                            surname = "Test Family Name",
                            mail = "Test email"
                        }));
                    }

                    return(null);
                }
            };
        });

        using var server = host.GetTestServer();
        var transaction = await server.SendAsync("https://example.com/challenge");

        Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
        var locationUri = transaction.Response.Headers.Location;

        Assert.StartsWith("https://login.microsoftonline.com/common/oauth2/v2.0/authorize", locationUri.AbsoluteUri);

        var queryParams = QueryHelpers.ParseQuery(locationUri.Query);

        Assert.False(string.IsNullOrEmpty(queryParams["code_challenge"]));
        Assert.Equal("S256", queryParams["code_challenge_method"]);

        var nonceCookie = transaction.SetCookie.Single();

        nonceCookie = nonceCookie.Substring(0, nonceCookie.IndexOf(';'));

        transaction = await server.SendAsync(
            "https://example.com/signin-microsoft?code=TestCode&state=" + queryParams["state"],
            nonceCookie);

        Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
        Assert.Equal("/me", transaction.Response.Headers.GetValues("Location").First());
        Assert.Equal(2, transaction.SetCookie.Count);
        Assert.StartsWith(".AspNetCore.Correlation.", transaction.SetCookie[0]);
        Assert.StartsWith(".AspNetCore." + TestExtensions.CookieAuthenticationScheme, transaction.SetCookie[1]);
    }
Beispiel #10
0
 protected virtual Task <Dictionary <string, StringValues> > ReadFormAsync(FormReader reader)
 {
     return(Task.FromResult(reader.ReadForm()));
 }