mutli-domain cookies in express redirecting localhost to mydomain.com - session

I've got an app where I'm trying to allow the user to create their own subdomains.
In order to get this working locally while developing and testing, I've had to setup a few available subdomains in my hostfile.
For login, I'm using oauth, and google is the first provider I'm working with.
When a user logs in from mydomain.com google forces the redirect auth to localhost. I've written a bit of middleware that checks if the req.get('host') is localhost, it redirects to mydomain.com.
This seems to work fine, except that it appears that express doesn't match the sessions from the one returned by localhost when the redirect goes to mydomain.com.
As this is only for dev and testing, is there a way to allow express to share all the session info across domains, or add a whitelist?
The stuff I've found on SO has pointed me to have my redirect middleware as
module.exports = function(baseUrl){
var base = baseUrl.split(':');
base = base[1].replace('//','');
return function(req, res, next) {
console.log('in redirect');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', base);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if(req.hostname.indexOf('localhost') > -1) {
var redirect = req.get('host').replace('localhost', base);
console.log('redirect is', redirect, req.path);
return res.redirect(redirect + '/');
}
next();
}
}
but then in my post login route, I need to check if the requested url is localhost, and if so, then I need to replace it. For some reason, the middleware isn't being called in this route. It is called when I initially
function createUrl(req, subdomain){
var domain = req.get('host') === 'localhost:3000' ? 'mydomain.com:3000' : req.get('host');
var url = req.protocol + '://' + subdomain + '.' + domain;
return url + '/team'
}
function redirectToSubdomain(req, res){
var url = createUrl(req, "me");
console.log('new url is ', url);
res.redirect(url)
}
router.get('/', auth.isAuthenticated(), function(req, res) {
var team = Team.getSubdomain(req);
if(team.error) return redirectToSubdomain(req, res);
return res.render('team', req.data);
});
I've tried setting my cookie to accept all domains as
app.use(passport.session({cookie: { secure: true, domain: '*'}}));

I ended up not using dev.localhost as the main url to the development site, than subdomain.dev.localhost for subdomains, and in my cookie set domain: '.dev.localhost'. Worked a treat.

Related

how to solve cors Allow Access control in vue js and laravel application

I Have tried almost everything. My front end is developed in vue js . backend is in laravel. we have written api for another website from which we are trying to fetch data. If directly access that website Url it gives all the data but when i try to access it from my website with axios it gives me this error.
Access to XMLHttpRequest at 'https://example.com/api/tickets/fetch_tickets?page=undefined' from origin 'http://localhost:8000' has been blocked by CORS policy: Request header field x-requested-with is not allowed by Access-Control-Allow-Headers in preflight response.
that website form which i am trying to fetch data also build in laravel. i have created middleware and applied it on api routes. I added chrome extension Allow Cors with which it works fine but we cant ask every client to use that extension.
We access that url from other website which is accessing data nicely. only vue js app creating these issue.
Vue Code
getTickets() {
axios.get( 'example.com/api/tickets/fetch_tickets?page=' + this.pagination.current, {
}).then((response) => {
// console.log(res.data.data)
// this.desserts = res.data.data;
// this.loadingprop = false;
this.desserts = response.data.data;
this.pagination.current = response.data.current_page;
this.pagination.total = response.data.last_page;
console.log(response.data.data);
}).catch((err) => {
this.handleErrors(err.response.data.errors);
})
.then(() => {
this.loading = false;
});
}
other website's routes
Route::group(['middleware' => ['api','cors']], function () {
Route::group(['prefix' => 'tickets'], function () {
Route::post('/store_ticket_auth', 'TicketApiController#storeTicketAuth'); //enter ticket auth
Route::get('/fetch_tickets', 'TicketApiController#fetchTickets'); //get all tickets
Route::get('/fetch_replies/{ticket_id}', 'TicketApiController#fetchTicketReplies'); // get all replies by ticket id
Route::post('/send_reply', 'TicketApiController#sendTicketReply'); // Send reply
Route::post('/update_ticket', 'TicketApiController#updateTicketStatus'); // Update Status
});
});
Do I need to add this on my cuurent project too?
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
I think the issue is on client side but dont know why it is not working.
I tried all answers on stackoverflow but nothing works
I have to add these lines in my index.php file of laravel
header("Access-Control-Allow-Origin: *");
//header("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS");
header("Access-Control-Allow-Headers:*");
if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {//send back preflight request response
return "";
}
Solved my issues by commenting out:
// window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
in resources/js/bootstrap.js
The error is telling you that the server won't allow the client to use a x-requested-with header.
In php you can do this to allow the server to accept that header:
header('Access-Control-Allow-Headers: X-Requested-With');
If you want the easy way you can use laravel-cors
You can follow the installation step and add this code in your config/cors.php
'allow_origins' => [
'https://yourfrontendrequest.url',
],
Install Moesif Origin & CORS Changer Chrome extension and
Then go to resources/js/bootstrap.js and comment out this line // window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
you can disable same origin policy in chrome
press win + R
and then copy this :
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security

