I'm working on a project where I'm building the frontend and someone else is building an API. I was proposing the following structure for all requests, sent as JSON:
{
"success": true, // true/false
"message": null, // a string if success==false indicating the error
"data": {} // The actual data in the response
}
They are more interested in making the API more RESTful, and instead of a "message" field they are proposing sending a message back in the status code message, in the HTTP headers, such as:
HTTP/1.1 401 Authentication Failed for john.smith#example.com. Please log in again.
and the frontend would display "Authentication Failed for john.smith#example.com. Please log in again." in a popup or something.
I'm worried about length restrictions, but I couldn't find anything indicating no maximum length. Should we ensure we keep those messages to a minimum length? Is there a good reason to not do this, and instead send it back as content (JSON or plain text)?
A little testing will go a long way, but you should be okay to do this and in fact the RFC says specifically:
The reason phrases listed here are only recommendations -- they MAY be replaced by local equivalents without affecting the protocol.
The only possible concern you may have is header size (some servers may have limitations, but I think they are all relatively large) and how some older browsers may react to this. Frankly I think it makes more sense to use the response body since it's easier to interpret and clear, but there shouldn't be anything wrong with your approach.
I want to add, although there might be no limit in the specification, there is a real chance of implementations to truncate the status message, as I discovered, when I was trying something similar as the OP with Jetty 9.4.14 .
It took me some time to find the reason for the truncated message - there is a hard coded, not configurable limit of 1024 characters [see method getReasonBytes(String)].
(could not post this as comment due to lack of reputation)
Related
I'm validating addresses to make sure they exist. I'm using the google API to do this. I have a google API key and it works great.... until I go over 100. At request 110 I get this
{
candidates: [],
error_message: 'You must use an API key to authenticate each request to Google Maps Platform APIs. For additional information, please refer to http://g.co/dev/maps-no-account',
status: 'REQUEST_DENIED'
}
All I'm doing is looping through a list of addresses. It works perfectly up until then. And it's always at the exact same point.
I've tried slowing it down (thinking i'm making too many requests too quickly) by wrapping it in a while loop and only doing 50 at a time, but all that does it slow it down but still crashes at exactly 110.
Any ideas why or how or how to fix it? It is an unpaid API key if that helps (wondering if they have a request limit, I can't find anything saying they do)
While it seems most likely that you have reached the quota allowed on an non-billing account, the status code should read "OVER_QUERY_LIMIT" which indicates that you are over your quota, rather than "REQUEST_DENIED", which you are getting.
https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
Further down, on the same page you have a suggestion as to the likely cause:
"REQUEST_DENIED" indicates that the request was denied. Possibly because the >request includes a result_type or location_type parameter but does not include an >API key or client ID.
You have to set up a billing account.
Turned out to be one of the parameters I was sending to it had a special character that was breaking it. I printed out the URL before sending it to see what was going on.
TLDR had to use encodeURIComponent on the addresses I was sending, before sending them
I have successfully set up the feedly developer access token using the javascript library Axios on a NuxtJS site. I am having trouble, though, figuring out how to set up the refresh token.
This is the process I have used for the developer token
export default function({ $axios }) {
$axios.onRequest((config) => {
config.headers.common['Authorization'] = [FEEDLY_ACCESS_TOKEN]
})
}
This code gets run whenever I make the relevant axios request.
What I am wondering, now, is what I need to do for the refresh token. I have taken a look at the instructions on these two pages:
https://developer.feedly.com/v3/developer/#what-happens-once-the-developer-access-token-expires
https://developer.feedly.com/v3/auth/#refreshing-an-access-token
However, I'm still not 100% clear as to what I am supposed to do. In particular, I have two questions:
Do I also run the refresh token each time I make an axios call -- or should I create a function that runs every thirty days and runs the code.
How exactly do I make the axios call for the refresh token. My initial guess is something like this:
$axios.$post('https://cloud.feedly.com/v3/auth/token/?refresh_token=FEEDLY_REFRESH_TOKEN&client_id=feedlydev&client_secret=feedlydev&grant_type=refresh_token')
Is that correct? If not, what do I need to change.
Thanks.
Different developers will use different strategie regarding refreshing an access token. While some will return a new token on every request, other will do it over a term of days or longer.
The idea is to reduce the window of risk in which an access token can be abused but it is sort of a subjective topic imo. Obviously there is a performance penalty when you generate a new access token on every request. Sometimes this may be acceptable, but I really don't think it's necessary in many cases. Measure the tradeoff between the penalty and the sensitivity of the token in your case.
The docs explain it well:
Endpoint:
POST /v3/auth/token
It does say that using url parameters is not recommended, so why not just do it the way they recommend it? Either:
using a x-www-form-urlencoded POST request (standard)
as a JSON object (make sure you set the Content-Type header to “application/json”)
You have more questions around this?
I'm trying to get the number of likes from a Facebook page with the following line of code in JavaScript, but I get the "application request limit reached error" even though I only made one API call to a single FB page
var jsonData = UrlFetchApp.fetch("https://graph.facebook.com/" + name);
Request failed for https://graph.facebook.com/nba returned code 403.
Truncated server response: {"error":{"message":"(#4) Application
request limit reached","type":"OAuthException","code":4}} (use
muteHttpExceptions option to examine full response)
I'm confused on why this is happening and I've looked at similar questions on StackOverflow regarding this problem, but none seemed to give the right solution or point me in the right direction. Any help is appreciated. Thanks!
App Level Rate Limiting
This rate limiting is applied globally on application level. When the app uses more than allowed resources the error is thrown.
Recommendations:
Do not make multiple calls in small amount of time, spread out the calls throughout the day.
Do smart fetching of data, you can always fetch important data only, you can remove duplicate data as well
Use parameters: "since", "until", "limit" to limit/filter the requests
You can find out more in Official documentation here!
I have get a request from an API, some times I would get the EXIF information, but sometimes I will get error message {"error":"no exif data"} How can I hide this error message.
In chrome, the error is 400 (Bad Request)
$http.get(res.getQNUrl(domain, key, "exif"))
.success(function(data){
$scope.imageExifMap[key] = data
}).error(function(data,status,headers,config){})
The error message you mentioned above is browser specific. It is a browser logging functionality.
Well there is a workaround(not a solution since its not a problem) for it. I would not recommend it since its a built-in browser functionality you are trying to suppress from doing the task it is meant to do, but if that is what you want then here are couple of ways to achieve it.
Using a regular expression filter like so
^(?!.* 404 \(Not Found\))(?!.*[file name])
Using a Log filter like so
I have not explained it much because there is already an SO question that explains these in detail.
Please refer this SO for detailed explanation regarding the above mentioned workarounds.
I am starting to build/design a new single page web application and really wanted to primarily use client-side technology (HTML, CSS, JavaScript/CoffeScript) for the front-end while having a thin REST API back-end to serve data to the front-end. An issue that has come up is about the security of JavaScript. For example, there are going to be certain links and UI elements that will only be displayed depending on the roles and resources the user has attached to them. When the user logs in, it will make a REST call that will validate the credentials and then return back a json object that has all the permissions for that user which will be stored in a JavaScript object.
Lets take this piece of javascript:
// Generated by CoffeeScript 1.3.3
(function() {
var acl, permissions, root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
permissions = {
//data…
};
acl = {
hasPermission: function(resource, permission, instanceId) {
//code….
}
};
root.acl = acl;
}).call(this);
Now this code setup make sure even through the console, no one can modify the variable permissions. The issue here is that since this is a single page application, I might want to update the permissions without having to refresh the page (maybe they add a record that then needs to be added to thier permissions). The only way I can think of doing this is by adding something like
setPermission: function(resource, permission, instanceId){
//code…
}
to the acl object however if I do that, that mean someone in the browser console could also use that to add permissions to themself that they should not have. Is there any way to add code that can not be accessed from the browser console however can be accessed from code in the JavaScript files?
Now even if I could prevent the issue described above, I still have a bigger one. No matter what I am going to need to have the hasPermission functionality however when it is declared this way, I can in the browser console overwrite that method by just doing:
acl.hasPermission(resource, permission, instanceId){return true;}
and now I would be able to see everything. Is there anyway to define this method is such a way that a user can not override it (like marking it as final or something)?
Something to note is that every REST API call is also going to check the permissions too so even if they were to see something they should not, they would still not be able to do anything and the REST API would regret the request because of permissions issue. One suggestion has been made to generate the template on the server side however I really don't like that idea as it is creating a very strong coupling between the front-end and back-end technology stacks. If for example for whatever reason we need to move form PHP to Python or Ruby, if the templates are built on the client-side in JavaScript, I only have to re-build the REST API and all the front-end code can stay the same but that is not the case if I am generating templates on the server side.
Whatever you do: you have to check all the permissions on the server-side as well (in your REST backend, as you noted). No matter what hoops you jump through, someone will be able to make a REST call that they are not supposed to make.
This effectively makes your client-side security system an optimization: you try to display only allowed operations to the user and you try to avoid round-trips to the server to fetch what is allowed.
As such you don't really need to care if a user can "hack" it: if they break your application, they can keep both parts. Nothing wrong can happen, because the server won't let them execute an action that they are not authorized to.
However, I'd still write the client-side code in a way that it expect an "access denied" as a valid answer (and not necessary an exception). There are many reasons why that response might come: If the permissions of the logged-in user are changed while he has a browser open, then the security descriptions of the client no longer match the server and that situation should be handled gracefully (display "Sorry, this operation is not permitted" and reload the security descriptions, for example).
Don't ever trust Javascript code or the front-end in general. People can even modify the code before it reaches your browser (sniffers etc) and most variables are accessible and modifiable anyways... Trust me: you are never going to be safe on the front-end :)
Always check credentials on the server-side, never only on the front-end!
In modern browsers, you can use Object.freeze or Object.defineProperty to make sure the hasPermission method cannot be redefined.
I don't know yet how to overcome the problem with setPermission. Maybe it's best to just rely on the server-side security there, which as you said you have anyway.