How to get HTTP-only cookie in React? - node.js

I'm currently developing a MERN stack application and the authentication I use is JWT and saving it in my cookie. This is how I send the cookie after the user login.
res
.cookie("token", token, {
httpOnly: true,
secure: true,
sameSite: "none",
})
.send();
And I am logging in the user by getting the "token" cookie in my backend. However, I implemented Redux with this application and every time I refresh the page, it automatically logs out. What I want is to detect in my front-end(React) the "token" cookie in my browser and I can't get it. I've tried using npm js-cookie and still can't get it. Is there a way to get the "token" cookie? Or use redux-persist based on what I've read? Please help, thanks.

Like already explained by an other answer, you can't access httpOnly cookies via JS.
I personally would recommend you to use a diffrent approach. Sure, cookies and httpOnly sounds like a good Idea, and you may think that cookies are a thousand times better than localStorage, but at the end, it doesn't really matter if you store the token in localStorage or in a cookie. You could argue about cookies vs localStorage for hours, but both have their vulnerabilities (e.g.: cookies: CSRF-Attacks (https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html), localStorage: XSS).
Now, while you could theoretically use localStorage here, I am not advocating using it. I would recommand you to just ditch both cookies and localStorage and store the JWT in your app-state (be it with the context-api, redux etc.) and send the JWT with an authentication header with all the request you make from the front to backend. Of course your backend would then need to verify that token. You could, for example, just implement an authentication middleware that you add to all the routes that need authentication. Expiration is also really easy because you don't have to sync the expiration of the JWT and the cookie anymore. Just set the expiration on the JWT and the verification of that token in the auth middleware will catch that. If you want to know why this method is safe against CSRF-attacks, look here: Where to store JWT in browser? How to protect against CSRF?
Here are some good articles, I would really recommand you read a bit of the first one:
https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/
https://medium.com/#ryanchenkie_40935/react-authentication-how-to-store-jwt-in-a-cookie-346519310e81

