Angular file upload - intercept upload - angularjs

I am using nervgh/angular-file-upload to upload files to the server. I am using a token authentication and need to intercept every call in order to attach/refresh a token when it expires. I can provide a token to file uploader like this:
$scope.uploader = new FileUploader({
url: 'upload_endpoint', headers: { 'Authorization': access_token }
});
But it's not getting into the interceptor, thus I cannot replace a token with a new one when the token expires. Any chance I still can intercept?
Thanks

There is a fileUploader callback called onBeforeUploadItem that you can use.
Ref. https://github.com/nervgh/angular-file-upload/wiki/Module-API

Related

How to check CSRF token using AJAX and CakePHP 3 when user is not logged in?

So I made my site live and I am entering into the public realm where people aren't always nice. I just started learning about CSRF and saw that it was something I needed when I made my cakephp 3 site live. As seen here!
I added the csrf component and the security component to my site, but I have 1 major problem. Now, when users want to sign up they can't. I use a custom form for stripe to send payment, but also add a user using ajax to my database. The user gets added first and then the payment is processed and saves the order to the database as well.
According to stripe docs I add the token in a hidden value to the form after I click the submit button and can't help but notice that my new security is not allowing this to happen.
Since I am using ajax to send the post data to my users controller and adding a form input on submit,
How do I check the csrf token and make sure there isn't a security leak without disabling the security for the actions involved?
An example of how this is to be done would be greatly appreciated since examples seem to be lacking for doing this in cakephp 3. It is also hard for me to figure out how everything works since the cakephp 3 automagic adds the tokens to the forms and cookie. I am unsure how/where/what to check.
For pass X-CSRF-Token, use beforeSend parameter in your Ajax request, and define csrfToken value of cookie.
$.ajax({
url: '/foo/bar',
type: 'POST',
dataType: 'HTML',
data: data,
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
})
.done(function(data) {
alert('done !');
});
According to stripe docs I add the token in a hidden value to the form after I click the submit button and can't help but notice that my new security is not allowing this to happen.
Cake's CSRF token would have no effect when POSTing to another site.
Since I am using ajax to send the post data to my users controller and adding a form input on submit,
How do I check the csrf token and make sure there isn't a security leak without disabling the security for the actions involved?
The CSRF token is available in cookie named csrfToken, so read that token in your javascript and set X-CSRF-Token header for your AJAX request. The CsrfCompoment will do the checking.
using js function:
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
...
then
$.ajax
({
type: "Post",
url: "URL_HERE",
data: {some_data},
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', getCookie('csrfToken'));
},
success: function (e) {
},
errors: function () {
}
});

"Failed to parse UUID" error message on attempting to login via TrueVault api

On attempting to login via the truvault api using angular js, I am getting this error message: Failed to parse UUID. I am passing the username, password and account_id as params. I am successful using the curl command and get the success response.
The 400 error is not described in the api docs for authorization. I am not sure about if this UUID is linked to the schema_id. Would anyone (truevault guys!!) know what I am doing wrong?
I contacted truevault support on this one. Dan helped me get through it.
I was passing the username/password/account_id as url string query parameters. I had to make two changes to the code:
1. Pass the above as form data parameters
2. add the angular-post-fix.js to my project.
(Note: I am not adding the link as there are editors who will disallow the post with links to elsewhere. It has happened in the past!)
When using Node.js, the querystring API is really useful. Just pass an object to the querystring.stringify() function, and the resulting output is ready to be sent to TrueVault for login.
Additionally, I found that adding the header 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' might be necessary (which is one of the things the Angular post-fix library does).
#orthodoc is right, but is kind of tricky how to actually build the request. Lets say we are using fetch with formData params, I'd like to add an example of a successful request:
...
var formData = new FormData();
formData.append('username', username);
formData.append('password', password);
formData.append('account_id', accountId);
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
body: formData
});
...

AngularJS - Setting default http headers dynamically

