Express.js API fails to receive cookies from front end - node.js

In a React.js app I am using the js-cookie library to set 2 cookies. I am able to log the cookies to the console. I also see both cookies in a chrome extension, and the keys/values match.
I am sending the cookies via a fetch request that has a key for credentials: 'include'
async function requestAllAccountData() {
const allAccountDataEndpoint = buildUrl(REACT_APP_HTTPS_BACKEND_DOMAIN, {
path: '/account-data/all'
});
console.log('allAccountDataEndpoint', allAccountDataEndpoint);
try {
const response = await fetch(allAccountDataEndpoint, {
method: 'get',
mode: 'cors',
credentials: 'include', // for cookie passage to back end
headers: {
'content-type': 'application/json',
},
});
const allAccountData = await response.json();
console.log('allAccountData',allAccountData);
return allAccountData;
} catch (error) {
throw new Error(error);
}
}
An express endpoint with the following code fails to print the cookie values. Later in the code the lack of cookie keys/values sends control down a sad path.
router.get('/all', async (req: Request, res: Response) => {
console.log('req.cookies', req.cookies);
// [Object: null prototype] {}
console.log('number of cookies keys', Object.keys(req.cookies).length);
// 0
In server.ts I am bringing in the cookie-parser package as an invoked middleware:
const corsConfigured = cors({
credentials: true, // this setting should accept cookies
origin: true,
});
server
.use(corsConfigured)
.use(cookieParser())
.use(Express.json())
.use('/account-data', accountDataRouter);
// ^ this is the router shown in the prior code sample
What am I failing to do to cause the cookies not to be visible inside the route handler?
The cookies have no special options set on them.
Update: Request Information
In Google Chrome I do not see a header for the cookies in either the GET or OPTIONS request:
Request Method: GET
Status Code: 401
Remote Address: [2600:1f16:d83:1201::6e:1]:443
Referrer Policy: strict-origin-when-cross-origin
access-control-allow-credentials: true
access-control-allow-origin: http://localhost:3000
content-length: 33
content-type: application/json; charset=utf-8
date: Thu, 01 Oct 2020 16:05:30 GMT
etag: W/"21-EAAxQ8w9ulq766ONDoxsOSjUMSY"
status: 401
vary: Origin
x-powered-by: Express
:authority: asanarepeater.ngrok.io
:method: GET
:path: /account-data/all
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,th;q=0.8
content-type: application/json
origin: http://localhost:3000
referer: http://localhost:3000/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
.
Request Method: OPTIONS
Status Code: 204
Remote Address: [2600:1f16:d83:1201::6e:1]:443
Referrer Policy: strict-origin-when-cross-origin
access-control-allow-credentials: true
access-control-allow-headers: content-type
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-origin: http://localhost:3000
content-length: 0
date: Thu, 01 Oct 2020 16:05:28 GMT
status: 204
vary: Origin, Access-Control-Request-Headers
x-powered-by: Express
:authority: asanarepeater.ngrok.io
:method: OPTIONS
:path: /account-data/all
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,th;q=0.8
access-control-request-headers: content-type
access-control-request-method: GET
origin: http://localhost:3000
referer: http://localhost:3000/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36

Related

No 'Access-Control-Allow-Origin' header is present on the requested resource while using Passport for google authenticate in Nodejs

I am trying to authenticate with google using a passport IN MERN app.
Getting the below error but if I open the link available in below error in a new tab I am able authenticate with google.
Only issue is with below error
Error :
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com' (redirected from 'http://localhost:8000/auth/google') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CORS Config
app.use(cors({
origin: ["http://localhost:3000"," https://accounts.google.com"],
methods: "GET,POST,PUT,DELETE",
credentials: true,
}));
Passport routes
CLIENT_URL=http://localhost:3000
router.get("/google", passport.authenticate("google", ["profile"]));
router.get("/google/callback", passport.authenticate("google", {
successRedirect: process.env.CLIENT_URL,
failureRedirect: "/login/failed",
}));
router.get("/login/failed", (req, res) => {
res.status(401).json({
error: true,
message: "Log in failure",
});
});
Client req using Axios
REACT_APP_API_URL=http://localhost:8000
export const googleLoginReq = async () => {
try {
let res = await axios.get(`${REACT_APP_API_UR}/auth/google`, { withCredentials: true });
return res.data;
} catch (error) {
console.log(error);
}
};
Headers
General:
Request URL: https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com
Request Method: GET
Status Code: 200
Referrer Policy: strict-origin-when-cross-origin
Response headers:
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-encoding: gzip
content-security-policy: require-trusted-types-for 'script';report-uri /cspreport
content-security-policy: script-src 'report-sample' 'nonce-TOmywtPu0Qo8iQCEZhMnTw' 'unsafe-inline' 'unsafe-eval';object-src 'none';base-uri 'self';report-uri /cspreport
content-type: text/html; charset=utf-8
cross-origin-opener-policy-report-only: same-origin; report-to="coop_gse_qebhlk"
date: Wed, 25 Jan 2023 10:01:03 GMT
expires: Mon, 01 Jan 1990 00:00:00 GMT
p3p: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
pragma: no-cache
report-to: {"group":"coop_gse_qebhlk","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gse_qebhlk"}]}
server: GSE
set-cookie: __Host-GAPS=1:WBh43ekzNFz-U7PJu6wrySL4P0fJVw:-8nse8F4eB1X5yrO;Path=/;Expires=Fri, 24-Jan-2025 10:01:02 GMT;Secure;HttpOnly;Priority=HIGH
strict-transport-security: max-age=31536000; includeSubDomains
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
Request headers:
:authority: accounts.google.com
:method: GET
:path: /o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=1000813228585-k44nrfc0plt3kmupqu4rqcj0qcohhm35.apps.googleusercontent.com
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: en-IN,en-US;q=0.9,en;q=0.8
cookie: __Secure-3PAPISID=0fADWvGybtHw6h4E/AuZfyvMRCsCGQG4m9; __Secure-3PSID=TAgcETHlEPmlnVokgxJP67RdvdDCwLo6zS5s8W_yA_tnNn79ks2clkRgFmsvP0yZRult_A.; __Host-3PLSID=o.chat-dl.google.com|o.chat.google.com|o.console.cloud.google.com|o.drive.google.com|o.mail.google.com|o.meet.google.com|o.myaccount.google.com|s.IN|s.youtube:TAgcET_mZKiKd0P8KBaXK00vnWmuYQPOt8sRxUc75wk7hbKaEbtuam5S-oCMNPtkvpnT_w.; NID=511=ui5rQ6D8-KrHAUOn491ZvzQP7VdaQ-r94ktEYHfqHSWwWXK9E29AWZYBZMZRE8g9Zesepsp6c6lp-VjKU1dUWus4ICU9FkArFbf7bw5E6wQFcb9mOasQA0yV1qPgVErv49i1GLrgpHc373TwTqgC1Oah1nme4oaN2VBBN-r5YyAXun1eL4P-u3Iw7W6SV7ExIqnkunp4bQoG9ThcP5DjlkyDy14sK_YuV5EZwGIm9P6a18SsDcHDE2quUps7_LdjcE_CRL_OcB8v53R-Y9msRdxrBNGhY23yvgFbVkANBh5wKElpTvfTG7vxrDxZW_8Ol3LcM_wmKdD1ePuPHQrh4v1wQ29i16Vd0Z7obEEfP2hdig; LSOLH=AH+1Ng3ry+24BKCDnw1k/j8gBn5vXNTEUY4wwBo52xPp9smoYZt/jdHVLmQLmcStBp6zxduzEbOG; 1P_JAR=2023-01-25-10; __Secure-3PSIDCC=AIKkIs3zFB8Qc0Oo3-AzH4hzyJkZFsjp0ZEMsrezMMUBxtGeayEzfxjxwSaygz9LHj3OTAhrEdFL
origin: null
referer: http://localhost:3000/
sec-ch-ua: "Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
google api credentials urls
CORS can be a bit fiddly to setup, and errors like this are pretty common. There is a good CORS primer available here.
What is happening in the background is that the API is taking the contents of the origin header, and trying to match it with what is enabled in the credential URLs.
However, if you look at the request headers that are sent, the origin is set as null, which isn't matching your list. Adding null to your configuration should get things working.
Nota bene: it looks like this is a work around for a dev environment, make a note to back it out when you get to prod ;)

