I have an Android application that allows users to post information to a database, via a java web server that I have code on.
Users are allowed to up/down vote said post. How do I prevent the same user from voting a plethora of times on the same post?
A few ideas I had:
Disabling locally via adding a local storage "key" for the post ID Unique Key. For instance, when the user votes up or down. It writes a key with the information of the type of vote and the Unique Identifier of the post on the user's local storage. Is this feasible with a lot of votes? Would it cause any sort of hard drive consumption/lag?
Storing a uniquely-generated key on the user's phone generated at application install. This key would be submitted to a new table in the database that associates posts with votes and the "user-key".
If you're expecting lots of information, a database is probably the way to go. Obviously this will use storage space, but not much. Writing to the db tends to be very fast in my experience.
The unique key would work fine too. That way would be more secure (depending on how you do it) since it would be harder to spoof it from the client. If you generate the key based on the user's Google account, or the device ID, you're in good shape. If you do it by some pseudorandom method then the user could still cast multiple votes by just clearing the app data and getting a new key.
If it's really important to prevent multiple votes, do it on the server. If it's not particularly important, do whichever method seems easier to you. You can also consider doing both, for the best of both worlds: immediate feedback to the user on a duplicate vote attempt (or just altering the UI to make it impossible), plus a backup validation on the server in case the user tries to get around the client check.
Related
Background
I work on an app that among other things, allows to contact with businesses found via Nearby-search, navigate to them, visit their websites...
Once the user performs any action on a single business, it's supposed to be added to the recents-list, allowing the user to do it again, or see the information about the business again.
If the user called some business, next time he visits the recents-list, it should be shown there as a list-item, along with the name, phone number, etc...
Same goes if it was navigated to.
The problem
I've noticed in the terms a very big limitation of caching, saying that only the place-ID is allowed to be store permenantly, and the basic geographic-coordinate (lat-lng) can be stored for 30 days.
Weird thing is that it says it's ok to store only place-ID and coordinate, but I couldn't find what's the use of these if there is no mapping and context whatsover with them. And of course if you add context, you actually do store more information. For example, if you've called the place and showed the name, you already know both, so both should be mapped to the place-ID...
Links:
https://cloud.google.com/maps-platform/terms/maps-service-terms#5.-places-api
Caching. Customer can temporarily cache latitude (lat) and longitude
(lng) values from the Places API for up to 30 consecutive calendar
days, after which Customer must delete the cached latitude and
longitude values. Customer can cache Places API Place ID (place_id)
values
https://cloud.google.com/maps-platform/terms/#3.-license
No Caching. Customer will not cache Google Maps Content except as
expressly permitted under the Maps Service Specific Terms.
https://developers.google.com/places/web-service/policies#pre-fetching,-caching,-or-storage-of-content
Applications using the Places API are bound by the Google Maps
Platform Terms of Service. Section 3.2.3(a) and (b) of the terms
states that you must not pre-fetch, index, store, or cache any Content
except under the limited conditions stated in the terms.
Note that the place ID, used to uniquely identify a place, is exempt
from the caching restriction. You can therefore store place ID values
indefinitely. The place ID is returned in the place_id field in Places
API responses.
What I've found
Sadly I couldn't find more information about this.
What I was told by someone is that caching should be fine for 24 hours as a part of "fair-use" to avoid re-queries of things that you already got, similar to how web browsers handle queries. This can help in case the user wishes to see information he already got just a few seconds ago, for example.
I was also told that if it's local on the user's own device, it should also be fine, as it's not published outside, and as the user could have saved the information anyway, manually.
For each of those claims, I couldn't find a reference.
This is very important here, as there has to be some mapping between the items on the "recents" list of the app and the actual place. For example, if it was a phone call, it has to at least have place-id (of the place) and the phone number (of the call). But it should also show the name of the place, as the user just showed this information and expect to see it there too, instead of just a phone number.
The questions
Weird thing is that it says it's ok to store only place-ID and coordinate, but what's the use of these if there is no mapping whatsover with them? What could I do with this exactly?
What is the fair-use of caching in this case?
Is it true that caching is ok in general for 24 hours, for all APIs ?
Can I also store in storage if it's very relevant as the user did something related to the query (dialed the phone number of the place, so should be possible to see this information right on the list, with other places)? I mean to store basic, relevant information I got from Google Places, for each recent-list-item ? Maybe I could set the basic information with an expired-date, while letting the place-ID stay, and when it's expired, only then to re-query?
Otherwise, it would mean the app will need to re-query all places each time the list is shown, to get a mapping between phone numbers and each place's information, and could easily cost a lot of money.
I wish to customise Views to target different types of people.
How do I identify a user without a) any input from them or b) caching data on their device c) using cookies or storing anything on the device.
I want to save the person identifier in a database table called "likes", to which I'll log views, time spent viewing articles etc.
In the database without them having to register and on future refreshes, use that data in order to display content tailored for them.
I don't need it to be 100% accurate, and if people are going to make the effort to fool the system then I'm happy to let them, because I don't handle any sensitive data.
So knowing this, what are the key identifiers for users available to my website?
I envisage my site/service being loaded via Android/iOS app or mobile/desktop browser.
Once identified, I wish to save data about them for showing articles/content both now and in the future.
The situation: I have many real life locations with specific information associated with them, and updated frequently. I am unsure of how to store this information for use in an android application.
My original thought was storing the data on some server/cloud source/database, reading from the server from each Activity in the app to make sure the info is up to date, and update the server with any changes that may or may not have been made.
For example: there are 200 people inside the library, one person leaves.
So we would read the number of people from the server, display this on the app, person leaves, subtract one, send the new number back to the server.
Would this be an incorrect approach? I'm fairly new to Android in general, and I really have no experience on how to approach this type of situation, what services to use, etc.
I would look into using Parse, its a pretty sweet way to power the backend, and their website is very detailed in explaining how to use it.
The app that I'm developing allows the user to enter in a zip code, then the app displays my local businesses that are closest to them. So if someone entered in a New York zip code, all of my franchises located in NY would show up.
It would be ideal if I could see what zip codes are most popular with the usage of this app, and which states receive the most traffic.
Is there a way to record/analyze the entered in zip codes of my users, and have that data sent back to me? Will this become a privacy issue if I gather this data?
Thanks
EDIT
The zip code the user will enter is simply in an EditText.
What you want to do is certainly possible. Since you're posing this question at all, I'm guessing you're app has the available franchises stored locally as opposed to retrieving them from a server.
Where is the data supposed to be sent to? If you have a server, you can use an HttpsURLConnection and POST the requested zipcode to your server when the user presses calculate or however else calculation is kicked off in your app. You will need the internet permission for this to work.
As a word of caution, you should be very up front about that you're doing this to the user, and also give them an option to turn it off, or even have it turned off per default. Personally, this would be the kind of thing that would bother me a great deal if I were to use your app. (Actually, if I couldn't turn it off, I probably wouldn't use it.)
EDIT
I'm not an expert on U.S. privacy laws but I imagine you probably need a formal privacy statement, as well. You certainly do if your app is also available in the European Union (regardless of whether it's useful there or not - whether or not it's available is enough.)
Yes you can easily collect this data and return it to a server. This will require an additional permission for your application 'android.permission.INTERNET' (If not already included.)
Not a lawyer and didn't stay in a Holiday Inn... but I don't see a privacy concern if you're using anonymous data... if you're packaging up user information (Name, Phone #, etc.) and sending it back I would think you'd want to include a "privacy policy" in your app's terms of service.
I just noticed this article about a mobile app that is storing user information in plaintext. I've paid attention to the idea of storing the user's password on the server (using a SHA-512 hash function), but I'm not clear on the best methods for storage of personal information at the device itself.
Let me be clear I am essentially only talking about user names and passwords. The data that my app interacts with is not at all sensitive, and I know that I can implement some sort of symmetric encryption/decryption on that data.
For user convenience purposes, I'd like to offer the user an option to store their user name and password locally so that they aren't required to enter it each time they use the app. But I know that user's tend to reuse the same password for many different purposes, which means that I need to take precautions to keep my user's passwords secure. Classic tension between convenience and security.
Is it just simply a terrible idea to ever store this information locally? Or are there relatively simple means to securely encrypt this? Do the iOS and Android O/S provide any help with this?
Not necessarily looking for exhaustive answers, but I'd really appreciate some topics to research, article links, books, etc. Thank you very much. If this is a redundant question, please direct me to any posts that give answers that are still considered current.
Thank you very much!
All data on the device is automatically encrypted by the device to some degree, using the device id as the key. This prevents data from easily being read by anything other than the device itself, or someone with the device id anyway.
There's another level of encryption that you can pile on that utilizes the passcode, called Data Protection, which prevents the data being read unless the passcode is entered.
You can manually enable data protection in your app by using NSFileManager to access files and setting the NSFileProtectionKey attribute to NSFileProtectionComplete. See: Implementing and Testing iOS data protection.
Note that the user must set their device to require a passcode, and the stronger the passcode, the more secure the data will be.
You may be able to easily enable data protection through the provisioning profile for your app, even if you don't use the NSFileManager class with NSFileProtectionComplete. See: Data Protection / NSFileProtectionComplete - successfully supported through entitlements.plist?
I still wouldn't store the password. Store a randomly generated session key that is created when they log in. At least you can expire those and it's not the plain text password.
Just a follow up to this post from a year ago. What I decided to do was to generate a random session key (similar to #Marcus Adams suggestion) but use that value as a salt. I then concatenate that session key with the user's chosen plaintext password and store this value on the device (if the user elects to store their password). i.e, the device stores this value:
device_hash = sha256(device_salt || plaintext)
That hashed value then becomes the string that I pass over HTTP to the server for validation. On the server side, I have a different salt value stored over there. When the server receives the device hash value, it has its own salt value which it concatenates to that string, and then performs its own hash. That final hash is the password that is stored in the server database. i.e., the server stores this string:
server_hash = sha256(server_salt || device_hash))
I think that this is a viable balance between security and convenience, particularly since I am only trying to protect the password, and not trying to encrypt the actual data that gets exchanged in the normal course of the app. If the user's device is compromised, no attacker can use a rainbow table or anything like that to reverse engineer the password since it is salted. SHA256 along with the long length of the password should eliminate a brute force attack if someone were truly motivated.
Curious if anyone has any criticisms of this approach.