Question

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?

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top