ASP.NET MVC Authorize Attribute does a 302 redirect when the user is not authorized - asp.net-mvc-2

MSDN explicitly says it should do 401 redirect, but I'm getting a 302 redirect on FF, and this is causing problems in AJAX requests as the returned status is 200 (from the redirected page).
http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx
I've found someone else with the same problem:
http://blog.nvise.com/?p=26
Any other solution, besides his?

I really like this solution. By changing the 302 response on ajax requests to a 401 it allows you to setup your ajax on the client side to monitor any ajax request looking for a 401 and if it finds one to redirect to the login page. Very simple and effective.
Global.asax:
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 302 &&
Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
{
Context.Response.Clear();
Context.Response.StatusCode = 401;
}
}
Client Side Code:
$(function () {
$.ajaxSetup({
statusCode: {
401: function () {
location.href = '/Logon.aspx?ReturnUrl=' + location.pathname;
}
}
});
});

The Authorize attribute does return a Http 401 Unauthorized response. Unfortunately, however if you have FormsAuthentication enabled, the 401 is intercepted by the FormsAuthenticationModule which then performs a redirect to the login page - which then returns a Http 200 (and the login page) back to your ajax request.
The best alternative is to write your own authorization attribute, and then if you get an unauthenticated request that is also an Ajax request, return a different Http status code - say 403 - which is not caught by the formsAuthenticationModule and you can catch in your Ajax method.

I implemented my own custom authorize attribute which inherited from AuthorizeAttribute and ran into the same problem.
Then I found out that since .Net 4.5 there is a solution to this - you can suppress the redirect in the following way:
context.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
Then the response will be a 401 - Unauthorized, along with the HTTP Basic authentication challenge.
More info here

If you are using a ASP.NET MVC 5 Web Application go to App_Start -> Startup.Auth.cs. Check if app.UseCookieAuthentication is enabled and see if CookieAuthenticationOptions is set to LoginPath = new PathString("/Login"), or similar. If you remove this parameter 401 will stop redirecting.
Description for LoginPath:
The LoginPath property informs the middleware that it should change an
outgoing 401 Unauthorized status code into a 302 redirection onto the
given login path. The current url which generated the 401 is added to
the LoginPath as a query string parameter named by the
ReturnUrlParameter. Once a request to the LoginPath grants a new
SignIn identity, the ReturnUrlParameter value is used to redirect the
browser back to the url which caused the original unauthorized status
code. If the LoginPath is null or empty, the middleware will not look
for 401 Unauthorized status codes, and it will not redirect
automatically when a login occurs.

Related

Next.js webhook returns a 301 (redirect) instead of 200

I have a Next.js app and I created an endpoint to handle a webhook from a third-party payment application.
The code for that endpoint is very simple, it checks that the order was paid and updates my database:
export default async function WebhookHandler(req, res) {
if (req.method === 'POST') {
const requestData = JSON.parse(req)
if (requestData.status === "paid") {
// Code to update database
}
res.status(200).json({ received: true });
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method not allowed.');
}
}
The problem is that this webhook is falling. When I go to my payment application logs, I can see the webhook requests are going to the right endpoint, but my endpoint response is a 301 (redirect) and the payment application expects a 200.
Any ideas why Next.js is creating this redirect? I don't even know where to look for this...
After a lot of digging, I found that it was my server configuration. It was redirecting my www.site.com to site.com 🤦‍♂️

Redirect for HTTP POST does not work in SvelteKit

In SvelteKit I want to handle a post request and redirect to a route on success. This should be possible by sending a status code of 303 and the location header - as in the SvelteKit docs. Unfortunately, it does not work. In the Dev tools you see the 303 response, but the redirect is not handled. Of course, there are workarounds (for example, a redirect on the client, or directly post to the desired page), but I would like to know why this error happens.
Stackblitz: https://stackblitz.com/edit/sveltejs-kit-template-default-z9rs2c
index.svelte
<script>
function submit() {
fetch("/endpoint", {method: "POST"});
}
</script>
<button on:click={submit}>Click me</button>
endpoint.js
export function post() {
console.log('got post request at endpoint');
return {
status: 303,
headers: {
location: '/success'
}
};
}
success.svelte
<h2>Success</h2>
HTTP POST redirect is handled by web browsers only if you are using native <form method=POST> HTML construct.
You are using fetch() API, which is very different. Thus you need to handle the redirect yourself.
You can do this by extracting location from the fetch() response headers and then calling manually goto() from $app/navigation.

Facebook messenger platform webhook Verify Token not validated