CORS is enabling for login and next api and failing for all other APIs

I am implementing a React application and node server as a backend. Recently I have updated my chrome version. And also updated some APIs but I haven't done any changes regarding CORS. But from Yesterday login request and the next request is getting success (I mean requests on the load of the application) after that any request that is fired due to event in the browser is failing.
All requests on load of the applications is a success when I go to any other routes by clicking on link API calls in that route Component are failing. I don't understand the reason for getting success on load and getting CORS error on any event-based API request?
My options req/res headers are
Request:
Request URL: http://localhost:4000/apps
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:4000
Referrer Policy: no-referrer-when-downgrade
Res Headers:
Access-Control-Allow-Headers: authorization,orgid
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Sun, 02 Aug 2020 06:58:37 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Req Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: authorization,orgid
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost:4000
Origin: http://localhost:3000
Referer: http://localhost:3000/apps/list
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52
This request is always getting success.
But I have another request (this req is failing with CORS)
Req:
Request URL: http://localhost:4000/rs
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:4000
Referrer Policy: no-referrer-when-downgrade
res Headers"
Access-Control-Allow-Headers: appid,authorization
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Date: Sun, 02 Aug 2020 06:59:21 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Req Headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: appid,authorization
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost:4000
Origin: http://localhost:3000
Referer: http://localhost:3000/apps/rs/list
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 Edg/84.0.522.52
I have enabled CORS in node API like,
let cors = require('cors')
app.use(cors());
app.use(function (req, res, next) {
next();
});
//routes start from here
Error message:
Access to fetch at 'http://localhost:4000/rs' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Failed GET request headers,
Request URL: http://localhost:4000/rs
Referrer Policy: no-referrer-when-downgrade
res Headers:
Connection: close
req Headers:
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,te;q=0.8
Authorization: Bearer eyJpZCI6IjVkNTE5NjFlNWMzMDM1NDlkNDYwZjk
Connection: keep-alive
Content-Type: application/json
Host: localhost:4000
orgId: 5dca073d4b044330e44e7946
Origin: http://localhost:3001
Referer: http://localhost:3001/apps/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*"); // "*" means allow connection from any request url.
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
You can change the * with the allowed url.
Or try this cors tutorial make sure to whitelist your request url. In your case 'http://localhost:3000'
// Set up a whitelist and check against it:
var whitelist = ['http://localhost:3000']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
// Then pass them to cors:
app.use(cors(corsOptions));
You don't require all that to send an http request. This is a basic example.
It should be like this:
Server.js
const express = require('express');
const cors = require('cors');
var app = express();
app.use(cors());
app.get('/', function(req, res) {
res.json({'Hello':'World'});
});
app.listen(3000);
Client..html
<html>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$.get("http://localhost:3000/", function(response) {
console.log(resposne);
});
</script>
</html>

