SQL - Methods of storing intermediate sign-up information for users - database

I am designing a Node + MySQL backend for a service that requires two-factor authentication to be set up for all users as a part of the sign-up process. Users first submit a primary phone number and password (with the phone number being used for sign-in), upon which the server sends them an SMS with a six-digit code. Only after they enter the code is their account fully created.
This poses the problem of how to store data for users in the intermediate state after entering username/password but before verifying the code. Such "pending users" will not be shown in searches, do not need to store all the data a regular user would, and will be deleted after a few days if never verified. Furthermore, since every user must enable TFA to fully sign up, there will be orders of magnitude more users than "pending users". Thus, it does not seem sensible to me to have all users simply store an "isVerified" flag. I am familiar with SQL on a technical level but have no experience designing databases for production, and I am wondering what alternate mechanisms I should consider to solve the aforementioned.
My current idea is to have a separate table of pending users, having only those columns necessary to store intermediate signup information. When a user verifies, a row is created in the real user table, the signup information is copied over, and the corresponding is row deleted from the pending users table. However, this makes it somewhat ugly to ensure that the primary phone numbers are unique across both tables (which is an additional requirement of the service).
What methods/techniques should I consider to improve my solution?

You can store this data same way as store session information on server.

Related

What is the right way to maintain user audit in a system designed to use external authentication?

I am using AWS cognito for user authentication in the application that I designed. And where ever there is a need for user audit in the application, I have used the id from cognito as if it is a foreign key from another table(I am using a relational DB).
Even though this works, this approach somehow feels improper. Is there any other proper way to design this?
In my application, the user logs in with his email address (common scenario). Hence, by construction the email address is a unique identifier both in cognito and in my database.
My database creates a user id for each new user, and that is the main identifier I use in my app (note that this identifier has nothing to do with cognito).
Cognito also assigns an id to each user (which it calls "username"), but I never reference that id (nor have I ever felt the need to reference it). I have been in production for several years, and I have never regretted this decision.
Upside of not linking user ids:
full flexibility (e.g. I can decide that I want to create a new user Object in my database for a particular cognito user. I can keep the previous user e.g. as a backup, even though it is not linked to the cognito user).
less work: i don't need to make sure the ids in my system are in line with those in cognito.
Downside of not linking user ids:
maybe it's faster to query cognito using the username field than the email field? maybe that could be an advantage for some use cases?

MongoDB: How to handle two users uploading the same username or password at the same time

This situation might not happen much, but I would rather be safe than sorry. I'm currently trying to make a sign in/sign up system with flutter MongoDB using API call to my database. On the signup screen, I am making checks to see if the data placed into the password and username text fields already exists within the database. In other words, if an account with those credentials already exists then I ask the user to try again, but if there isn't one then I allow for the user to go to the EULA and submit page.
The problem here is that I feel like that two or more users can do the same check at the same time, and will get the same result because, while their information might match, there isn't an instance of an account with those credentials uploaded to the database for the system to tell them to stop before they go to the submit page. And if they submit the data they wrote on their phones to the database at the same time, a situation is made where we have multiple instances of the same kind of account existing in the database.
I know that keys exist and can help in making each account unique from each other, but, in this situation, I am not sure on how to handle or prevent the concurrent uploading of similar or identical data from local devices to the same server. Are calls to my server and MongoDB asynchornous? Is this something that I need to worry about at all?
TL;DR: If you use a unique index on the username field, then it will raise an error on attempting to create a duplicate, and you can forward this to the user's sign up page and let them change their name.
The long answer:
This is more of a UX problem than a DB problem.
If I understand correctly, the user enters a username & password, then reads the EULA before the account is created.
I would disagree with this - you should make the account once they submit their name, and update it with a Boolean for eulaAccepted so that if this process fails (eg. bad connection) they can come back and accept it later.
You should do two sets of unique username validation:
When they type in the name, you can check for them and let them know the name is available. This still means someone else could take it before they hit save.
Once they hit save. Put a unique index on the username field. Then if a user tries saving a duplicate (even if submitted simultaneously, they will be processed sequentially) then it will raise an error. You can forward this onto the user, prompting them to try a different name.
Answering your other questions:
Are calls to my server and MongoDB asynchronous?
Yes, as they go over the network they are naturally asynchronous. But the saves inside the Database itself are sequential and atomic. MongoDB is ACID compliant. have a read through what it means, and what changed in version 4
Is this something that I need to worry about at all?
Yes, it's good to keep an eye on this sort problems. If you don't consider it now, you will have a nasty bug on your hand later.

In app purchases Auto renewable

