I am trying to post a form from Extjs to Django (ver 3.1) as backend
and have an CSRF token Error from the Django side "POST /test/ HTTP/1.1" 403"
My senerio is this :
My Extjs app run on localhost:1841 (default from extjs for
development)
My Django app run on localhost:8000 (defualt Django runserver
command...)
Both on the same server.
I did read that because I am not generating the form from Django but from
the ExtJS which is external to django ,
I need to get the CSRF through Django api ==> get_token(request)...
so here is my view :
def csrf(request):
return JsonResponse({'csrftoken': get_token(request)})
Here is the JS function that call this csrf function...
function getCsrfToken () {
Ext.Ajax.request ({
url : 'http://127.0.0.1:8000/csrf/',
success : function (response, opts) {
obj = Ext.decode (response.responseText, true);
#save it for later user...
Ext.util.Cookies.set('csrftoken', obj['csrftoken']);
},
})
};
I did test it , and it is working fine by generating CSRF token.
Here is my submit form action (POST) from the ExtJs side...
onSubmitClick : function () {
let form = Ext.getCmp ('formID');
var csrf = Ext.util.Cookies.get ('csrftoken');
if (form.isValid ())
form.submit ({
url : 'http://127.0.0.1:8000/test/',
headers : {
'X-CSRFToken': csrf,
},
success : function (form, action) {
let data = Ext.decode (action.response.responseText)
Ext.Msg.alert ('Success', data['success']);
},
});
} else { // display error alert if the data is invalid
Ext.Msg.alert ('Invalid Data', 'Please correct form errors.')
}
}
As you can see , I did send the CSRF token from the in the header...
headers : {
'X-CSRFToken': csrf,
},
After that I did get the Django CSRF Error as shown above.
Here is my Django relevant setting...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'core.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
# corsheaders
CORS_ORIGIN_ALLOW_ALL = True
#CSRF
CSRF_HEADER_NAME = 'X-CSRFToken'
CSRF_COOKIE_SECURE = False
#CSRF_USE_SESSIONS = True
CORS_ALLOW_CREDENTIALS = True
#CORS_ORIGIN_WHITELIST = ['127.0.0.1:8000']
CSRF_TRUSTED_ORIGINS = ['localhost:1841']
Here is the image of the get request for getting the token ...
Here is the image log of the Post Request...
Any Help With this error please.
Thanks for your replies!
Related
I have created a custom route in Strapi v4 called "user-screens". Locally I hit it with my FE code and it returns some data as expected. However when I deploy it to Heroku and attempt to access the endpoint with code also deployed to Heroku it returns a 404. I've tailed the Heroku logs and can see that the endpoint is hit on the server side, but the logs don't give anymore info other than it returned a 404.
I am doing other non custom route api calls and these all work fine on Heroku. I am able to auth, save the token, and hit the api with the JWT token and all other endpoints return data. This is only happening on my custom route when deployed to Heroku. I've set up cors with the appropriate origins, and I am wondering if I need to add something to my policies and middlewares in the custom route. I have verified the permissions and verified the route is accessible to authenticated users in the Strapi admin.
Here is my route:
module.exports = {
routes: [
{
method: "GET",
path: "/user-screens",
handler: "user-screens.getUserScreens",
config: {
policies: [],
middlewares: [],
},
},
],
};
And my controller:
"use strict";
/**
* A set of functions called "actions" for `user-screens`
*/
module.exports = {
getUserScreens: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
}
strapi.entityService
.findMany("api::screen.screen", {
owner: user.id,
populate: ["image"],
})
.then((result) => {
ctx.send(result);
});
},
};
For anyone facing this, the answer was to change how I returned the ctx response from a 'send' to a 'return' from the controller method. I am not sure why this works locally and not on Heroku, but this fixes it:
New controller code:
module.exports = {
getUserScreens: async (ctx) => {
const user = ctx.state.user;
if (!user) {
return ctx.badRequest(null, [
{ messages: [{ id: "No authorization header was found" }] },
]);
}
return strapi.entityService
.findMany("api::screen.screen", {
owner: user.id,
populate: ["image"],
})
.then((result) => {
return result;
})
.catch((error) => {
return error;
});
},
};
I am developing an application using laravel 8 and vuejs. I am trying to post form data from my vuejs to backend(laravel) but it is not working
The vuejs creates a subsection of a section which is add to an array of subsection inside the section array which is converted to string and added to a form data then sent as a request to my backend.
The frontend is working perfectly well but I cant access the data on my backend. How do I get the values of the course title, section title, sub section title and file added
Vuejs
<script>
import { reactive } from "vue";
import axios from "axios";
export default {
name: 'CreateCourse',
setup(){
const sections = reactive([{'section_title': '', 'sub_sections': [{'sub_section_title': '', 'file': '', 'url': ''}]}]);
const course = reactive({'title': '', 'description': ''});
const addSection = () => {
sections.push({"section_title": "", 'sub_sections': [{'sub_section_title': '', 'file': '', 'url': ''}]});
}
const addSubSection = (idx) => {
console.log('the value of idx is ', idx);
sections[idx].sub_sections.push({"sub_section_title": "", 'file': '', 'url': ''});
}
const uploadFile = (e, idx, i) => {
sections[idx].sub_sections[i].file = e.target.files[0];
sections[idx].sub_sections[i].url = URL.createObjectURL(sections[idx].sub_sections[i].file);
}
const createCourse = (e) => {
e.preventDefault();
let newCourse = JSON.stringify(course)
let newSection = JSON.stringify(sections)
const formData = new FormData();
formData.append("course", newCourse);
formData.append("sections", newSection);
showLoader(true);
axios.post('/api', form, { headers: {'Content-Type': 'multipart/form-data'}}).then(response =>
{
NotificationService.success(response.data.message);
showLoader(false);
course.title = '';
course.description = '';
}).catch(err => {
NotificationService.error(err.response);
showLoader(false);
});
}
return {
course,
createCourse,
sections,
addSection,
addSubSection,
uploadFile
}
}
</script>
laravel code
echo $request->get("title");
echo $request->get("description");
foreach($request->section_title as $titles)
{
echo $titles
}
foreach($request->section_sub_title as $sub_titles)
{
// info($sub_titles);
// return $sub_titles;
echo $sub_titles
}
{"course":{"title":"Frontend","description":"This is building web interface with html, css and javascript"},"sections":[{"section_title":"HTML","sub_sections":[{"sub_section_title":"What is HTML","file":{},"url":"blob:http://localhost:8080/ea0acc7d-34e6-4bff-9255-67794acd8fab"}]}]}
Bit tricky to understand where you're stuck, but let's give it a shot:
Does the api request actually reach your route (post -> /api), do you see in the network tab a post request to the route?
Have you tried running dd($request->all()) in the controller method so see what you're getting (just do this on the first line inside your method)?
Small gotcha moment:
Sometimes it helps to run the php artisan route:clearcommand
My goal is that i want to access $auth.user.roles from plugin and middleware to be able to not let this role reach the other role page.
what is expected is that when console.log($auth.user) it gives me the user data (id,...) and when a console.log($auth.loggedIn)it gives me true.
My problem is that i can't access $auth.user from plugin and middleware to chieve that which $auth.user = null and $auth.loggedIn = false while im logged in.
here is my nuxt.config.js:
axios: {
baseURL: env.parsed.API_URL || 'http://localhost:3000/api',
debug:true},
auth: {
strategies: {
local: {
endpoints: {
login: {
url: '/auth/signin',
method: 'post',
propertyName: 'data.token'
},
user: {
url: '/auth/me',
method: 'get',
propertyName: 'data'
},
logout: {
url: '/auth/signout',
method: 'post'
},
tokenRequired: true,
tokenType: 'bearer',
globalToken: true,
autoFetchUser: true
},
},
},
redirect:false,
plugins: [ '~/plugins/roles.js' ]
},
here is my plugins/roles.js :
export default function ({app}) {
const username = app.$auth.user
if (!app.$auth.loggedIn) {
return console.log(username ,'roles plugin ', app.$auth.loggedIn)
}}
here is the res: null roles plugin false
the same result using this code:
export default function ({$auth}) {
const username = $auth.user
if (!app.$auth.loggedIn) {
return console.log(username ,'roles plugin', $auth.loggedIn)
}}
Ps:when i use $auth.user in my vue pages it gives me the whole user data (thats wonderfull)
I searched about this problem so i found common answers like :
*Change the user propertyName to false.
*reinstall node_modules.
but same result
Thank you every one <3
I am getting response payload from server like this:
{"0":
[
{"id":1,
"profile_id":"1",
"schoolName":"xx",
"courseName":"xx",
"courseDescription":null,
"created_at":"2020-06-25T09:11:21.000000Z",
"updated_at":"2020-06-25T09:11:21.000000Z"},
{"id":2,
"profile_id":"1",
"schoolName":"yy",
"courseName":"zz",
"courseDescription":"xx",
"created_at":null,
"updated_at":null}
],
"status":"Read Education info successfully!"}
Axios .then response is like this:
.then((response)=>{
vm.setState (
{ educations: Object.values(response.data) },
() => console.log(this.state.datas)
);
})
data- object has educations: []- array inside multiable
education: -objects
Q) how to pass axios response data payload to education object?,
export default {
data() {
return {
educations: [
education: {}],
--- Edit ---
Tried to get response like this:
.then((response)=>{
this.education = response.data.map(value => {
return {
schoolName: value.schoolName,
courseName: value.courseName
}
console.log('Receiving data ....')
})
Vue does not give any error, but I cannot see any data to pass data-object.
In Vuestools:
education : object
courseName: "" is empty.
I am using Axios module for Nuxt.js.
I do have problem with CSRF token. Whenever I log in into the app, I cannot send any POST request. The response is always 403.
Axios configuration:
Inside nuxt.config.js
axios: {
debug: true,
credentials: true,
baseURL: `${process.env.API_PROTOCOL}://${process.env.API_HOST}${process.env.API_PORT ? `:${process.env.API_PORT}` : ''}${process.env.API_PREFIX}`,
},
Inside 'axios.js' plugin / interceptor
const EXPIRED_TOKEN_MESSAGE = 'Expired JWT Token';
export default function ({
$axios, redirect, store,
}) {
$axios.setHeader('Content-Type', 'application/json');
$axios.setHeader('Accept', 'application/json');
$axios.onRequest((config) => {
const configLocal = config;
if (config.method === 'post') {
configLocal.headers['X-Requested-With'] = 'XMLHttpRequest';
configLocal.headers['x-csrf-token'] = store.state.authentication.csrf;
}
});
$axios.onError((error) => {
const { response: { data: { message } } } = error;
// const msg = status === 500 ? 'Internal Server Error' : message;
if (message === EXPIRED_TOKEN_MESSAGE && store.state.authentication.csrf) {
store.dispatch('authentication/logout');
return redirect('/');
}
if (process.client) {
// store.dispatch('alerts/addAlert', { type: 'error', message: msg });
}
return Promise.reject(error.response);
});
}
Request call:
this.app.$axios.$post('resources/add', data).then(() => {
}).catch(e => console.log(e));
Reproduction steps - under the hood of request:
After I printed request config inside $axios.onRequest as we can see from above everything is set, but in networking not at all
Going further backend server is not receiving any headers:
With console log:
`2019-07-04 18:45:18.380 DEBUG 712 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2019-07-04 18:45:18.380 DEBUG 712 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.`
Any ideas what's wrong ?