Laravel / Airlock AJAX login - 419 (unknown status)

I'm trying to do a cross origin login request and everything except logging in is working. So if I go to api.example.com and log in with the laravel app and then go to www.example.com I can get the user by calling the /api/user end point (setup as part of airlock). What I'm failing to do is log in via AJAX with username / password. Here is the JS used:
First I call setCSRFCookie()
function setCSRFCookie() {
let xhr = new XMLHttpRequest();
xhr.open('GET', domain+'/airlock/csrf-cookie');
xhr.withCredentials = true;
xhr.send(null);
}
Then I call loginUser()
function loginUser() {
let xhr = new XMLHttpRequest();
let params = 'username=m#example.com&password=password';
xhr.open('POST', domain + '/login', true);
xhr.withCredentials = true;
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
xhr.send(params);
}
I'm getting a 419 (unknown status) which appears to be Laravel's response for an invalid CSRF token. I looked at the actual request and both APP_NAME_session and XSRF-TOKEN are being passed as part of the request. The only thought I had was that the /login default auth route isn't setup for this and I need to do one under /api/login so it's served by the airlock middleware. I appreciate any help you can give.
Laravel 6.12.0
Airlock 0.1.0
Make sure api.example.com is included in config/airlock.php like this
'stateful' => [
'localhost',
'api.example.com'
],
And request middleware should be auth:airlock

http-proxy to cloudfront results in 403 error

I have a series of serverless next.js apps running on AWS that I am serving at subdomains, and I want to proxy them to subdirectories on my main domain. So, for example, the app at foo.example.com/foo/ should appear at www.example.com/foo/.
I've accomplished this by using http-proxy and express. I have a fairly simple express server that runs in its own serverless app, like so:
const serverless = require('serverless-http');
const httpProxy = require('http-proxy');
const express = require('express');
const app = express();
const proxy = httpProxy.createProxyServer();
app.get('/', (req, res) => {
res.send('Hello, you are at index.');
});
app.get('/:project/*', (req, res) => {
const project = req.params.project;
const rest = req.params[0];
const url = `https://${project}.example.com/${project}/`;
req.url = `/${rest}`;
req.headers['X-Projects-Router-Proxy'] = true;
req.body = undefined;
proxy.web(req, res, {
target: url,
xfwd: false,
toProxy: true,
changeOrigin: true,
secure: true,
});
});
module.exports.handler = serverless(app);
This works quite well on its own, which is great. However, when I try to put this behind CloudFront, the index page works fine, but anything that touches the proxy returns a 403 error:
403 ERROR
The request could not be satisfied.
Bad request.
Generated by cloudfront (CloudFront)
What might be going wrong here, and how can I configure http-proxy so that it will cooperate with CloudFront?
You need to add *.example.com into CloudFront CNAME/Alternative name filed and also in DNS to point it to CloudFront, when url changes as {project}.example.com, CloudFront finds the distribution based on the host header and if it can't find, it'll give you 403 error.

Store Laravel Passport access token in a cookie

Is it safe to store the access token in a cookie?
I've checked, and even if you have the access token, if you are not properly logged in, you will get a 401.
The access token is changing (I'm changing it) every time the user logs in.
The cookie gets destroyed on sign out or on timeout (based on the rememberme option).
Should I anyway store it somewhere else? Where about?
Yes it's safe, but still you need to add middleware on your routes
Before we are using JWT AUth, this is our solution on frontend side on login page
axios({method: 'post',
data: {email: this.email.trim(),
password: this.password},
url: '/api/login'})
.then(res => {
if (res.data.success) {
// Sets the Cookie Expiration Time to 1 Hour same as JWT Token on the Backend
var now = new Date();
now.setTime(now.getTime() + 1 * 3600 * 1000);
document.cookie = "ut=" + res.data.data.type;
document.cookie = "api_token=" + res.data.data.token;
document.cookie = "expires=" + now.toUTCString() + ";"
// Redirect to a new URL, or do something on success
window.location.href = "/dashboard";
}
}).catch(function (error) {
//error
});
Any suggestions?

keep session in node.js with proxy

I wish to connect to site (E) and within an html page access to my odata-server using odata protocol.
I've create a proxy in site (E):
this.use('/data', function(req, res) {
var request = require('request');
var apiUrl = process.env.ODATA_SERVER || 'http://localhost:5000';
url = apiUrl + req.url;
response = req.pipe(request(url))
response.pipe(res);
});
this is the scenario: A user connect to site (E), login and a dynamic page should load data from odata-server.
But the problem is: as the browser receive the data I lose the authenticate session with the user and E. How can I keep user login?
I've added this in my authenticate function:
(request({uri: uri, jar: true })).auth(loginName, password, false);
and now it works! :)
UPDATE: see my last comment :)

Resources