Getting 400 bad request when I use "ValidateAntiForgeryToken" and "Authorize" - xamarin

I'm using asp.net core in the server side and xamarin in the client side.I use JWT token and I want to validate forgery token at the same time.
This is my client side code :
public async Task<string> PostAsync(object model, string url)
{
var cookieContainer = new CookieContainer();
var handlerhttps = new HttpClientHandler
{
UseCookies = true,
UseDefaultCredentials = true,
CookieContainer = cookieContainer
};
var clientPage = new HttpClient(handler: handlerhttps)
{
BaseAddress = new Uri(uriString: Application.Current.Resources[index: "Domain"] + "/api/token")
};
var pageWithToken = await clientPage.GetAsync(requestUri: clientPage.BaseAddress);
var verificationToken = await pageWithToken.Content.ReadAsStringAsync();
using (var handler = new HttpClientHandler
{
CookieContainer = cookieContainer,
UseDefaultCredentials = true,
UseCookies = true
})
{
using (var client = new HttpClient(handler: handler) {BaseAddress = new Uri(uriString: url)})
{
client.DefaultRequestHeaders.Add(name: "RequestVerificationToken", value: verificationToken);
if (Application.Current.Properties[key: "Token"] != null)
{
var token = Application.Current.Properties[key: "Token"].ToString();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(scheme: "Bearer", parameter: token);
}
var json = JsonConvert.SerializeObject(value: model);
var content = new StringContent(content: json, encoding: Encoding.UTF8,
mediaType: "application/json");
var response = await client.PostAsync(requestUri: client.BaseAddress, content: content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
}
My problem is when I use [ValidateAntiForgeryToken] and [Authorize] in the server side at the same time, I get 400 bad request.
But when I remove [ValidateAntiForgeryToken], It will authorize without any problem.
When I remove [Authorize] , I don't get 400 bad request and it validate forgery token successfully.
I don't know how to solve this problem.

If you are using Microsoft.AspNetCore.Mvc.TagHelpers it will add a input field with a 'difficult to guess' code:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8PXv-VNSuRBLvOlUgHlQcf4p8B29vW6EKn4ENesSgHR79kWTvbnQ9a1Taj90b-e66-79H7Nx5ljHnvPbwqfSNqHMRMaBkoRKGsTxtbZZlq0rSl2zbGK2aKpPQc0qnoNuRehSNhP097P5-Vlp-3OSPYdIqLQJSqIsPDaQsEOXsNU4qIIDrj-tIhqk5EW9tTYc6g">
Anyways, even if you add #Html.AntiForgeryToken() it wouldn't conflict. However you cannot decorate the 'first' controller action with [ValidateAntiForgeryToken], only the final one with will get the POST.
Example:
Action 1
[HttpPost]
[AllowAnonymous]
[ActionName("SpecialSignUp")]
public IActionResult Index([FromForm] string email)
{
// TODO : code in here
return View(email);
}
Users will be redirect to above action through a POST.
Let's say that the view above displays a form with the email field pre-filled and other fields to be filled.
If you decorate it with [ValidateAntiForgeryToken] you will get a 400 (Bad Request). Removing it, all will be fine.
Action 2
[HttpPost]
[AllowAnonymous] // It could be [Authorized]
[ActionName("SpecialSignUp")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LaunchSignUpAsync([FromForm] SpecialSignUpViewModel model)
{
// TODO : Code in here
return RedirectToAction("OtherActionX", data);
}
Form will be posted by the above View
Now all it's working, no conflict is happening anymore. If you respect that sequence, it will work for you!
I had the same issue, and it was happening because I decorated the 'Action 1' with [ValidateAntiForgeryToken] as well.
Hopefully it helps!

I faced a similar issue but got it resolved by adding "RequestVerificationToken" on my request
My controller code (sample)
HttpPost("SignOut")
Authorize ==> using JWT
ValidateAntiForgeryToken
*/

You can try making a custom method for validation of JWT token to replace the
[Authorize] by
public void ValidateJWT(string token, out bool status)
{
if (token == null)
{
status = false;
}
byte[] secretKey = System.Text.Encoding.UTF8.GetBytes("your jwt secret key");
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(secretKey),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
status = true;
}
catch
{
status = false;
}
}

Related

How to Fetch Access token from my custom controller in asp.net web api 2

I have implemented the code for generating access token.I am able to get the token from default Token End Point Path(https://localhost:44312/token) when trying to get it from Postman.
However I want to implement Login Controller which internally should call the default token end point and send the response.
public async Task<IHttpActionResult> Login(UserModel userModel)
{
HttpResponseMessage response;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44312/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("cache-control", "no-cache");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
userModel.grant_type = "password";
var parameters = new Dictionary<string, string> { { "username", userModel.UserName }, { "password", userModel.Password }, { "grant_type", "password" } };
var encodedContent = new FormUrlEncodedContent(parameters);
response = client.PostAsync("/token", encodedContent).Result;
}
return Ok(response);
}
I get an httpstatus OK response but not the access token. Any guidance in solving the issue would be helpful.

Return an HttpResponse in an APIController Method which calls a different API

I have an APIController Method as below. Basically I need to validate an API response. So it's an API call within an API call.
public class DCController : ApiController
{
[HttpPost]
public HttpResponseMessage SampleMethod(string url)
{
var uri = new Uri(url);
var baseAddress = uri.GetLeftPart(System.UriPartial.Authority);
var apiAddress = url.Replace(baseAddress + "/", "");
var responseString = string.Empty;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(apiAddress).Result;
if (response.IsSuccessStatusCode)
{
responseString = response.Content.ReadAsStringAsync().Result;
}
}
if (!string.IsNullOrEmpty(responseString) && responseString.ToString().Validate())
{
return Request.CreateResponse(HttpStatusCode.OK, "Validated");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid");
}
}
Issue:
1. Request object is null in the return lines.
2. If i try creating a request object -
var request = new HttpRequestMessage();
It throws below error:
An exception of type 'System.InvalidOperationException' occurred in
System.Web.Http.dll but was not handled in user code
Additional information: The request does not have an associated
configuration object or the provided configuration was null.
Not sure what settings I need to add. I am relatively new to working with APIs. Any help is appreciated.
I could get it working by below code -
[HttpPost]
public HttpResponseMessage Get(string url)
{
string responseString = GetWebApiData(url); //Extracted the method
HttpResponseMessage response = new HttpResponseMessage();
if (!string.IsNullOrEmpty(responseString) && responseString.ToString().Validate())
{
response.ReasonPhrase = "Valid";
response.StatusCode = HttpStatusCode.OK;
}
else
{
response.ReasonPhrase = "Invalid";
response.StatusCode = HttpStatusCode.BadRequest;
}
return response;
}

Resharpe.portable get Twitter request token

Hello i'm doing an xamarin.form application and i'm implementing the twitter login using oauth.
I have problem to get the request_token folowing the link:
https://dev.twitter.com/oauth/reference/post/oauth/request_token
using restsharp.portable for the request POST i arrive at this point:
public async void GetTwitterToken()
{
try
{
TwitterLogin tw = new TwitterLogin();
RestClient client = new RestClient("https://api.twitter.com");
RestRequest request = new RestRequest("/oauth/request_token", Method.POST);
client.Authenticator = OAuth1Authenticator.ForRequestToken(tw.oauth_consumer_key, tw.oauth_consumer_secret);
IRestResponse response = await client.Execute(request);
}
catch (Exception e)
{
}
}
Parameter "response" it's ok but i'don't know how to parse to get token (it's not json).
i have seen this example:
public void GetRequestToken()
{
var client = new RestClient("https://api.twitter.com"); // Note NO /1
client.Authenticator = OAuth1Authenticator.ForRequestToken(
_consumerKey,
_consumerSecret,
"http://markashleybell.com" // Value for the oauth_callback parameter
);
var request = new RestRequest("/oauth/request_token", Method.POST);
var response = client.Execute(request);
var qs = HttpUtility.ParseQueryString(response.Content);
_token = qs["oauth_token"];
_tokenSecret = qs["oauth_token_secret"];
}
But i don't have HttpUtility.ParseQueryString(response.Content) whith xamarin.form framework

Retrieve userId and send private message with linqtotwitter

I want to send private message to Twitter with my web app in asp.net mvc3. I was doing the authorization with oauth, here is my code:
in AccountController:
public ActionResult LogOn()
{
credentials.ConsumerKey = TwitterClient.ConsumerKey;
credentials.ConsumerSecret = TwitterClient.ConsumerSecret;
auth = new MvcAuthorizer { Credentials = credentials };
auth.CompleteAuthorization(Request.Url);
if (!auth.IsAuthorized)
{
string callbackUrl = "http://127.0.0.1:31891/Account/CompleteAuth";
Uri uri = new Uri(callbackUrl);
return auth.BeginAuthorization(uri);
}
return RedirectToAction("Index", "Home");
}
After the user is authorized , he is redirect to action CompleteAuth, and I get the token and tokenSecret, here is code of this action:
public ActionResult CompleteAuth(string oauth_token, string oauth_verifier)
{
string AccessToken = oauth_token;
string AccessTokenSecret = oauth_verifier;
TempData["AccessToken"] = AccessToken;
TempData["TokenSecret"] = AccessTokenSecret;
return RedirectToAction("Tweeting","Home");
}
after, it's redirect to Home in action Tweeting, when i try to get userId and send to him direct message :
public ActionResult Tweeting()
{
var auth = new MvcAuthorizer
{
Credentials = new InMemoryCredentials()
{
ConsumerKey = TwitterClient.ConsumerKey,
ConsumerSecret = TwitterClient.ConsumerSecret,
//OAuthToken = (string)Session["AccessToken"],
//AccessToken = Session["TokenSecret"]
OAuthToken = TempData["AccessToken"] as string,
AccessToken = TempData["TokenSecret"] as string
}
};
var twitterContext = new TwitterContext(auth);
var message = twitterContext.NewDirectMessage(auth.UserId, "Hi ucef, cool to discuss with you" + DateTime.Now);
return View();
}
But exception occurred because auth.UserId is null, have you any idea?
This appears to be the same as your previous question:
Send Private message with LinqToTwitter
Joe

Using an MVC Action Filter to catch redirects in Ajax requests and return a JsonResult

In my ASP.NET MVC 3 application, I have some action methods that can be invoked with Ajax and non-Ajax requests. The action methods may return a RedirectResult and I want the target URL to be loaded in the browser - even for Ajax requests.
My current solution is for the action method to call IsAjaxRequest itself. If false, it returns a RedirectResult. If true, it returns a JsonResult containing the target URL, and I have script in the browser to read this and set window.location accordingly.
I was hoping to declutter the action methods and handle this in a filter. My problem is that the target URL (filterContext.HttpContext.Response.RedirectLocation) is null in the filter event handlers other than OnResultExecuted, and setting filterContext.Result in that handler (and changing response.StatusCode) doesn't succeed in issuing JSON in the response.
If I use one of the other handlers, such as OnActionExecuted, I can change the response to issue JSON, but cannot get hold of the target URL.
A 2-step process does not work either - if I change the result to a JsonResult in OnActionExecuted, the RedirectLocation is null in OnResultExecuted.
Can anyone recreate this problem or recommend a better solution? Thanks.
PS here is the code from OnResultExecuted:
if ((filterContext.Result is RedirectToRouteResult ||
filterContext.Result is RedirectResult) &&
filterContext.HttpContext.Request.IsAjaxRequest())
{
string url = filterContext.HttpContext.Response.RedirectLocation;
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
filterContext.HttpContext.Response.RedirectLocation = "";
filterContext.Result = new JsonResult
{
Data = new { Redirect = url },
ContentEncoding = System.Text.Encoding.UTF8,
ContentType = "application/json",
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
Here's an example of how you could proceed:
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
string url = "/";
var redirectResult = filterContext.Result as RedirectResult;
if (filterContext.Result is RedirectResult)
{
// It was a RedirectResult => we need to calculate the url
var result = filterContext.Result as RedirectResult;
url = UrlHelper.GenerateContentUrl(result.Url, filterContext.HttpContext);
}
else if (filterContext.Result is RedirectToRouteResult)
{
// It was a RedirectToRouteResult => we need to calculate
// the target url
var result = filterContext.Result as RedirectToRouteResult;
url = UrlHelper.GenerateUrl(result.RouteName, null, null, result.RouteValues, RouteTable.Routes, filterContext.RequestContext, false);
}
filterContext.Result = new JsonResult
{
Data = new { Redirect = url },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
// TODO: It is not an AJAX request => do whatever you were doing
}
}

Resources