Laravel / Airlock AJAX login - 419 (unknown status) - laravel

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

Related

i have token in header of ajax and when i get dd return null

i wanna send GET request from frontend to backend
i mean i want to send token from frontend to middlware
i mean i want get token from cookie and push in GET request and send for one of route in api.php that the route is GET method
i mean i want to push my token in ajax and send to laravel
infact i have two laravel project that i want send token from one to another
i mean i want push my token in header in ajax and get in backend with laravel
so see my code in the below fisrt my route from backend
later my jquery and then middleware
but my current problem is that when i dd header is is null
thanks
Route::get('/customers', 'App\Http\Controllers\CustomerController#show');
//
$.ajax({
url: "http://localhost:8000/api/customers",
type: "GET",
headers: {
"Authorization": getCookie("access_token")
}
});
//
dd($request->header('Authorization'));
if ($request->hasHeader('Authorization')) {
$access_token = $request->header('Authorization');
$query = DB::table("admins")->where("access_token", $access_token)->first();
if (isset($access_token) && $access_token == $query->access_token) {
return $next($request);
} else {
return response()->json([
"status" => 401,
"message" => "شما اجازه دسترسی ندارید",
]);
}
}

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?

The HTTP request must contain a user-specific secret - Error in fortify

I have below code in my applicaton.
makeAjaxRequest: function(url, data){
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function () {
var response = Ext.JSON.decode(xhr.responseText);
if (response) {
Ext.Msg.alert('Alert', response.message);
Ext.getBody().unmask();
}
};
Ext.getBody().mask('Loading...');
xhr.send(data);
}
Fortify is showing this error for this line
Error - "The http request at * line * must contain a user-specific secret in order to prevent an attacker from making unauthorized requests"
xhr.open('POST', url, true);
How do i resolve this fortify issue?
Is it something Fortify is highlighting because it doesn't have full context of the application.
In my application i have SSO setup which is passing a user specific secret with every request. But fortify may not be aware of it and ends up flagging this as an issue.
Kindly advice on what is best way to resolve this issue.
Thanks.
You need to add the setRequestHeader !!!
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(data);

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

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.

Django - CSRF token seems invalidated after Ajax login

I have a page that can be viewed authenticated or not.
This page contains form (with its CSRF token)
The form requires authentication to be taken into account
I manage the authentication check by ajax (on form submit)
If the user is not authenticated, he can do it from a new window (with a link)
Once authenticated, the user can close the new window and resubmit the form
In that case, Django tells me that my CRSF token is not valid anymore
CSRF token missing or incorrect
I imagine that's because the session_id has changed or something like that.
Is my assertion correct ?
How could I allow the user to resubmit the form without having to reload the page ?
While the above method can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many javascript frameworks provide hooks that allow headers to be set on every request.
You need to send the CSRF token through an AJAX call:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
Here is reference link, https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/#ajax

Resources