To overcome csrf attack, I have to send in csrf-token value in a header for every request by picking in the value from cookie as described here. Since this is to be done at every request, I am setting the default headers for $http in the main module's run function.
Now, If a new tab is opened for the same website, a new csrf token (in cookie) is issued by the server. Since the run function is run only once, the default header for csrf will be old one (for old tab), while the new csrf cookie will be sent to server, resulting in csrf-mismatch.
How to overcome this at a global level?
I want somehow to create a function which will be run everytime the $http is called, so that then I'll override the default headers.
Note: I do not want to set this header value for every $http request.
(Not that I think that it's relevant, but I'm using ui-router)
Edit
This is not just limited to csrf-token, I want to set some other headers too based on the logged in user, which has to be done dynamically (say when one user logs in, and logs out, then another user logs in).
you need to use http interceptor to do this on every request. read more about http interceptors here
below is one such example
module.factory('xsrfTokenInterceptor', function ($q, $http) {
return {
'response': function (response) {
var cookies = response.headers("Set-Cookie");
var token = someCrazyParsing(cookies);
$http.defaults.headers.common["X-CSRFToken"]=token;
return response || $q.when(response);
}
};
});
module.config(function($httpProvider){
$httpProvider.interceptors.push('xsrfTokenInterceptor')
})
How about headers $http(config) parameter.
$scope.getWithHeader = function(){
$http({
method: 'GET',
url: 'http://fiddle.jshell.net',
headers: {
'CustomHeader': 'HelloWorld'
}
}).success(function(){
console.log("success");
});
};
sample code on jsFiddle

upload file to RESTful service in angularjs

i try to make angular CRUD app that is a bit like "dropbox". So, it must have file and folder hosting with sharing and access functionality. I'm stuck on a question how to upload image and video files? I used File API (FileReader, Blob) to make preview of files on the client side but i dont have idea how to POST this type of data to server.
Something like this should work well to send as multipart/form-data request to backend API:
var file = ... // get from file input;
var backendUrl = ...
var fd = new FormData();
fd.append('myFile', file, 'filename.ext');
$http.post(backendUrl, fd, {
// this cancels AngularJS normal serialization of request
transformRequest: angular.identity,
// this lets browser set `Content-Type: multipart/form-data`
// header and proper data boundary
headers: {'Content-Type': undefined}
})
.success(function(){
//file was uploaded
})
.error(function(){
//something went wrong
});
See here for reference:
FormData API Doc
Using FormData Objects (MDN)
multipart-formdata file upload with AngularJS
You can upload file using ngFileUpload or angularFileUpload directives.
In case of angularFileUpload, you use .upload in controller and in case of ngFileUpload, you use .http
Also, you can also use application/x-www-form-urlencoded content type instead of multipart provided your file is not huge. In case of application/x-www-form-urlencoded, you can just receive the value in rest webservice as normal InputStream thereby requiring no need of marshalling of multipart data.
You may refer the below for the possible ways to upload file using angular js and rest web service:
http://technoguider.com/2015/08/file-upload-using-angular-js-and-rest-web-service/

How to setup XSRF protection in angular js?

I am developing an application using angularJs, resources and jersey rest api's. And I want to implement xsrf protection in my project. Please suggest a better example. I got one example here, but it uses ColdFusion. http://www.bennadel.com/blog/2568-Preventing-Cross-Site-Request-Forgery-CSRF-XSRF-With-AngularJS-And-ColdFusion.htm
Different from given example, you need to do 2 things:
When the main page gets loaded once the user logs in, you need to set a session cookie with name XSRF-COOKIE. Then AngularJS will do the rest by appending a header to every request as stated in documentation (1)
You need to validate every call to your rest API in back-end (for example with an interceptor) by comparing the token in cookie and the one in header. The logic is described on the page you referenced
(1) To take advantage of this, your server needs to set a token in a JavaScript readable session cookie called XSRF-TOKEN on the first HTTP GET request. CSRF Protection section in Documentation
Incase this is your code in jsp/ html page which sets the header and token:
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
You can configure the csrf headers for all ajax requests as flollows:
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
angular.module("app", [])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common[header] = token;
}]);
And then your http request code will go as follows:
$http({
url: "loadMyData.htm",
method: "POST",
}).success(function(data)
{
console.log(data);
})
create interceptor with below command.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const cookie = this.cookieService.get('XSRF-TOKEN');
request = request.clone({
headers: new HttpHeaders({
'XSRF-TOKEN': cookie,
}),
withCredentials: true
});
return next.handle(request);
}

Resources