5

So i am creating my first larger scale application (by larger scale i mean something i see myself publishing in the app store) and i am not sure of how to handle user authorization. The client will consist of a application for android and iphone, and they make HTTP requests on a server.

My data is stored in a postgreSQL server and i have already implemented so that a user can log in, but right now logging in basically means nothing. When you query the database there is no check to make sure that the data you request / wish to alter is yours.

I was thinking that when a user log in they receive a token. Whenever a request would be made upon a user ID, the host requesting this data would also have to provide that IDs token.

Queries are made with rest calls, and are usually of the form [id of user, new data 1, new data 2, new data 3], and this new data will be inserted into a table, and the new row will have a relation to the client id.

The data i store is in no way sensitive. Most requests will be a user wishing to add a row to a table in my database. The most sensitive piece of information would probably be a users email, so this authentication system would only be in place to ensure that no one is inserting troll-data on a client that is not them.

Another point i'm not sure how to handle is what to do when the token expire. I cannot request the user to log in every few hours, the token should be renewed automatically. Is it normal to store id / pass at the client and do the request automatically?

Rewbert
  • 153

2 Answers2

2

First off, the token approach seems sound for your case. One option is to encrypt user information (e.g. id) into the token. On the server side, you can then keep things stateless. Realize that no matter the details of how it is generated, this token is sensitive. If someone has it, they can use it to pretend to be that user as long as it is valid (just like a session id.)

To the last part, it's unclear what the log in requirement is here. You say you don't want them to have to log in every few hours. How often do you want them to have to log in and is that based on inactivity? I would not recommend storing the credentials as other applications on the device could potentially retrieve the credentials.

JimmyJames supports Canada
  • 30,578
  • 3
  • 59
  • 108
1

Don't really know the full use case but this really screams using a session to me. Normally these are implemented with a unique ID sent to the client in the form of a cookie and stored on the server in an in memory database like redis or memcached.

When a user logs a new object will be added to redis and stored by a unique key with any user information needed, an expire time can be set here too. Setting an expiry will automatically remove a key from the cache which will make a user's session invalid if it is past the expire date. For your case it would probably store just the user id, it could also be used to store any other commonly used static data that doesn't need to be queried every time.

Since session information is useful on most endpoints a top level filter is normally implemented to query redis for the key and store the user information on the request before any handler logic is executed. If the key does not exist a 403 status could be sent in the response.

It all depends on what server side technology you are using but this pattern is very common and could already be implemented in the framework you are using. For example I wrote up some pseudoish code in a few minutes that uses express and their redis session object. Just with a few lines of code it provides session expiry support and user data security.

    var session = require('express-session');
var RedisStore = require('connect-redis')(session);

//this is middleware provided by the library which will query `redis`
// from the request cookie, add the session to the request data and
//update the expiry with user activity.
app.use(session({
    store: new RedisStore({ttl: 10000000}),
    secret: 'keyboard cat'
}));

app.post('login', function(req, resp) {
    var sessionData = doLogin(req);
    //store the session data on the request if login is successful
    if(sessionData) {
        req.session = sessionData;
    }

    resp.send(200);
});

app.post('insert', function(req, resp) {
     var userId = req.session && req.session.userId;
     // use the session data to validate the user
     if(userId) {
        doInsert(req);
        resp.send(200);
     }
     else {
        resp.send(403);
     }
}); 

Just a side note, normally an api shouldn't take the user as a param to manipulate data for a that user because it is very prone to hacking. Storing the user information on a session and always referencing the user information will prevent any unauthorized user data manipulation.

pllee
  • 1,212
  • 1
  • 9
  • 13