GAE implementing consistant facebook login using Datastore - facebook

I am implementing an mobile app for android and iOS and I am using GAE with the datastore for persistance as the server side of my app. My app uses facebook login for user authentication. One of the key aspects of the app is that users can interact with each other through the app but I want to keep their actual facebook-id secret so that user cannot discover the facebook profile of another user through my app.
My original design for this was using MySQL and there I had a simple implementation of a users table with the table primary key, an auto-increment integer served as the user id for the app. So I could safely send the user id of other users to the client app, and this did not give away any information I did not want to give away. When a user logs in, the client app performs all the necessary facebook login procedures and sends the facebook access token to the server. The server would extract the facebook user information from this token chech if a user with this id already exists, if so use this user row, otherwise create a new one.
On an SQL database this works great since it is strongly consistent, and there is no way I will "miss" the fact that the user is already in the table. However now when I am using the eventual consistent datastore with the same idea, I ran into a problem where if a user logs in for the first time ever, an entry is added to the datastore, but then if the user logs in again shortly after the query I am performing to check if a "User" entity with the same facebook-id is already present this query sometimes still return no results. This leads to the same facebook id being assosiated with 2 different users of my app and this is obviously bad.
(I know this seems like an unlikely scenario, but I actually accidentally ran into it during development)
I thought of a few ways to mitigate this:
Instead of using the app user id as the entity key use the facebook id, this ensures consistency (since there is no index involved in the lookup now). This would imply I need to use the facebook id as the id for my app and this violates one of the design principles (the facebook id of other users will now leak to the client app).
Instead of relying on the datastore generated entity key id for the user, specify the id myself, by performing some sort of deterministic manipulation of the facebook user id, such as a hashing it or encrypting it. This way I can use the key to perform the lookup and no matter how many times the same user logs in their user id will be generated the same. But this seems like too heavy an approach to do correctly. If I hash it I will need to make sure to use a good hashing algorithm to prevent collisions. A good hash or encryption will output a long string as a user id, which is not too bad, but I would like to keep the user id as a simple long integer value if possible.
Accept the fact that this is eventually consistent, during a log in if we find more then one corresponding entity, delete them and stay with one. This is bad, because what if the user has already performed some operations that are stored on the previous entity? I will have to run through all the data for the multiple user entities from the same user and perform some sort of merging operation on them. This will also require me to run through other entities that store the user id and change them all.
Use memcache to store the user, this will probably make this scenario even more unlikely, but not eliminate it entirely. Memcache entries can be evicted prematurely, and in this case we are back to swaure one.
What is the best approach here? Is there something I am missing? Would really appropriate your input.

Related

Facebook log in vs regular log in, mongo schema issue

I am using mongo db to store user data, their passwords. I have two ways of creating an account:
Regular sign up when user selects username and password and
Sign up using facebook log in.
Now, when I have regular sign up, password and username should be required, but using facebook log in they are not, so I am wondering how I should now design a schema for the users model to include both cases?
The most obvious way seems like to have two different models: users_facebook and users_regular, but is it the right way to go? Why or why not? It could also be users_auth (auth data only for users who signed up manually) and users_data (both users' types data). There is also something like MongoDB Facebook Stitch that is somehow used for the purpose it seems, although I do not get what it is. I am very new to databases and not sure which is the right way to go. The problem seems though pretty trivial.

couchDB / pouchDB / IONIC best practice

I want to create an app with IONIC to manage buildings. A user can hold multiple buildings. Each building has rooms. Each rooms has logs. Each user is a member of a cooperation.
For many years I've used LAMP. Now moving to mobile and made some IONIC apps. With 2 apps I've used sqlLite as datastore on the mobile device.
But now I've read up on couchDB and pouchDB and really like the concept and the sync option. So now I'm looking into this to use as my datastore (on the mobile and also on the backend).
Now I've got 2 major questions/concerns:
1) Authentication
In my LAMP situation, I usually have an SESSION (table which holds the sessions strings and userID) and an USERS table.
When the user logs in, the user is lookup in the USERS table, and a session string is created and saved with the userID.
Now each time a request is made to the server (for example update data), the session string is also supplied and matched to the SESSION table and retrieve the correct user. From that point on, I can validate if the post is valid and the data also belongs to the correct user.
Back to couchDB, I know there is a cookie management in couchDB (http://guide.couchdb.org/editions/1/en/security.html).
So here I can validate if an user exists and validate the credentials. Now the app can send requests with a cookie.
2) Fetch/Update the right data
In my LAMP situation, I always knew which data belongs to which user. And the back end always checks if this is correct.
In my couchDB I want to create database and each document is an user with all the data.
So now here comes the problem. I can validate an user in couchDB, put there's no way to validate the data (at least as far I know of) that it belongs to the right user.
My goal is that the mobile device syncs the document to the couchDB server.
3) Database structure
At first I wanted to create a database per user. But this is not scalable. Also an user is an member of a cooperation. I also need to generate reports per cooperation/user.
So now I was thinking to create a database per cooperation. But now the problem is, when a user login, I need to know wich database to connect to lookup the user data.
Now I want to use 1 database and each document is an user and holds al data (buildings/logs).
Has anybody got some other suggestions/resources on this approach?
You can try couchdb in combination with superlogin:
SuperLogin is a full-featured NodeJS/Express user authentication solution for APIs and Single Page Apps (SPA) using CouchDB or Cloudant.
github
Tutorial

How is one supposed to practically use the Access Control features in the Realm Mobile Platform?

