How to setup XSRF protection in angular js? - angularjs

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);
}

Related

Esri-arcgis request intercept based on wildcard route

I'm trying to implement a MapLayer in my react application. The map is only accessible over a proxy which needs authentication to identify the users for each end every request.
To provide the token i added the following request interceptor to make sure all calls which access that backend would be expanded by the authorization. If i do it this way there is no header added to the requests.
esriConfig.request.interceptors.push({
urls: ['backend/api/*'],
before: async function (params: any) {
params.requestOptions.headers = {
Authorization: 'Bearer ' + token),
};
},
});
If i remove the urls parameter so that all routes are extended with the token I'll recieve some cors errors because the esri package also makes some calls to another api where i get blocked because i'm sending an authorization header which is not expected.
Other api:
https://www.arcgis.com/sharing/rest/portals/self?f=json&culture=de-de
How can i make sure only requests to my api will be extended with the autorization header?
The urls property takes a String or RegExp or an array of those. See https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#RequestInterceptor
You're specifyng the url as a string (not a proper RegEx). You need to change
urls: ['backend/api/*'],
to
urls: [/backend\/api/],
or (without the array)
urls: /backend\/api/,

Angular file upload - intercept upload

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

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 () {
}
});

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

Restangular 1.4 setDefaultHeaders failing?

I am having trouble with Restangular 1.4 sending authorization headers to an external web api, which challenges if no such header is provided.
In the following code I try to set the default headers to include basic auth header, but when I look at Fiddler it tells me that no authorization header is present from the start, so the api call is rejected as unauthorized.
Does anyone know if this a bug in Restangular, or whether there is something lacking in the way I have tried to code the auth header?
angular.module('MyAPIService', ['restangular']).factory('MyAPIService', function (Restangular) {
Restangular.setBaseUrl('http://mywebapi/api/');
var encoded = Base64.encode(username + ":" + password);
Restangular.setDefaultHeaders({ Authorization: 'Basic ' + encoded });
return Restangular.one('users', username).get();
Try to set headers in configuration block (not sure about factories). My code looks like this:
angular.module('app', ['restangular'])
.config(['RestangularProvider', function (RestangularProvider) {
// ... some code here
RestangularProvider.setDefaultHeaders({
token: 'some-secret-token'
// other headers
});
// ... some code here
}]);
and works for me.
Turns out that the issue is that the Authorization header is null for all preflight (i.e.) OPTIONS request. (to learn about them, see the section on Preflighted Requests at [https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS). So since I was able to control the API's Basic Auth handling, I made the API not issue a 401 challenge for such preflight requests. The Authorization header was present on non-preflight requests (GET,POST,PUT,DELETE).

Resources