How does Laravel add X-XSRF-TOKEN automatically when requesting via axios? - javascript

I have a API that uses the same auth middleware. So when I am successfully logged in, I am redirected to a page that gets data from my API from the same app. In my app.blade.php I only have axios added and a simple html and take note, I don't even have a csrf-token meta in my header except from my login page which has #csrf in my form.
Here is my app.blade.php layout
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
#yield('content')
<script src="{{ asset('js/axios.min.js') }}"></script>
<script>
const http = axios.create({
baseURL: '/api'
});
http.interceptors.request.use((request) => {
console.log('Starting Request', request);
return request;
});
</script>
#stack('scripts')
</body>
</html>
and in one of my pages:
#extends('layouts.app')
#section('content')
<div>
<h1>Hello World</h1>
</div>
#endsection
#push('scripts')
<script>
async function test() {
const { data } = await http('/some-page');
// I'm getting a data even without passing a csrf token?
console.log(data);
}
test();
</script>
#endpush
I'm getting the API data even without passing a csrf/xsrf token which is weird.
When I check my console for logs of outgoing request, this is the output
I mean, where did that came form? I don't even have a csrf token in my templates and also nothing or whatsoever passed to my axios config.
Am I missing something here?

Check the docs on XSRF token:
X-XSRF-TOKEN
Laravel stores the current CSRF token in a XSRF-TOKEN cookie that is
included with each response generated by the framework. You can use
the cookie value to set the X-XSRF-TOKEN request header.
This cookie is primarily sent as a convenience since some JavaScript
frameworks and libraries, like Angular and Axios, automatically place
its value in the X-XSRF-TOKEN header.

Related

Registering service worker behind authentication fails on ESM modules

I have developed a javascript application with a custom service worker and facing a problem fetching the service worker file behind authentication.
My application is deployed behind a cookie based authentication (after login, the user has a cookie which is checked by every request). This is fine for for fetching all resources, except the service-worker file, for which the browser doesn't send any cookies. Note: This only happens if the service worker is loaded with {type: "module"}, and works fine with {type: "clasic"}.
Here is miminal example reproducing my issue:
backend: index.js
// Service worker file
app.get('/test.js', (req,res) => {
if(req.cookies.token != null) {
res.sendFile('./public/test.js')
}
else {
res.sendStatus(401)
}
})
// Index page
app.get('/', (req, res) => {
// initial login check goes here
res.cookie('token',"<user token>").sendFile('./public/index.html')
})
frontend: index.html
<body>
<h1>Test</h1>
// Doesn't work with the auth
<script type="module">
const registration = await navigator.serviceWorker.register('test.js', {type: "module"})
console.log(registration)
</script>
// Works with the auth
<script src="test2.js"></script>
// Works with the auth
<script type="module">
const registration = await navigator.serviceWorker.register('test.js', {type: "clasic"})
console.log(registration)
</script>
</body>
When the request is made, the browser doesn't attach any cookie information:
.
Why doesn't the browser treat the service-worker module request as everything else? Why is there a difference between the two types?

Requests failing when made to service URL, but not to version url

I'm trying to set up a service on Google App Engine, but am having trouble getting XmlHttp to work consistently with it.
After deploying, the website can be accessed from 2 different urls: service-dot-project.appspot and version-dot-service-dot-project.appspot, and for some reason there is inconsistencies between the two.
Heres some demo code that verifyably causes me trouble.
# routes.py
from flask import render_template
from . import app
#app.route("/test", methods=["GET"])
def test():
return render_template("test.html")
#app.route("/api/test", methods=["GET"])
def api_test():
return "It Works!"
# templates/test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Debug</title>
</head>
<body>
<div id="out"></div>
<button type="button" onclick="run()">
Test the thing.
</button>
<script>
function run() {
let xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = () => {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200)
document.getElementById("out").innerText = xmlHttp.responseText;
}
xmlHttp.open("GET", "/api/test", true);
xmlHttp.send(null);
}
</script>
</body>
</html>
# service.yaml
runtime: python38
service: name
automatic_scaling:
min_idle_instances: 1
instance_class: F4
entrypoint: gunicorn -b :$PORT main:app
env_variables:
...
When I try and press the button on the version url, it works as intended, and "It Works!" gets printed into the div above the button, but on the service url (without the version specified), the page itself loads, but pressing the button causes the request to hang for a few seconds, before printing this to the console:
GET https://service-dot-project.appspot.com/api/test [HTTP/2 404 Not Found 7912ms]
When testing using a local flask debugging environment, the problem does not occur.
Is there something that Google App Engine does that I should know about that may have caused this issue to happen? Is /api a reserved endpoint? The rest of my endpoints works on the service url, its only the api endpoints that break. My only app.before_request method fails with a 403, not a 404, so this cannot be the cause.
if you go to https://console.cloud.google.com/appengine/versions
and select your service that is having troubles, is there some other version that is receiving the traffic instead of your desired version?
Also, try going to the logs, find the entry for the 404, expand it and see which version is throwing that error, under protoPayload > versionId
It seems that the issue is being caused by one of the other services running on our project.
Our default service is defining in its dispatch.yaml
dispatch:
- url: "/api*"
module: otherservice
Which is intercepting all the requests made to myservice-dot-project and redirecting them to otherservice-dot-project
Why this isn't the case for the version url is probably because there is no version of the default service with the same version number.
The fix is to either change the dispatch url of the default service, or change the url of the new service's API endpoints.