I don't see an easy way to grant permissions to another user. It seems to be quite convoluted at the moment, and I wonder if I'm missing something obvious.
Say I want to invite another user to share a Realm. First I would have to ask the other user for their identification, then I would create the permission object, and then finally I would give the other user the address of my realm.
It would be great if I could share some sort of permission token via text message and let the new user register themselves. I suppose I could do that if I created another "User" which represented the shared group, and merely share this abstract user's credentials. It feels a bit hacky that way, but it seems easier to do.
I was hoping the demo application of the shared drawing environment would hold a clue, but after looking at the source code, it turns out both devices are logged in as the same user.
Am I missing something? Given the demo Draw application, how would one user practically invite a second user to join in their shared drawing environment? It seems like there would have to be a whole set of convoluted permissions and url/identification sharing handshakes.
Thanks for asking the question! Today, you will need to create a shared Realm that all users would input their user IDs into and have access to. This way any user can look up an ID and share access to another Realm.
We realize the limitations and are working on offering a number of improvements. The first is pretty close to what you describe, called a PermissionOffer object where you can inform the Realm Object Server you want to grant access to another user for a given Realm(s). The server will then provide a token you can share via any means with the other user. That user can then use the token to create a PermissionOfferResponse object and accept the access grant. This is coming soon, so stay tuned!
Later, we plan to offer a way to lookup user IDs so you don't have to replicate all of them in a shared Realm (see this issue).

Multi database authentication system, where should I store sessions using Zend Framework?

I am writing an ERM application using the Zend Framework in which user accounts are created under a main company account, enabling me to limit the number of user accounts for a company based on the license which the company paid for. Each company account has its own database (with identical structure to other companies) on my server to store data relevant to that company. The name of each companies database is stored in my "back end" database along with the rest of the companies account information and license key. The authentication system works as follows:
A new user (having never used the application before) lands on the index page and is greeted by a single text field for "Company Account Number"
After clicking "Submit", the next step in authentication is for username and password. When the user submits this form, all three pieces of information (account number, user name and password) are sent to my application's Authentication handler.
My "back end" database which stores company accounts is first queried to see if the account entered by the user exists. If it does, the company_db_name column is returned and a connection established then saved in the Zend_Registry. Otherwise, authentication has failed.
If the company account does exist, the database that was returned then has its users table queried for the specified username and password hash which either returns a successful instance of MyApp_Auth or false if the credentials were incorrect.
At first, I planned on storing user session data in the individual companies database, however I have run into the problem that there is no connection to this database when first landing on the application's index page. I have planned a workaround as follows:
Move my session storage table out of the customer's database to my "backend" database, which has a connection as soon as the application launches.
Add a "company account number" column to the table and index this column.
When a user lands on the application index page, the backend database can then be queried for the current user agent's sessionid. If it is found, then return all the necessary information i.e. the company database name to establish a connection, and the user's information to build a model with.
I have a couple questions regarding this approach:
Question 1 : Is there any risk in storing all session information for every user of my application in a single back-end database table? I am thinking in the multi-thousand user mindset.
Question 2 : I am concerned that a new user may visit the index page and by complete chance (understanding that this is a very low possibility, but still possible) have the same session_id as an existing session in the back-end database. Is this a valid concern, and if so, can it be mitigated?
Question 3 : Is there a better way, or would you recommend a different method to achieve my required functionality?
Thank you for your time!
To answer your 3 questions:
Answer 1. The is not risk as such for the storing session information of every user as long as you remove it on session expiration. The issue here is "scalability" what approach are you using? Is it scalable enough? What is the write/read speed? MySQL is 'structured' approach just like MSSQL. What processing time are you looking for? How much of information is stored? What is the architectural studies. Is it feasible enough for your client?
Answer 2. Ideally the session_id will not be the same so that should not be your concern.
Answer 3. You need NoSQL (Not Only SQL but, even more) approach. Read this
Looking at the MASSIVE-ness of your data, I strongly suggest you to go for HBASE (uses Hadoop, easy for multi cluster) or CouchDB or if you are Amazon fan dynamoDB.
Questions? :)
EDIT: Just realized you are using Zend Framework. In that case, you can also use MongoDB, and use Shanty Mongo library.

One time login in iOS - Most Efficient Way?

I am looking for the best way to do a One Time Login for my iPhone application. Using iOS 5.1.1 SDK but targeting iOS 4.1 for deployment.
Its purpose is to fetch a generated ID: if an ID exists then I don't need to login anymore, the ID will be returned in XML.
My application is an extension to a current web based service, it involves asynchronous HTTP POSTs on location updates with an ID as an identifier and checking the XML returned for any errors. The ID does not expire. It is a single view application as it just requires a start/stop button.
The username for the web service never changes so I just want to fetch the ID once off, there is no benefit or security risk if a person was to hack things and get the id due to the nature of the service and the application providing no information on the user. The process I would like goes as follows.
Application launched.
Do we have an ID stored? (yes/no)
If yes go into application.
If no present username/password screen to get ID.
On entering username/password, password is encrypted, sent to the server for verification, if yes then an id is returned and stored.
The username/password would be two inputs and a login button.
What would be the best way to go about this? I really don’t know what direction to follow here.
What I would recommend doing is using iOS's Keychain to store the ID of the user. You can never be too safe, Example usage can be found here GenericKeychain alternatively theres numerous easy to use wrappers to accomplish this.
If you really dont care for security, NSUserDefaults works for storage.
Also, I would suggest utilizing iCloud Document storage to make this ID persistent for all the user(s) devices. You can refer to this thread for more info.
Hope all that I suggested helped with your question !
UPDATE: For anyone else who finds this answer useful. As #sandmanza mentioned, be sure to include the Security.framework, if you go the Keychain route.
You can save ID in NSUserDefault and upon launching the app, you can retrieve ID from NSUserDefault and check whether ID is present or not, and based on that you can proceed further.