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)); }
/// <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)); }
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)); }
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)); }
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"]) }); }
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]); }
protected virtual Task <Dictionary <string, StringValues> > ReadFormAsync(FormReader reader) { return(Task.FromResult(reader.ReadForm())); }