AngularJs does not read url

I need to use angularJS to call a rest api located at localhost:80/users.
The problem is that it does not read the url (the url works if I access it in the browser).
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>Today's welcome message is:</p>
<h1>{{myWelcome}}</h1>
</div>
<p>The $http service requests a page on the server, and the response is set as the value of the "myWelcome" variable.</p>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("https://www.w3schools.com/angular/welcome.htm").then(function (response) {
$scope.myWelcome = response.data;
});
});
</script>
</body>
</html>
When I run the code from above (which is from https://www.w3schools.com/angular/tryit.asp?filename=try_ng_services_http) on my PC I don't see the correct result. Instead
Today's welcome message is:
Hello AngularJS Students
The $http service requests a page on the
server, and the response is set as the value of the "myWelcome"
variable.
I see
Today's welcome message is:
The $http service requests a page on the server, and the response is
set as the value of the "myWelcome" variable.
in Chrome and Firefox.
If I replace the url from the code (https://www.w3schools.com/angular/welcome.htm) with my localhost/users, I also don't see the correct result. But, if the url is https://restcountries.eu/rest/v1/region/europe it works! Why does it work for some URLs and it does not for others?
The server which is running the angularJs uses a different localhost port than the Rest server provider. Could this be the problem?
I use the latest AngularJS version (1.6.7).

CORS request made despite error in console

I'm fiddling around with Google Cloud Storage. I've created a simple Python Flask handler:
#!/usr/bin/env python3
import secrets
import flask
from flask_cors import CORS
from google.cloud import storage
app = flask.Flask(__name__)
CORS(app)
client = storage.Client()
bucket = client.get_bucket('<my-bucket>')
#app.route('/')
def get_upload_urls():
blob = bucket.blob('00000' + secrets.token_hex())
return flask.jsonify({
'url': blob.create_resumable_upload_session(),
})
if __name__ == '__main__':
app.run('0.0.0.0', 9999)
This is accompanied by a really simple web frontend:
index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width">
<title>Test</title>
</head>
<body>
<input id="input" type="file" />
<button id="button">Upload</button>
<script src="index.js"></script>
</body>
</html>
index.js:
const input = document.getElementById('input')
const button = document.getElementById('button')
button.addEventListener('click', async () => {
const [ body ] = input.files
const response = await fetch('http://localhost:9999')
const { url } = await response.json()
await fetch(url, {
method: 'PUT',
body,
})
})
This frontend allows me to pick a file, and upload it to Google Cloud Storage using a resumable upload session created by the Python backend.
The problem with this is that it actually works. I'd expect the PUT request to fail, but it doesn't.
When a file has been selected and the upload button is pressed, the following errors are logged to the console:
index.html:1 Failed to load
https://www.googleapis.com/upload/storage/v1/b//o?uploadType=resumable&upload_id=:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3333' is therefore not allowed
access. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
index.js:13 Uncaught (in promise) TypeError: Failed to fetch
async function (async)
button.addEventListener # index.js:5
However, the PUT request was made succesfully and the file shows up in the Google Cloud Storage. I can download it and it appears to be totally fine.
Why doesn't the PUT request fail despite the CORS error in the console?
Edit:
I'm just looking for an explanation, not for a workaround — I'm going to configure CORS properly anyway. I would just like to know why the request doesn't fail, and why fetch does reject.
#sideshowbarker was right, I had the same issue. CORS needs to be set also in PUT response in addition to OPTIONS preflight request. Then fetch will succeed (even though upload worked before).

podio API JS browser authentication and API calls

I'm quite newbee on API thing, been reading the documentation here for JAVASCRIPT client but I can't make things work, even on authentication part. I already have the client ID and ClientSecret from PODIO itself.
Basically, I want to get all podio data in a workspace in a JSON format using client side (browser only).
I've downloaded the library here and created an HTML file on my localhost and link the podio-js with following code. Getting this error "podio-js.js:1 Uncaught ReferenceError: require is not defined at podio-js.js:1". Do I need to install something such that loader thing to make this work?
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="lib/podio-js.js"></script>
<script type="text/javascript">
var podio = new PodioJS({
authType: 'server',
clientId: 'foo',
clientSecret: 'foo'
});
var redirectURL = 'http://localhost/PODIO-JS/podio-js-master/PODIO_CLIENT.html';
// Your request handler (for example in ExpressJS)
var action = function(request, response) {
var authCode = request.query.code;
var errorCode = request.query.error;
podio.isAuthenticated().then(function() {
// Ready to make API calls...
}).catch(function(err) {
if (typeof authCode !== 'undefined') {
podio.getAccessToken(authCode, redirectURL, function(err, response) {
// make API calls here
console.log (responsedata);
});
} else if (typeof errorCode !== 'undefined') {
// a problem occured
console.log(request.query.error_description);
} else {
// start authentication via link or redirect
console.log(podio.getAuthorizationURL(redirectURL));
}
});
</script>
</head>
<body>
</body>
</html>
You can only use the syntax PodioJS = require('podio-js') if you're working in an AMD environment, typically using requirejs.
You're using a good ol' HTML page instead, which means you have to follow the second part of the browser usage section found here: https://github.com/podio/podio-js#browser
From within the podio-js folder:
npm install -g browserify
npm run bundle
and then include dist/podio-js.js using a tag in your HTML page.
Note: once you've bundled the source, you can copy paste the compiled file wherever you want.

Categories

Resources