Posted by: Eric Hansen
Again an easy but essential requirement for our two-factor system. This will be another Flask web route and mostly database driven. Lets look at the flow of how things will transpire first for this project:
SMS: POST number to /sms -> URI generates token and sends to number via SMS -> User enters their number and token to website and submits -> Site POSTs number and token to /auth/#/token -> HTTP 200 for authenticated, 403 for failure
Voice: POST number to /who -> URI generates token and sends to number via call -> User enters their number and token to website and submits -> Site POSTs number and token to /auth/#/token -> HTTP 200 for authenticated, 403 for failure
The only difference between the two is how the user receives their token. We’ll use that to our advantage. Here is the auth URI:
@app.route("/auth//", methods=['GET','POST']) def auth(number, token): valid = False up = phone.select(phone.id).where(phone.digits==number).get() records = SelectQuery(tokens).where((tokens.token==token) & (tokens.phone==up.id)).count() if records: valid = True if valid: tokens.update(token="").where(tokens.phone==up.id).execute() return make_response("", 200) return make_response("", 403)
If you think its pretty simple that’s because it is. We get the phone ID by looking up the numbers and then check to see if there’s a token ready for the phone number (phone ID has to match as well as token). If the authentication is valid we set the token to “” so no one can use it again for that number (this is one reason why the generate_token method is flawed…its too easy to figure out), and return HTTP/200 (OK) to the user. Otherwise, we return HTTP/403 (Forbidden).
We can definitely make this more intricate, however, and I’ll showcase some of that next time. But this is a good start for anyone wanting to make their own two-factor authentication system.