CORS error but only on POST request, despite cors config (GET have no issue)

I use a nodejs express server.
Despite allowing the host, I still have an CORS error
" No 'Access-Control-Allow-Origin' header is present on the requested
resource."
but only for the POST endpoint. The "GET" have no issue.
Both (GET and POST) endpoint are allowed for my client-browser:
My server:(running on http://serverURL)
var whitelist = ['http://localhost:4200', 'http://someOtherDeployUrl.com']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = {origin: true} // reflect (enable) the requested origin in the CORS response
} else {
corsOptions = {origin: false} // disable CORS for this request
}
corsOptions.methods= "GET,HEAD,PUT,PATCH,POST,DELETE";
callback(null, corsOptions) // callback expects two parameters: error and options
}
router.post('/score', cors(corsOptionsDelegate), function (req, res, next) {
...
res.status(200).send('Ok');
});
router.get('/scores', cors(corsOptionsDelegate), function (req, res, next) {
res.status(200).send(scores);
});
The client ( angular 9) : (running on localhost:4200)
public saveScore(player, score) {
console.log("save score")
let objectObservable = this.http.post("http://serverURL/score", {
player: player,
score
}).subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
return objectObservable
}
public getScores() {
return this.http.get("http://serverURL/scores");
}
any idea why it's don't work?
The whole request/response of the GET:
Response:
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: http://localhost:4200
Content-Length: 2
Content-Type: application/json; charset=utf-8
Date: Sun, 14 Jun 2020 14:42:35 GMT
Etag: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
Server: Cowboy
Vary: Origin
Via: 1.1 vegur
X-Powered-By: Express
Request:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en,en-US;q=0.9,fr-FR;q=0.8,fr;q=0.7
Connection: keep-alive
DNT: 1
Host: serverUrl
If-None-Match: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
Origin: http://localhost:4200
Referer: http://localhost:4200/menu
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
The whole response/request for the (failing) POST
Response:
Allow: POST
Connection: keep-alive
Content-Length: 4
Content-Type: text/html; charset=utf-8
Date: Sun, 14 Jun 2020 14:30:00 GMT
Etag: W/"4-Yf+Bwwqjx254r+pisuO9HfpJ6FQ"
Server: Cowboy
Via: 1.1 vegur
X-Powered-By: Express
Request:
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en,en-US;q=0.9,fr-FR;q=0.8,fr;q=0.7
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: serverUrl
Origin: http://localhost:4200
Referer: http://localhost:4200/menu
Sec-Fetch-Mode: cors
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
Try enabling CORS preflight (OPTIONS) handling for your route.
When you need your route to handle so-called complex CORS operations, you must add a OPTIONS route handler. The browsers send an extra request, an OPTIONS request.
Why is this extra complex? Because cybercreeps.
Add this route handler. Right before your post handling is a good place for it.
router.options('/score', cors())