I've created a facebook app on facebook developers
I've setup a local rails server and exposed it to public internet using ngrok. I'm receiving facebook's webhook validation GET request and I'm returning the hub_challenge code in response. The response status code is also 200. I've provided a secret Verify Token which is required to set up a messenger webhook. But after all this I'm getting error
The Callback URL or Verify Token couldn't be validated. Please verify
the provided information or try again later.
I've checked that the request is received and the response being sent back to the facebook server, but don't know why it fails and says Verify Token couldn't be validated. Is it some special token that I have to get from somewhere from facebook messenger platform? Currently I've provided it my own secret token. Any help will be appreciated. Thanks
when I verify Facebook Webhook with my website i got that kind error
The URL couldn't be validated. Response does not match challenge, expected value="1421256154", received="1421256154\u003Clink rel=..."
My code
public function verify_token(Request $request)
{
$mode = $request->get('hub_mode');
$token = $request->get('hub_verify_token');
$challenge = $request->get('hub_challenge');
if ($mode === "subscribe" && $this->token and $token === $this->token) {
return response($challenge,200);
}
return response("Invalid token!", 400);
}
my code everything is ok .I am using laravel thats why APP_DEBUG=true defalt when I change it APP_DEBUG=false its working and my problem solved.

Can't resolve Dropbox.com redirects with Axios or D3-fetch

I'm trying to fetch data in the browser from a Dropbox link: https://www.dropbox.com/s/101qhfi454zba9n/test.txt?dl=1
Using Axios this works in Node:
axios.get('https://www.dropbox.com/s/101qhfi454zba9n/test.txt?dl=1').then(x => {
console.log('Received correctly')
console.log(x.data);
}).catch(error => {
console.log('Error', error.message);
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
}
console.log(error)
});
https://runkit.com/stevebennett/5dc21d04bbc625001a38699b
However it doesn't work in the browser (click the "Console" tab):
https://codepen.io/stevebennett/pen/QWWmaBy
I just get a generic "Network Error". I see the 301 Redirect being retrieved, which seems perfectly normal, but for some reason, it is not followed.
Exactly the same happens with D3: "NetworkError when attempting to fetch resource."
https://codepen.io/stevebennett/pen/KKKoZYN
What is going on?
This appears to be failing because of the CORS policy. Trying this with XMLHttpRequest directly fails with:
Access to XMLHttpRequest at 'https://www.dropbox.com/s/101qhfi454zba9n/test.txt?dl=1' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS isn't allowed on www.dropbox.com itself.

How to POST to NetSuite custom record from external site?

I'm trying to integrate a very small custom web application with NetSuite. I want a custom record to be created in NetSuite whenever a user clicks a button in my web application.
I have written a RESTlet that works with the REST API Testing chrome extension. I have successfully created records through that chrome extension.
However, when I try to POST from my web application, I get this error:
"Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. The response
had HTTP status code 401."
How can I POST to NetSuite with a RESTlet from an external site? Should I even be using a RESTlet or is there a better way?
RESTlets are meant more as a system to system technology. They require authentication and if you are doing that from a public app your credentials will be compromised.
Netsuite doesn't allow you to set a CORS header so your cross domain integration needs to be via a publicly available suitelet and JSONP.
Since JSONP makes use of get requests you need to make sure your url params end up less than about 2k characters. That's not a standard limit so ymmv
patterns I often use:
Client code:
var url = "public suitelet url from deployment screen";
var params = {
mode: 'neworder',
//simple name/value data
};
$.ajax({
url: url+"&"+ $.param(params) +"&jsoncallback=?",
cache:false,
dataType:'json',
success: function(jResp){
if(!jResp.success){
if(jResp.message) alert(jResp.message);
return;
}
// act on the results
}
});
A library function in the suitelet source file.
function _sendJSResponse(request, response, respObject){
response.setContentType('JAVASCRIPT');
//response.setHeader('Access-Control-Allow-Origin', '*');
var callbackFcn = request.getParameter("jsoncallback") || request.getParameter('callback');
if(callbackFcn){
response.writeLine( callbackFcn + "(" + JSON.stringify(respObject) + ");");
}else response.writeLine( JSON.stringify(respObject) );
}
and then a Suitelet function
function service(request, response){
... do some work and generate a response
var returnObj = {
success:true,
message: '',
result:result
};
_sendJSResponse(request, response, returnObj);
}
That's your browser and its CORS setting
If using chrome ( you should be ;) ) on Windows, create a chrome shortcut with the following flags
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir
Then, kill/restart ALL INSTANCES of chrome in the Task Manager and try your requests again
Otherwise google "disable CORS on MY_BROWSER"