I need to get the coordinates from the browser and get the address of those coordinates. For that I can use the Bing Maps Location api (https://dev.virtualearth.net/REST/v1/Locations/*long*,*lat*?c=fi&o=json&key=*myapikey*).
How secret should I keep this key?
When embedding Bing Maps you also need a key that would be seen in the browser. Not sure how that key compares to the Locations api.
Should I create a separate key for those calls?
Can I do the api calls from javascript which would expose the key?
The alternative being that the frontend does a backend call with the coordinates and the backend is calling the Maps api.
Generally speaking you should keep your key private as anyone who gets the key can make transactions which would be billed to you. In practice this has not been a huge issue and it's easy to block a key and get a new one if this occurs. If you want to be more secure, keeping the key server-side and routing your client calls through the server will protect it. You can also generate a session key from your API key on the server when the page is first rendered and send that to the client. A session key works like a normal key, but has a short expiration time, so there's no danger of it leaking and being used by someone else.
Related
I have some REST services on my site that will be available for 3rd parties to access.
My plan is simple. In order to call on these services, they need to request a key from me. I will privately supply them with a GUID. Each call to any of my services will, via a filter, check the header for the key and accept/reject the request accordingly.
This site is all HTTPS so the key would be encrypted during transit. I'm not worried about the key being visually identifiable to authorized clients. In other words, I'm not worried about any kind of 'inside' attacks or people sharing the key. I just don't want random, unauthorized outside users.
I have looked around and I don't really see anybody doing it exactly this way. I feel like I'm over-simplifying... but on the other hand, I don't see what's wrong with it either.
My question is.. does this sound secure enough (from a basic/minimal perspective) or does it expose some gaping security hole that I'm not seeing?
FWIW - I am using the Spring Framework, including Spring Security 4.
Thanks!
If it's HTTPS and the API key is in the header encrypted during transit as you described etc, then it follows a pretty standard design authentication pattern.
Your security now depends on how you distribute and store your API keys.
Although, you could use an "Application Identifier and Key pairs" approach.
Whereas the API Key Pattern combines the identity of the application
and the secret usage token in one token, this pattern separates the
two. Each application using the API issues an immutable initial
identifier known as the Application ID (App ID). The App ID is
constant and may or may not be secret. In addition each application
may have 1-n Application Keys (App_Keys). Each Key is associated
directly with the App_ID and should be treated as secret.
Just in case you wish to extend the application in the future.
I am attempting to make a website's back-end API (I want to make the back-end independent of the front-end so I'm only making a server-side API for now, abiding to RESTfulness as much as possible). I haven't done this before so I'm unaware of the 'best' & most secure way to do things.
How I do it now:
Some parts of the API should only be accessible to a specific user after they login and up to 24 hours later.
To do this, I am generating a random Session ID whenever a user logs in (I'm using passwordless logins so the user is assigned that ID when they click on a link in their email) on the server side, which respond by sending that session ID to the client once. The client then stores this session ID in localstorage (or a file in disk if the client is not a web browser).
Next, I store that ID along with the associated email in my DB (MySQL table) on the server side.
Now every time the client want something from my API, they have to provide the email & session ID in the URL (I don't want cookies for now), which the server checks against the ones in the DB, if they exist then the server responds fully else responds with an error.
After 24 hours, the server deletes the email/session ID pair and the user has to login again (to generate another session ID and associate it with their email).
Now the questions:
Is my method secure or does it have obvious vulnerabilities? Is
there another battle-tested way I'm not aware of?
Is there a better way for the client to store the session ID (if
they are a web browser)?
What is the best way to generate a unique session ID? Currently I
generate a random 16-char string that I set as the primary key of
the session-email table.
Is using a MySQL table the most performant/best way to store session
IDs (given it will be queried with each request)?
Do I need to encrypt session IDs in any way? Is it secure for the
client to send it as a 'naked' URL param?
Sorry for having too many questions in one post but I think they're related by the single scenario above. If it makes any difference, I'm using F# and I expect my client to either be an android app or a web app.
Your REST API MUST not know anything about the REST client session, not even the session id. If you don't want to send a password by every request, all you can do is signing the user id, and the timeout, so the service can authenticate based on the signature. Use JSON web token: https://en.wikipedia.org/wiki/JSON_Web_Token
You can have a server side REST client, which can have the session your described. The question is, does it really worth the effort to develop a REST service instead of a regular web application? I am not sure in your case, but typically the answer is no, because you won't have any 3rd party REST client and your application does not have enough traffic to justify the layered architecture or it is not big enough to split into multiple processes, etc...
If security is important then you MUST use a true random generator algorithm or hardware. https://en.wikipedia.org/wiki/Random_number_generation#.22True.22_vs._pseudo-random_numbers It is not safe to send anything through HTTP, you must use HTTPS instead. You MUST use the standard Authorization header instead of a query param. https://en.wikipedia.org/wiki/Basic_access_authentication
I am developing an enterprise app where I need to pass a Session ID in REST requests which will pass the same id in my EJB methods.
The approach I have taken is:
Create a Session ID whenever user logins. Use this session id to pass as Header Param in each api except login. (I am still figuring out how to exclude one REST API)
Use this session id in the Header and pass it to each EJB. (How to read header param in subsequent Rest calls after interceptor is invoked.)
Can anyone please let me know, if this is the right way to go?
Also, will generating a one-way hash for creating a session token useful rather than sending a auto-generated primary key?
Passing a token as a header parameter to identify a logged in user is a common approach. Actually using OAuth is basically the same idea, but adding a standard way of doing so and adding the possibility of expiring/revoking tokens.
About generating a one-way hash, yes. That's the way to go. An auto generated primary key would be a terrible idea. If I log in and I am assigned session 1427, I can be almost 100% sure that there is a 1426 session available for a different user right now. Huge security hole.
Make sure you make those tokens as hard to guess as possible and use https throughout the whole process or you will be exposing your login tokens to eavesdroppers.
Yes. Dont use autogenerated primary key. If you are using multiple layers of application and dont want to use JSESSIONID, use SecureRandom to generate a session-token and use it.
All,
Getting "REQUEST DENIED" when I try to access Google Maps Geocoding web service. Not sure why. The URL looks right to me and the Simple Access API browser key is valid and has both Maps v2 and Maps v3 turned on.
I realize the API key is no longer required in v3 so I have no idea how to get around the API limits using the web services via query string params.
http://maps.googleapis.com/maps/api/geocode/json?key=MYAPIKEY&latlng=39.76144296429947,-104.8011589050293&sensor=true
When I remove the "key" parameter, it works but I need stats and don't wanna hit the API access limits so I need the key in there (I think)
Any suggestions would be great.
Thanks
Decided to go with geonames.org for this project. Much easier to deal with than Google.
I'm working on a REST webservice, and in particular authentication methods for browser-based requests. (using JsonP or Cross-domain XHR requests/XDomainRequest).
I've done some research in OAuth, and also Amazon's AWS. The big drawbacks of both is that I need to do either of the following:
Store secret tokens in the browser
Let a server-side script handle the signing. Basically I'd first to a request to a server of mine to get a specific pre-signed javascript request, which I'll use to connect to the real REST server.
What are some other options or suggestions?
Well, the only true answer here is proxying through a server, using sessions/cookies to authenticate and of course use SSL. Sorry for answering my own question.
Yes, jsonp call-authentication is tough, because the browser-client needs to know the shared secret.
An option would be to make the end-point anonymous (no authentication necessary). This comes with other security wholes (server is open for attacks, anyone can call it). But you could handle this by either only exposing very limited resource and/or using rate-limiting. With rate-limiting only a certain number of calls are allowed by one client in a certain range of time. It works by identifying the client (e.g. by source-ips or other client footprints).
I once experimented with one-time tokens, but they all somewhat failed because you have the problem of getting the token itself and protecting multiple retrievals of the token by bots (which comes again to the need of rate-limiting).
I havent tried this myself but you can try the following..(I am pretty sure i will get some feedback)
On the server side, generate a timestamp. Using HMAC-SHA256 an generate a key for that time stamp using a password and send the generated key and time stamp in the html.
When you make the AJAX call to the web service(assuming it is a different server) send the key and the time stamp along with the request. Check if timestamp is within a 5-15 minutes..
if it is do do the HMAC-SHA256 with the same password and key if the key generated is same.
Also on the client side you will have to check if your timestamp is still valid before making the call..
You can generate the key using the following url..
http://buchananweb.co.uk/security01.aspx