1

With the purpose of learning about endpoints I'm building an app called "Where Are You?". The app lets users request the location of other users. The idea is that it does so by letting the user select a contact, lookup the contact by phone number in my endpoint. If found it means that the contact have the app and GCM is sent requesting the location. If the contact isn't found a SMS is sent with an url which will request the location through a browser, perform a http post of said location and have the server GCM it back to the person requesting the location.

I need to authenticate users of the app and store phone numbers of several contacts as well as users of the app. As of now I'll mainly focus on the server side of things.

How can I archive the above in a safe manner?

So far I'm enabling OAuth 2.0 for my API and passing the user_required=True as argument to my Model.method decorator. Resulting in the following code:

from google.appengine.ext import endpoints
from google.appengine.ext import ndb
from protorpc import remote
from endpoints_proto_datastore.ndb import EndpointsModel

class User(EndpointsModel):
    owner = ndb.UserProperty()
    phone_number = ndb.StringProperty()
    reg_id = ndb.StringProperty()
    created = ndb.DateTimeProperty(auto_now_add=True)

@endpoints.api(name='whereareyoudroid', version='v1', 
               description='Where Are You Users')
class UserApi(remote.Service):
    @User.method(user_required=True,
                 response_fields=('id',),
                 path='user')
    def insert(self, user):
        user.owner = endpoints.get_current_user()
        user.put()
        return user

    @User.method(user_required=True,
                 request_fields=('id',),
                 path='user/{id}',
                 http_method='GET')
    def get(self, user):
        if not user.from_datastore:
            raise endpoints.NotFoundException('User not found.')
        return user

But the above code only requires a valid gmail account. I'm thinking something where you only can access a user if you already have the phone number? Which would be the case if I limit the response fields on the get method to exclude the phone number... unless someone decides to brute force the service. Suggestions? Comments?

From this I gather that I can configure my endpoint to only accept requests from my apps. Is that right? And if so, couldn't someone extract the need information from the apk or modify it to perform... evil? :)

Update:

  1. A makes a request for B's location

    Querys endpoint by phone number if not found simply send a request per SMS if found... go to 2.

  2. Request is forwarded to GAE app

    This is done by inserting a Location endpoint whoes id is a UUID and sends a GCM to B about the request

  3. GAE app verifies that A's secret ID is on B's whitelist

    There is no whitelist and the secret id is the UUID so this step is eliminated

  4. The app then queries for B's location

    If B decides to grant access to it's location B simply updates the Location endpoint based on the UUID

  5. Once the app retrieves this information, it then verifies that it is only sending this information to the user identified by A's secret ID

    When B updates it's location GAE sends a GCM to A informing about the update

  6. The info is then sent securely to A's client

    Done! GCM and SMS (and HTTPS) can be considered secure... right?

    Update: GCM isn't secure... but does it really matter that much?

bossylobster
  • 9,993
  • 1
  • 42
  • 61
user672009
  • 4,379
  • 8
  • 44
  • 77
  • 1
    From your description, it does not sound like there is any kind of access control, i.e. if I know someone's name and look up their phone number, I can query where they are as long as I have an account with you (whether they like me doing that or not). If that's the case, I wouldn't worry much about OAuth's security, it is good enough (because the security problem is elsewhere). If you only forgot to mention that detail, my apologies. In that case, I would personally authenticate users with public key cryptography, since it's the safest possible way (...) – Damon Mar 20 '13 at 15:29
  • 1
    (...) although OAuth is "good enough" for millions of people, but I personally do not like the idea of giving away security to some unknown other party (which is basically what you do). Hashed passwords are more and more troublesome, and things like bcrypt are not really all that effective (compared to the cost). Generating a public key from a secret key (hashed password, if you will) is reasonably efficient (think curve25519) and only needs to be done rarely. The public key stored in your database is worthless even if leaked/stolen, and unlike a hash not trivially brute-forced. – Damon Mar 20 '13 at 15:33
  • There will be no passwords as I intent to auth with google... at least thats what I think I will. – user672009 Mar 20 '13 at 20:05
  • Requesting of locations will be done by sending a GCM or SMS to the contact in question which will be presented with the chooice of granting or denying. In futura versions it should be possible to white list people. So my mom or doughter or someone alike wont have to grant each time I want to pick them up... or a senario like that. But the idea is that you get a message saying, "someone wants to know where you are, do you allow?". So it will be granted or denied for each request. – user672009 Mar 20 '13 at 20:09
  • 1
    It is highly unlikely that someone will be able to modify a GCM so it says "mom wants to know where you are" when it should say "stalker wants to know". Breaking a https connection (assuming a valid certificate) is highly unlikely too (otherwise you could not do online banking). Insofar, one could say the system is more or less as secure as Google accounts are. Which I guess should be "good enough" for most people who trust Google blindly anyway and use Google to authenticate everywhere on the web, too. – Damon Mar 21 '13 at 12:31

1 Answers1

3

You are wanting to acquire a rather sensitive combination of information - user email (as identity), phone number, and location.

So firstly, you'll have to be very considerate about privacy issues for users, having a policy on how this information is stored and distributed and make it clear to users what they are allowing. I would suggest not storing any aggregate of this type of dataset in the client, in as much as possible.

For this purpose I would recommend using GAE storage as much as possible.

Your app querying a user's location shouldn't be too worrying, provided things are done over secure channels kept well.

What is worrysome is that that information only reaches an allowed source. i.e that only a mutual contact can request this information.

I'd suggest that for each user, a whitelist of allowed contacts would be best. For each user, have a secret random uuid associated (that never goes out to any client) on GAE. A user registering for your service would create this ID. The whitelist would then consist of a list of secret IDs.

A process could then be-

  1. A makes request for B's location
  2. request is forwarded to GAE app.
  3. GAE app verifies that A's secret ID is on B's whitelist
  4. The app then queries for B's location
  5. Once the app retrieves this information, it then verifies that it is only sending this information to the user identified by A's secret ID
  6. The info is then sent securely to A's client
Ivo
  • 5,378
  • 2
  • 18
  • 18
  • Your process is pretty close to what I actually had in mind. You made me realize that the ID's need to be non-sequential and not guessable. I've updated my question based on your answer. – user672009 Mar 20 '13 at 22:18