Esri-arcgis request intercept based on wildcard route - reactjs

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/,

Related

How to attach an Authorization header with a token when using Leaflet js

I am using Leaflet in my Angular.js map application. One of my resources requires an authorization header with token. I am using the leaflet-realtime plugin (found here: https://github.com/perliedman/leaflet-realtime) to get map updates and therefore need to be able to specify my header when realtime performs a fetch to get the data.
I first tried using another library, fetch-intercept (found here: https://github.com/werk85/fetch-intercept), to intercept the requests and attach the header, but the interceptor was being ignored. I included a console.log in the interceptor and it was never reached.
After more research, I noticed specifying headers is supposed to be supported: https://github.com/perliedman/leaflet-realtime/pull/83. However, I cannot find an example for how to properly attach an authorization token. Here is what I am currently trying:
this.mapRealtime = L.realtime({
url: this.getRealtimeUrl(),
crossOrigin: true,
headers: {"Authorization": "token"},
type: 'json',
},
However, when I check the Network logging from my web browser (Chrome) debugging console, all I see for the Request Headers is:
Provisional headers are shown
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
and the server returns status 403 with errortype MissingAuthenticationTokenException.
Can anyone provide an example of how to correctly attach the token? Thanks!
The realtime Leaflet only take url or json file path and you will be unable to pass headers(auth) as they have patch for it which is not working. I was facing same issue. What I did is following:
realtime = (L as any).realtime(async function (success, error) {
let geodataJson = await self.updateGeoJson();
success(geodataJson);
}, {
interval: 15 * 1000,
onEachFeature: onEachFeature,......
I have pass funtion to realtime and in that function I called simple API with headers
async updateGeoJson() {
await this.api.getMarkersGeoJson().subscribe((res: any) => {
this.geoData = res;
});
return this.geoData; }
On first call it will not get data in from this function so we also need to load data in this.geoData in ngOnInit before initmap.
For me it is working I know this is just work around but this issue is still in leaflet realtime. Hopefully this will work for you

How to call App Engine Endpoints with the JavaScript library in promises mode

I have a web application which calls several App Engine Endpoints with the Google API JavaScript client library.
I am currently changing this application from callback mode to promises mode, as recommended by Google (https://developers.google.com/api-client-library/javascript/features/promises#using-promises) and I am encountering a problem. Note that the app works well with the callback mode.
My problem with the promises mode is to find what is the correct path argument to use when calling the request method:
JavaScrit code:
var params = {'webSafeKeyParent’: ‘neN4fm15xW52b2ljZXMtb19saW5lmlYLEglBY1NFwpRpdHkYgICAgQj97AoM’};
gapi.client.request({
'path': 'https://myappenginename.appspot.com/_ah/api/customerApi/v1/?????????',
'params': params
}).then(function(response) {
// Handle response
}, function(reason) {
// Handle error
});
Endpoint definition in "customerApi":
#ApiMethod(
name = "listByParent",
path = "customerByParent/{webSafeKeyParent}",
httpMethod = ApiMethod.HttpMethod.GET,
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE})
public List<Customer> listByParent(final User user, #Named("webSafeKeyParent") final String webSafeKeyParent, #Nullable #Named("cursor") String cursor, #Nullable #Named("limit") Integer limit) throws UnauthorizedException {
For few of my endpoints it works by including in the path argument of the JavaScript request method, the values of "path" and "name" as declared in the #ApiMethod annotation.
i.e. for the above endpoint, the following path works:
https://myappenginename.appspot.com/_ah/api/customerApi/v1/customerByParent/listByParent
Strangely enough this does NOT work for some other endpoints of the same kind. I receive either a 404 HTTP error or a 503 one.
I've also tried with the paths displayed under "Request" when you query the endpoints with the APIs Explorer but without success....
Is there any detailed documentation on how to call App Engine Endpoints with promises, with the Google API JavaScript client library? I have not found any. Do you have some advice to share please?
Thanks in advance
Actually the request method DOES work ALL THE TIME with the "path" argument composed of the values of "path" and "name" as declared in the #ApiMethod annotation...
It was a mistake on my side if it didn't work for some endpoints. Don't know which mistake, however.
Note that I have noticed that it is very important to pass to the JavaScript request method the correct httpMethod of the App Engine Endpoints. By default the request methid assumes that it is a GET. In case your Endpoint has httpMethod= ApiMethod.HttpMethod.POST in the #ApiMethod annotation, you shall pass the argument 'method': 'POST', as detailed in the doc: https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiclientrequestargs

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

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).

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