your server must track purchases and allow user to restore purchased subscriptions to all iOS devices owned by a single user
I also need to track purchases and allow user to restore purchased subscriptions to all iOS devices owned by a single user. However, I am not aware of any mechanism that will allow me to identify all iOS devices owned by a single user from the app. I am not even aware of any mechanism for identifying the AppleID used by the user from the app. So how am I supposed to do this?
If you are using auto-renewable subscription you can just use the restore feature of store kit. If you're using non-renewable you must allow users to share their subscription across their devices. There are several ways to accomplish this. If you own a server, you can generate a key with a purchase. Associate a number with this key that indicates how many times a user has restored to another device (say, 5). When a user then enters this key on another device, you decrease this number. You would thus have to add a "Share" button in your app that would give the user this key. And you would need an "Unlock" button where the user can enter this code. If you are interested I could also find a method for you that doesn't require a server (but this is less secure).
Hope this helps.
EDIT:
sorry, just noticed you're talking about auto renewable:
http://developer.apple.com/library/ios/#documentation/StoreKit/Reference/SKPaymentQueue_Class/Reference/Reference.html
restoreCompletedTransactions is what you're after

Evernote users in the application database

What's the best practice or the common way of keeping (or not keeping) Evernote users in your application's database?
Should I create my own membership system and create a connection to Evernote accounts?
Should I store Evernote user data (or only part of it) in my own app and let the user log in only with Evernote?
Summary: you must protect their data but how you protect it is up to you. Use the integer edam_userId to identify data.
I think the API License agreement covers protection in the terms:
you agree that when using the API you will not, directly or indirectly, take or enable another to take any of the following actions:...
1.8.4 circumvent or modify any Keys or other security mechanism employed by Evernote or the API;
If you cache people's data and your server-based app lacks security to prevent people looking at other's data, then I think you're pretty clearly violating that clause. I think it's quite elegantly written!
Couple that with the responsibility clause 1.2
You are fully responsible for all activities that occur using your Keys, regardless of whether such activities are undertaken by you or a third party.
So if you don't protect someone's cached data and another user is able to get at it, you're explicitly liable.
Having cleared up the question of your obligations to (as you'd expect) protect people's data, the question is how do you store it?
Clause 4.3 covers identifiers pretty directly although it's a bit out of date now that we are all forced to use oAuth - there are no passwords ever entered into anything other a web view. However, mobile or desktop client apps must provide a mechanism for the user to log out, which must completely remove the username and password from your application and its persistent storage.
For a web app, you can't even save the username: If your Application runs as an Internet service on a multi-user server, you must not ask for, view, store or cache the sign-in name or password of Evernote user accounts.
The good news is that you can rely on the edam_userId value which comes back to you in the oAuth token credentials response, as discussed here.
When you look at the Data Model, you can see the unique id under the User and going into the User struct, see the reassuring definition The unique numeric identifier for the account, which will not change for the lifetime of the account.
Thinking about the consequences, as you can't get the user id until you have logged into the service, if you want to provide a local login for people you will have to link your local credentials to the user id. That may irk some people if they have to enter a username twice but can't be helped.
You can allow users to log-in via OAuth. Here's a guide on how that process works.
But you'll probably also want to store a minimal amount of user data, at least a unique identifier, in your database so you can do things like create relationships between the user and their notebooks and tags. Refer to the Evernote data model for those relationships. If you're using rails, this will also help you take advantage of rails conventions.

Destructible Passwords in a Silverlight E-Commerce Application

I have a business requirement that calls for an end user to be able to login to an e-commerce system with a one-time use password, purchase a course, and then never be able to login again. At the moment the company that is allowing their employees, my client's students, is going to generate that password for them and send me a list of the passwords they are generating.
I do not like the concept but I have yet to come up with a better one that will work for all parties. If something happens mid-purchase they have to go back to the company to get new login credentials.
The ability to purchase a course cannot be open to the public, it has to be through the e-commerce portal, and for the moment there is only one company participating but there will be more in the future. I am seeing this as a total maintenance nightmare.
My question is has anyone run across this before, if you wouldn't mind sharing tell me how you solved it, or point me in a direction that will give me some insight. I have googled the concept to death and have not come up with any bright ideas.
You can't resolve the "problem during purchase" issue yourself - They need to modify their service so that the password is destroyed when the transaction completes.
No matter what you do with regards to the password, once the user is logged in, the password is disabled on their servers. After that, you have no control.
They should either:
Cancel password on transaction completion
Provide you with an API/Web service to allow you to request a new key.
I have the answer for this one and document it here for my own personal OCD completion purposes. I created a login form that allows for a two part key; username is based on company name plus internal company ID(not a guid), paired with a password that is cryptic key, ex: #SCD6-, plus employee id generated by the company. The rub is I don't know what the employee ID is, and only use it because it should be unique although it doesn't matter if it is not, once the user logs in once completes the only marginally secure process then checks out the login is invalid and can never be used again, unless manually unlocked (in case of a duplicate employeeID at some time in the future, which is unlikely). The username and key is emailed to the employees of the target company, which is generated by the target company.If I do have the employeeID in the system which is 50/50 then I can pre-fill the forms out.
The only thing this lock protects is a process and not secure information so I am not too worried about security and it's only real purpose is to keep John Q, from stumbling onto the process and paying money that my client would need to refund later. If it were a secure data process I would not use this method.

Resources