CORS cookies not setting by browser , cookies are present in response

I am sending http request to API endpoint of node.js server, this response is containing cookies and showing in mozilla debugger. I am sending this request through localhost.org or by my virtual host e.g myapp.example.com.
I tried AJAX XMLHTTPRequest and angular http as well
also add xhrFields: {withCredentials: true} for AJAX
credentials: 'include' for fetch, etc.
But cookies are not being set by browser, I am trying this for 2 days but this problem is not yet resolved.
this is util function which send ajax request
function sendServerRequest(url,method,data) {
return new Promise(function ( resolve ) {
resolve($.ajax({
url,
method: method || 'GET',
data,
xhrFields: {withCredentials: true},
crossDomain: true,
success: function ( data ) {
return data
},
error: function ( err ) {
try {
let responseStatus = err.responseJSON
if ( responseStatus.status === sessionExpires ) {
sessionExpireCall(responseStatus.message)
}
} catch ( e ) {
console.log('Failed to get response');
}
}
}));
})
}
Response Raw
HTTP/1.1 200 OK
X-RateLimit-Limit: 13000
X-RateLimit-Remaining: 12996
Date: 2019-06-26 06:17:56
X-RateLimit-Reset: 1561533343
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Access-Control-Allow-Origin: http://192.168.10.3
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type,
Authorization
Access-Control-Allow-Credentials: true
set-cookie: true
set-cookie: driverId=c81e728d9d4c2f636f067f89cc14862c; Max-Age=3600;
Domain=192.168.10.3; Path=/; Expires=Wed, 26 Jun 2019 07:17:56 GMT
set-cookie: driverName=kamran; Max-Age=3600; Domain=192.168.10.3; Path=/;
Expires=Wed, 26 Jun 2019 07:17:56 GMT
set-cookie: connect.sid=s%3AX- syECgzpFEZhh4d5B_xfStUoYPrO3p1.%2FPj%2BMo7UnaZto6OGoP%2BOjdKvrJ%2F3Fm%2Bn1BJ%2FXU7Qdh8; Domain=192.168.10.3; Path=/; Expires=Wed, 26 Jun 2019 07:17:56 GMT; HttpOnly
Content-Type: application/json; charset=utf-8
Content-Length: 34
ETag: W/"22-tpsDmOyD3m/F84/JvyRCwDCbeY8"
Connection: keep-alive
{"detail":"verified","status":200}
Request Raw
GET http://localhost:3000/driverboard/verifycode?
mobile=923002222222&vcode=2609 HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Accept: */*
Origin: http://192.168.10.3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Referer: http://192.168.10.3/capptin-driverboard/verification.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: true
CORS is not about cookies, CORS about HTTP headers. It allows making cross-domain requests(from one domain to another. For example from myapp.example.com to google.com). Cookies only send to the same domain, for example from myapp.example.com you can send cookies to the same domain .example.com
Docs here https://developer.mozilla.org/ru/docs/Web/HTTP/CORS
You can Append the cookie to your response with "/" as path.
add cookie in c# core. Append it to response:
context.Response.Cookies.Append(cookieNameAsString, cookieValue, new CookieOptions()
{
Expires = time,
Path = "/",
});
or create a cookie in javascript:
document.cookie = "cookieNameAsString='cookieValue'; max-age=time;";

Why isn't ServiceStack adding the Access-Control-Allow-Origin header to the GET request?

I configured ServiceStack to enable CORS:
Plugins.Add( new CorsFeature(
allowOriginWhitelist: new List<string>() { "http://localhost", "http://localhost:8080" },
allowCredentials: true,
allowedHeaders: "Content-Type, Allow, Authorization"
) );
PreRequestFilters.Add( ( request, response ) =>
{
if( request.Verb == "OPTIONS" )
{
response.EndRequest();
}
} );
The OPTIONS request and response look great and succeed with the http://localhost:8080 as the origin. However, the subsequent GET fails because, according to Chrome, it's missing the Access-Control-Allow-Origin header.
Here's the error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin http://localhost:8080 is therefore not allowed access.
Here's the request:
GET /app/api/operations/metadata HTTP/1.1
Host: dummy.domain.net
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Content-Type: application/json; charset=utf-8
Referer: http://localhost:8080/dev.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
And here's the response:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Vary: Accept
Server: Microsoft-IIS/7.5
X-Powered-By: ServiceStack/4.034 Win32NT/.NET
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Allow, Authorization
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 20 Dec 2014 17:22:38 GMT
Content-Length: 38203
Note the missing Access-Control-Allow-Origin header.
ServiceStack's CorsFeature already handles OPTIONS requests so you need to remove this so it doesn't short-circuit the request.
//Should be removed
PreRequestFilters.Add((request,response) => {
if (request.Verb == "OPTIONS" )
{
response.EndRequest();
}
});
WhiteList added to Custom Http Handlers
I've added support for Origin White lists in Custom Http Handlers like /operations/metadata in this commit. This now works as expected as seen in in http://test.servicestack.net (source code):
HTTP Request
GET http://test.servicestack.net/operations/metadata HTTP/1.1
Host: test.servicestack.net
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Origin: http://localhost:8080
HTTP Response
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Vary: Accept
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://localhost:8080
X-Powered-By: ServiceStack/4.00 Win32NT/.NET
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Allow, Authorization
Access-Control-Allow-Credentials: true
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 21 Dec 2014 00:30:39 GMT
Content-Length: 17027
This change is available from v4.0.35+ that's now available on MyGet.

Resources