2

I'm currently writing a web service that will be consumed by an android app.

To access user specific content, one must authenticate against the service.

Since I'm not (primarily) using a webbrowser to make calls to my API, a solely session based authentication is not an option.

I don't want to pass the users credentials on every call either, so I decided to use a JWT[1] based authentication.

Edit: A few more details

The webservice is running on node.js.

The following modules play a key part in context to the question : express is used for the endpoints, passport for authentication, jwt-simple to generate tokens. Not directly relevant for the question but involved in the process is bcrypt-nodejs for encryption and sequelize to query the database, for which postgresql is used.


So far, the process looks the following - using example endpoints

  1. A first call is made to /api/auth/login/, passing along the username and the password of the authenticating user.
  2. The api returns the users information stored in the database, along with a token. e.g. {success: true, user: {id: 42, token: aaa.bbb.ccc}}
  3. Any subsequent request passes said token as a query parameter to authenticate the same user.

The question that rises now is: How do I correlate the token to a user and verify its validity.

The options I see are the following.

  1. Since the token carries a payload, it's actually enough to put the users id into it and assume that if the token properly decodes it's valid and the API call will be made with privileges of the user whose id is contained in the payload.

    • Since the token is encoded using a secret only known to the server, it shouldn't be possible to fake a token, unless someone gets its hands on the secret.
    • other claims as exp or iat can be included as well.
  2. Upon generation of the token, it will be added to a tokens table which contains the token and its corresponding user id (id | user_id | token). When a request is made, the database will be queried for existence of the token and only if an entry exists, its user_id will be used.


Long story short, my question breaks down into these:

  1. Is it necessary/sound to add the token to a database or can I just use the payload to identify the user?

  2. Does it make any sense to change the servers secret - used to encode the token - about every week, hence invalidating any token generated previously?

    • Using this approach an additional query against the database has to be made on every single request.

[1] - http://jwt.io/

    2 Answers 2

    1

    Your token should contain the users id and a hash. If the hash matches the JWT, you're fine (as long as nobody knows the private key your are using to create that hash).

    5
    • 1
      Why the need for a hash when using a json web token? It's already signed.
      – Cerad
      CommentedAug 28, 2015 at 17:13
    • @Cerad Thanks for the question, i tried to wrap my head around the purpose of that and what to hash.
      – C5H8NNaO4
      CommentedAug 28, 2015 at 17:35
    • The signature portion of a jwt is a hash. No point in adding another.
      – Cerad
      CommentedAug 28, 2015 at 18:03
    • @Cerad Thanks. Yes, as far as i understood, the signature is built by using the secret to hash header.payload. I think i got a bit confused by the part that says "If the hash matches the JWT"
      – C5H8NNaO4
      CommentedAug 28, 2015 at 21:47
    • the SSH analog is pub/private key. Your public key can go into e-mails, etc, no problem. provided that no one else knows your private key. (or that the NSA has broken SSH.)
      – Thufir
      CommentedJan 17, 2017 at 13:40
    1

    Is it necessary/sound to add the token to a database or can I just use the payload to identify the user?

    I think both approaches are fine. I've implemented token based authentication in .Net, and we put all identity related information in the token. I would argue it's more scalable, especially for a web farm. All the authentication information we need is in the token itself, so we don't need to ask database for additional information. But, the size of token could potentially be very large. Another problem is it's not easy to implement logout. The token is valid until it expires, it's not easy to revoke it. See here.

    You can also put required information in the database. And the token itself only contains something like a "session id". It's now more like a traditional cookies-based authentication. However, you have to deal with some other problems like where to store session information (cache or database), use a shared session database or each machine keeps its own session data, etc.

    1
    • Hey there, thanks for your Answer! I haven't really thought about logging out, that's a good point. Could I just add a last_logged_out timestamp into my user entry and compare it to the iat claim of the token? If the age of the token is older than the last time the user logged out the token is invalid. So for the beginning adding a payload of '{"exp":1448665200000,"iat":1440797905060, "uid":42} could be just enough.
      – C5H8NNaO4
      CommentedAug 28, 2015 at 21:40

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.