Although you cannot do anything with the httpOnly cookie in the frontend, there definitely IS a way to handle frontend-sent httpOnly cookies and extract your JWT from that cookie, all in the backend of your MERN stack app.
As far as persisting the user and preventing the 'logout upon refresh' issue, you will have to create a useEffect hook that constantly checks whether the token exists or not - we'll get to that later.
First, I recommend using Cors in your backend:
const cors = require("cors");
app.use(
cors({
origin: ["http://...firstOrigin...", ...],
credentials: true,
})
);
Once that's ready to go, set the following options when creating your httpOnly cookie. Also, create a non-httpOnly cookie that tracks your httpOnly cookie with same expiration date and a boolean value instead if the JWT. This will allow you to use the 'universal-cookie' library and actually read the non-httpOnly cookie in the frontend:
res
.cookie("token", token, {
origin: "http://...firstOrigin..."
expires: // set desired expiration here
httpOnly: true,
secure: true,
sameSite: "none",
})
.cookie("checkToken", true, {
origin: "http://...firstOrigin..."
expires: // same as above
secure: true,
sameSite: "none",
})
Having created a 'checkToken' cookie that mimics our actual 'token', we can use it to set the state (useState hook) and persist the user if it exists and not expired, through the useEffect hook.
However, to send it correctly, we must specify a few things first. In this example, I will use axios to make such API call in the frontend.
Note that every API call's request header will contain our httpOnly cookie and it's content - we can confirm this by opening chrome dev tools' network tab, make the API call, then check the "Request Headers" for the "Cookie"...
const cookies = new Cookies();
const checkToken = cookies.get("checkToken");
const AuthUser = () => {
const [user, setUser] = useState(checkToken);
useEffect(() => {
async function checkToken() {
await axios
.post("http://...yourBackend.../authToken", {
withCredentials: true, // IMPORTANT!!!
})
.then((res) => {
// handle response - if successful, set the state...
// to persist the user
)}
.catch((err) => {
// handle error
)}
};
checkToken();
}, []);
// Implement your login behavior here
}
Once that's done, we can confirm that we're getting such token in the request body of our API call in the backend (wherever that's handled), log the cookie in the console to check for it, then store the cookie's value in a variable to enable verification of said cookie:
app.post(".../authToken", (req, res) => {
// Get all cookies from request headers
const { cookie } = req.headers;
// Check to see if we got our cookies
console.log(cookie);
// Handle this as you please
if (cookie == undefined) return;
const token = cookie.split("token=")[1].split(";")[0]; // Yep, it's a string
console.log(token); // Check to see if we stored our cookie's JWT
// Some middleware:
jwt.verify(token, process.env.TOKEN, (err, user) => {
// if success upon verification,
// issue new 'token' and 'checkToken'
});
});
Done.
Please note that this a general implementation and serves as only a guide to understanding the functionality of httpOnly cookies. OP never provided original code to go off of.
I hope this helps. Godspeed.

You can't. "httpOnly" means "JavaScript cannot access it".
Using Redux-Persist would also not really help you determine if you are still logged in or if your session is timed out. That data could have been persisted weeks ago or the token could have been revoked.
The most sensible thing you can do it set up a /whoami endpoint on the server and just as a first action while your application initializes sending a request there. Either info about your user comes back -> great, save it and display it. Otherwise you get a "401 unauthorized" which means the user is not logged in and needs to log in.

We run into similar problem when improving the security of auth workflow on a project Created using React/Django
The question was: What is the best place to store JWT ?
After research we ended up implementing Oauth2 protocol, here is an article that helps you understand the logic if Refresh token rotation
Our implementation was
Generate 2 tokens on backend side (Access Token [short life] and Refresh Token [long lifespan])
Refresh token should be stored in HttpOnly cookie (as they mentioned in responses, it is not accessible on Client side by JS)
At frontend level we use only Access Token, and when it is expired, we make a call to backend to regenerate another Access and Refresh
Backend will access the Refresh Token in HttpOnly cookie and decide if it is valid to generate new Tokens
If Backend generates new valid tokens, it sends Access Token to frontend and update Refresh Token in the Cookie
Ps:
by this logic, you have no access to refresh token on frontend side, so when your Access Token no longer valid you tell the server to check Refresh Token stored in HttpOnly Cookie if it is still valid then regenerate other valid Tokens
I hope this inspires you

Related

Browser receives httponly cookie but does not store it on React frontend

I have a React-App with a Node and Express backend (both are running locally and on different ports) and I'm trying to implement JWT authentication/authorization in my application. I send the accessToken and refreshToken, at the time of login, and store the refreshToken as an httponly cookie. Here is the code used to achieve that at the backend:
const {accessToken, refreshToken} = await user.generateAuthToken()
res.cookie('jwt', refreshToken, {httpOnly: true,maxAge: 24*60*60*1000})
res.json({accessToken,user})
This is pretty straightforward and this flow works on postman by the way. Postman receives the refreshToken and stores it as an httpCookie thus allowing me to refresh a Token whenever my access Token expires.
However, I've been trying to achieve the same thing on React frontend for days but am unable to do so.
Now I understand that Cross Origin requests are not allowed to set cookies but I'm actually doing the following using Cors:
app.use(cors({
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
origin: ['http://localhost:3000', 'http://localhost:5000']
}));
On the frontend, this is how I make the login request:
const loginUser = await axios.post('/users/login',body,{withCredentials: true})
As far as I understand, this should work and I know that refresh token is received as a cookie when I login (by observing the network tab in the developer tools) so the problem is that it is not being stored on the browser. I've tried almost all the solutions given previously here on stackoverflow but none of them worked for me.
For anyone still suffering this issue, turns out the problem was with axios.post. I removed {withCredintials: true} config option from the request and just added
axios.defaults.withCredentials = true;

passport-local cookie and session database handling

I am currently trying to setup an oauth service for my current project. Being new to all this, I have read many articles on the subject, but I am still missing some pieces.
My environment is:
servers: node, express, passport
authentication: local strategy (using my own accounts / passwords)
I have a database with user/password ( passwords run through bcrypt)
web interface: react, server accesses through superagent
On my nodejs server, I am using these modules:
express
express-session
express-mysql-session
passport
passport-local
bcrypt
Different parts of the solutions are working: I can create new users, create new sessions, see their content in the express-mysql-session database.
However I am quite confused on the following:
when my web client tries to access protected routes, I don't seem to be getting any cookie in the request. Is it that superagent will not send my passport cookie by default? I read somewhere that in single page apps, jwt might be more appropriate, is that linked to this problem?
despite all I read, I am still confused about deserializeUser. My understanding is that with the passport-local solution, upon access, the web client will send the session cookie, which contains the session Id. Passport will fetch further information concerning this session from database, and then continue to handle the request. Does this session info retrieval happen automatically (in express-mysql-session?)? Or do you have to "manually" do it in deserializeUser (many examples show a User.findById call in there)? If you have to do it "manually", it means that you have to access the express-mysql-session db using another connection than the one this module is using?
to log out, is req.logout() enough to ensure the session is erased from the session db entirely?
Answers I found so far:
One has to add the withCredential method to superagent, to get it to send authentication cookies:
res = await superagent
.get(url)
.withCredentials()
.send();
On the CORS side of things, on the server, the 'credentials' option is required if using the 'cors' npm module, for instance:
app.use(cors({
origin: ['http://localhost:3003'],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
}));
All session information is automatically retrieved by these modules. However, many example show this call going back to the user database to get more information (rights, other info). The goal is to avoid having the same information in two locations (sessions db, and user profiles db), and having these getting out of sync (when an account gets closed etc...)
req.logout() disconnects the session, but the session information sticks around in the database.
The following question put me on the right track: how to delete cookie on logout in express + passport js?. You need to use req.logout, res.session.destroy, and while you're at it res.clearCookie to delete the client cookie:
router.post('/logout/',
(req, res) => {
req.logout();
res.status(200).clearCookie('connect.sid', {
path: '/',
secure: false,
httpOnly: false,
domain: 'place.your.domain.name.here.com',
sameSite: true,
}).end();
req.session.destroy();
},
Session is disconnected, database cleaned, cookie gone.

What is the optimal way to secure JWT in cookies for a React/Redux application?

Right now I'm working on a React/Redux full stack application and I'm working on setting up JWT auth and passing the JWT via cookies. I had a couple of questions on handling the CSRF token generated by the server.
1) Once you set the CSRF token on the server side, does it then get passed to the client? How exactly does it get passed? (I've seen examples where its passed in as an object, but the ones ive found weren't explained very well or just scarce)
server.js
// config csrf in server
app.use(csrf({
cookie: {
key: '_csrf',
secure: true,
httpOnly: true,
sameSite: 'strict',
maxAge: 86400
}
}))
// Hits my api routes, and if these arent hit, the index.html file is rendered
app.use(routes)
// Route used to fetch the index html file
app.get('*', (req, res) => {
let csrfToken = req.csrfToken()
console.log(csrfToken) // This doesnt console log anything on the server side
res.sendFile(path.join(__dirname, "./client/build/index.html"), {
_csrf: csrfToken
})
})
2) Once the CSRF token is set, should it be stored in the state of the application (Redux store) for persistent storage? Or would this be unnecessary?
3) On the client side, when I'm ready to submit data to a route via POST request, if I understand correctly, you'd have to include the input hidden field with the csrf variable like so:
<input type="hidden" name="_csrf" value=csrfToken/>
So when you submit a form, you'd include that input, then in the post request (assuming fetch or axios), you'd set the headers to include that csrf token, that way the server can compare it to the token the client is submitting to the route, am I understanding this correctly?
Thank you!
None of what you’ve asked specifically relates to react or redux. This is about request / response exchange with an HTTP server.
When using the the CSRF middleware, it automatically provides a CSRF tokens as a session cookie on request, and you’re expected to provide that back to the server on further requests.
1) CSRF tokens are usually set in a cookie by the server, or set as meta tag in the HTML. This code is generated uniquely per HTTP request to the server. It’s the applications responsibility to read the cookie/meta tag and then send it back to the server for future requests. One possible way is as a header: ‘X-csrf-token’ (https://en.m.wikipedia.org/wiki/Cross-site_request_forgery)
2) unnecessary in some cases: but that’s only by virtue of the fact that if the server sends a cookie header response, then your browser will always store that cookie, unless you have cookies turned off. When sending a request to the server, you need to retrieve that cookie and send it as the header above
3) I suggest you read the readme for express CSRF middleware (https://github.com/expressjs/csurf/blob/master/README.md), particularly this part about how the middleware looks for the CSRF tokens in responses or further requests:
The default value is a function that reads the token from the
following locations, in order: • req.body._csrf - typically generated
by the body-parser module. • req.query._csrf - a built-in from
Express.js to read from the URL query string.
• req.headers['csrf-token'] - the CSRF-Token HTTP request header.
• req.headers['xsrf-token'] - the XSRF-Token HTTP request header.
• req.headers['x-csrf-token'] - the X-CSRF-Token HTTP request header.
• req.headers['x-xsrf-token'] - the X-XSRF-Token HTTP request header.
As you can see - how you provide it back to the server is up to you — most people choose a header, but it can be as a body or a get request query string.

How to implement authentication in Next.js

I am new to Next.js and I am struggling with the authentication system using jwt token. I want to know what is the best / standard way to store the jwt token and routing with the authentication system. I have been trying different approaches, from different tutorials/articles, but do not quite understand it. Here are what I have tried.
When the user login, it sends username/password to a separated API server (ex. new project that handles backend stuff), the server will respond with the access-token, then in Next.js project, I set the cookie with that received token. In Next.js project, protected routes will be wrapped with a withAuth hoc, which will check for the token in a cookie. The problem with this approach is that it is vulnerable to XSS because the cookie has no httpOnly flag.
This is similar to 1.) but using localStorage, the problem is access-token could not be sent to the server on the first request. (This one I'm not sure, but in my understanding, in every HTTP request, I must stick my access-token manually, so what about requests that I have no control over? ex. first request or using <a> tag).
I wrote authentication backend inside Next.js server (custom express server). When the user login, the server will validate it and then set an httpOnly cookie. Then the problem is, with client-side routing (go to URL using Next.js Router), it could not check for token. For example, if a page is wrapped with withAuth hoc, but it cannot access the token inside cookies with javascript.
And I've seen a lot of people, in getInitialProps of the protected route, they only check for existence token in cookie / localStorage, then what if the token is being revoked or blacklisted, how do they handle it because they did not send the token to the server? Or do I have to send the token to the server in every client-side page change?
Since we are on quarantine I have enough time to answer this question. It will be a long answer.
Next.js uses the App component to initialize the pages. _app page is responsible for rendering our pages. We authenticate users on _app.js because anything that we return from getInitialProps can be accessed by all of the other pages. We authenticate user here, authentication decision will be passed to pages, from pages to header, so each page can decide if the user is authenticated or not. (Note that it could be done with redux without prop drilling but it would make the answer more complex)
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {};
const user = process.browser
? await auth0.clientAuth()
: await auth0.serverAuth(ctx.req); // I explain down below
//this will be sent to all the components
const auth = { user, isAuthenticated: !!user };
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps, auth };
}
render() {
const { Component, pageProps, auth } = this.props;
return <Component {...pageProps} auth={auth} />;
}
}
If we are on the browser and need to check if a user is authenticated, we just retrieve the cookie from the browser, which is easy. But we always have to verify the token. It is the same process used by browser and server. I will explain down below. But if we are on the server. we have no access to the cookies in the browser. But we can read from the "req" object because cookies are attached to the req.header.cookie. this is how we access to cookies on the server.
async serverAuth(req) {
// console.log(req.headers.cookie) to check
if (req.headers.cookie) {
const token = getCookieFromReq(req, "jwt");
const verifiedToken = await this.verifyToken(token);
return verifiedToken;
}
return undefined;
}
here is getCookieFromReq(). remember we have to think functional.
const getCookieFromReq = (req, cookieKey) => {
const cookie = req.headers.cookie
.split(";")
.find((c) => c.trim().startsWith(`${cookieKey}=`));
if (!cookie) return undefined;
return cookie.split("=")[1];
};
Once we get the cookie, we have to decode it, extract the expiration time to see if it is valid or not. this part is easy. Another thing we have to check is if the signature of the jwt is valid. Symmetric or asymmetric algorithms are used to sign the jwt. You have to use private keys to validate the signature of symmetric algorithms. RS256 is the default asymmetric algorithms for APIs. Servers that use RS256, provide you with a link to get jwt to use the keys to validate the signature. You can either use [jwks-rsa][1] or you can do on your own. You have to create a certificate and then verify if the token is valid.
Assume that our user authenticated now. You said, "And I've seen a lot of people, in getInitialProps of the protected route, they only check for existence token in cookie / localStorage,". We use protected routes to give access only to the authorized users. In order to access those routes, users have to show their jwt tokens and express.js uses middlewares to check if the user's token is valid. Since you have seen a lot of examples, I will skip this part.
"then what if the token is being revoked or blacklisted, how do they handle it because they did not send the token to the server? Or do I have to send the token to a server in every client-side page changing?"
with verifying token process we are 100% sure if the token is valid or not. When a client asks the server to access some secret data, the client has to send the token to the server. Imagine when you mount the component, component asks the server to get some data from the protected routes. The server will extract the req object, take the jwt and use it to fetch data from the protected routes. Implementation of the fetching data for browser and server are different. And if the browser makes a request, it just needs the relative path but the server needs an absolute path. As you should know fetching data is done getInitialProps() of the component and this function executed on both client and server. here is how you should implement it. I just attached the getInitialProps() part.
MyComponent.getInitialProps = async (ctx) => {
const another = await getSecretData(ctx.req);
//reuslt of fetching data is passed to component as props
return { superValue: another };
};
const getCookieFromReq = (req, cookieKey) => {
const cookie = req.headers.cookie
.split(";")
.find((c) => c.trim().startsWith(`${cookieKey}=`));
if (!cookie) return undefined;
return cookie.split("=")[1];
};
const setAuthHeader = (req) => {
const token = req ? getCookieFromReq(req, "jwt") : Cookies.getJSON("jwt");
if (token) {
return {
headers: { authorization: `Bearer ${token}` },
};
}
return undefined;
};
export const getSecretData = async (req) => {
const url = req ? "http://localhost:3000/api/v1/secret" : "/api/v1/secret";
return await axios.get(url, setAuthHeader(req)).then((res) => res.data);
};
[1]: https://www.npmjs.com/package/jwks-rsa
With the introduction of Next.JS v8, there are examples placed in the NextJS example page. The basic idea to follow is:
JWT
Using cookies to store the token (you may choose to further encrypt it or not)
Sending the cookies as authorization headers
OAuth
Using a third-party authentication service such as OAuth2.0
Using Passport
This question might need an updated answer, now middlewares are there in Next.js 12 (october 2021): https://nextjs.org/docs/middleware
I am drafting a comprehensive answer to explain auth in Next.js more deeply, you can follow the progress there on GitHub
Here I'll try to propose a summary for Next.js, using middlewares.
Verifying the token after auth and redirecting accordingly
Most of the answer from #Yilmaz from april 2020 is still relevant. However, previously, we had to use getInitialProps in _app to process the request OR a custom server.
This is no longer the case.. Using a middleware let's you achieve a similar purpose, with cleaner code. Because middleware are specifically designed for such use cases.
Here, I suppose you get a JWT access token using an asymetrical algorithm like RS256, exactly like in this previous answer.
Here is a possible implementation:
import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
const removeCookie = (res: NextResponse, cookieName: string) => {
res.headers.append("Set-Cookie", `${cookieName}=; Max-Age=-1; Path=/`);
return res;
};
export default async function middleware(
req: NextRequest,
ev: NextFetchEvent
) {
const { pathname } = req.nextUrl;
const isPublic = isPublicRoute(pathname);
if (isPublic) {
return NextResponse.next();
}
const accessToken = req.cookies[TOKEN_PATH];
if (!accessToken) {
return NextResponse.redirect(LOGIN_HREF);
}
const isValidToken = await checkAccessToken(accessToken);
if (!isValidToken) {
let res = NextResponse.redirect(LOGIN_HREF);
res = removeCookie(res, TOKEN_PATH);
return res;
}
return NextResponse.next();
}
How to verify the token
In my example, the checkAccessToken should verify the token (not decode, verify the signature).
This is where things are the most complicated imo.
When using the RSA256 algorithm
You also get a PUBLIC certificate (in addition to the SECRET key that must be... kept secret). Eventhough you do the check in the middleware, which is private and server-only code, that's good news because it means you could even use it in the browser, in theory.
So, you can either fetch the token validation endpoint provided by your auth server, or verify the token yourself.
Fetching is not the recommended option because it might break Vercel/Next edge capabilities and add latency, according to the documentation.
I must admit that I did not succeed to verify the token yet using Next.js :) I'll update this answer if I manage to have a code sample that works.
When using a symmetrical encryption
You have only a PRIVATE secret passphrase. It means that the decoding have to happen server-side (good news, you are writing a middleware).
Login/logout
This doesn't change with middlewares. You store your access token as an httpOnly cookie. When logging out, you unset this cookie.
Managing those Set-Cookies headers are the responsibility of your auth server.
This is a basic workflow but it should work. You can then add a refresh token in the mix with a similar approach.
About token revokation
If you verify the token in your middleware, there is no immediate revokation mechanism for the access token. Because there is no call to a database.
Therefore, in this scenario, you'd want to opt-in for short lived access token (eg 5 minutes) coupled with a refresh token. You can revoke the refresh token, so basically revoking works but takes a few minutes.
If a 3rd party server verifies the token: then it could check for blacklisted tokens.
Caveats
Also, some piece of advice: most articles, tutorials etc. online are focused on server-to-server communication. Or client-to-API. They completely suck when it comes to check authentication before accessing web pages.
For instance, setting the Authorization header is not possible in the browser. It works only when communicating with an API. Cookies are mandatory for web pages.
Even then, if this API is meant to be called from a browser, it should preferably accept a cookie.
When discussing with experts on the field, you need to always clarify the Next.js use case.
Open questions: about session-based authentication
Some frameworks seem to prefer relying on the database. They store a hashed token in the db, which acts as a session. If you want to check auth, you need a server that will check the user's token against the stored token (= checking that there is an active session with this token).
I am thinking of Meteor for instance.
I couldn't find the name of this mechanism and its actual relation to JWT however. Are they simply variations of the JWT approach?
Next.js official authentication doc is not showing middlewares at the time of writing, but instead use getServerSideProps. I really don't like this pattern.
It uses a kind of session system but I am not clear about the internals of it, I am not even sure of the name (is that session-based auth?).
Vercel edge handles examples shows how to secure an API route, but not a page (at the time of writing)

Create session only after successful authentication in express

I have a requirement to create a session only after successful authentication.
I was able to create redisStore based session using express middleware, but it creates session when the first request comes to server.
But how I can create session only after successful authentication.
I googled somewhat, and foundreq.session.regenerate() (but I found the issue as below mentioned in this thread:
Regenerate session IDs with Nodejs Connect)
But in regenerate case also, it creates a fresh one, assuming old one is created already, and is created with same parameter.
So there is any other way to create a new session ID only after successful authentication..?
You may be conflating the idea of a session with the idea of an authenticated session.
It's normal for all users to have a session - even the anonymous, not-yet-logged-in users. The difference between this and an authenticated session is just that, locally on your web server, you specify that a particular user has been authenticated.
For example, once you authenticate someone, you can set:
req.session.isAuthenticated = true;
Then, when rendering pages, your controllers can do something like
function(req, res, next) {
if (!req.session.isAuthenticated) return res.redirect('/login');
res.render('appPage');
}
This might not be the exact answer you're looking for, but I'll answer the title for future readers:
From experimenting with my application, I've noticed that express-session sets the session cookie only if you manipulate the session object.
For example consider the below code:
app.post('/login', function (req, res) {
var authenticated = false;
if (req.session.authenticated) {
// session cookie is already set
authenticated = true;
} else if (/*validate the user here*/) {
console.log(' authenticating');
authenticated = true;
// if below line executes, the response will have Set-Cookie header
req.session.authenticated = authenticated;
}
res.json({
status: authenticated
//if --^ false, no session cookie will be set since we didn't manipulate session object
});
});
Even though a request creates a session object in memory for us to use, the Set-Cookie header seems to be sent only if we manipulate (or tamper with?) the session object created.
Unless we sent the Set-Cookie header along with the response and session id is stored in cookie at client side, I wouldn't consider it as an established session and worry about it.
Hope it helps.
Side note: This is the case of a cross-domain ajax request, might be different for normal http request, perhaps someone can confirm this

Resources