127

I am still trying to find the best security solution for protecting REST API, because the amount of mobile applications and API is increasing every day.

I have tried different ways of authentication, but still has some misunderstandings, so I need advice of someone more experienced.

Let me tell, how I understand all this stuff. If I understand something incorrectly, please let me know.

As far as REST API is stateless as well as WEB in general, we need to send some auth data in each request(cookies, token....). I know three widely used mechanisms to authenticate user

  1. Token with HTTPS. I have used this approach a lot of times it is good enough with HTTPS. If user provides correct password and login, he will receive token in response, and will use it for the further requests. Token is generated by the server and stored, for instance in the table separate or the same where user info is stored. So for each request server checks if user has token and it is the same as in the database. Everything is pretty straightforward.

  2. JWT Token. This token is self-descriptive, it contains all necessary information about the token itself, user cannot change for example expiration date or any other claim, because this token is generated (signed) by the server with secret keyword. This is also clear. But one big problem, personally for me, how to invalidate token.

  3. OAuth 2. I don't understand why this approach should be used when communication is established directly between server and client. As far as I understand, OAuth server is used to issue token with restricted scope to allow other applications access user information without storing password and login. This is great solution for the social networks, when user wants to sign up on some page, server can request permissions to get user info, for instance from twitter or facebook, and fill registration fields with user data and so on.

Consider mobile client for online store.

First question should I prefer JWT over first type token ? As far as I need login/logout user on mobile client, I need to store somewhere token or in case of JWT, token should be invalidated on logout. Different approaches are used to invalidate token one of the is to create invalid token list (black list). Hmm. Table/file will have much bigger size than if token was stored in table and associated with user, and just removed on logout.

So what are benefits of JWT token ?

Second question about OAuth , should I use it in case of direct communication with my server? What is the purpose of one more layer between client and server only to issue token, but communication will be not with oauth server but with the main server. As I understand OAuth server is responsible only for giving third-party apps permissions (tokens) to access user private information. But my mobile client application is not third-party.

1
  • Thanks, I was wondering this recently. I went with session management (Beaker), and delete session tokens after an hour. Oauth didn't seem the right fit. Commented Dec 8, 2016 at 6:11

4 Answers 4

102

Consider the first case. Each client gets a random ID that lasts for the duration of the session - which could be several days if you like. Then you store the information relevant to that session somewhere server side. It could be in a file or a database. Let's suppose you pass the ID via a cookie but you could use the URL or an HTTP header.

Session IDs/ Cookies

Pros:

  • Easy to code both the client and server.
  • Easy to destroy a session when someone logs out.

Cons:

  • The server side periodically needs to delete expired sessions where the client didn't logout.
  • Every HTTP request requires a lookup to the data store.
  • Storage requirements grow as more users have active sessions.
  • If there are multiple front end HTTP servers the stored session data needs to be accessible by all of them. This could be a bit more work than storing it on one server. The bigger issues are the data store becomes a single point of failure and it can become a bottleneck.

JSON Web Tokens (JWT)

In the second case the data is stored in a JWT that is passed around instead of on the server.

Pros:

  • The server side storage issues are gone.
  • The client side code is easy.

Cons:

  • The JWT size could be larger than a session ID. It could affect network performance since it is included with each HTTP request.
  • The data stored in the JWT is readable by the client. This may be an issue.
  • The server side needs code to generate, validate, and read JWTs. It's not hard but there is a bit of a learning curve and security depends on it.

    Anyone who gets a copy of the signing key can create JWTs. You might not know when this happens.

    There was (is?) a bug in some libraries that accepted any JWT signed with the "none" algorithm so anyone could create JWTs that the server would trust.

  • In order to revoke a JWT before it expires you need to use a revocation list. This gets you back to the server side storage issues you were trying to avoid.

OAuth

Often OAuth is used for authentication (i.e. identity) but it can be used to share other data like a list of content the user has purchased and is entitled to download. It can also be used to grant access to write to data stored by the third party. You might use OAuth to authenticate users and then use server side storage or JWT for the session data.

Pros:

  • No code for users to signup or reset their password.
  • No code to send an email with a validation link and then validate the address.
  • Users do not need to learn/write-down another username and password.

Cons:

  • You depend on the third party in order for your users to use your service. If their service goes down or they discontinue it then you need to figure something else out. Eg: how do you migrate the user's account data if their identity changes from "[email protected]" to "[email protected]"?
  • Usually you have to write code for each provider. eg Google, Facebook, Twitter.
  • You or your users might have privacy concerns. The providers know which of their users use your service.
  • You are trusting the provider. It is possible for a provider to issue tokens that are valid for one user to someone else. This could be for lawful purposes or not.

Miscellaneous

  • Both session IDs and JWTs can be copied and used by multiple users. You can store the client IP address in a JWT and validate it but that prevents clients from roaming from say Wi-Fi to cellular.
4
  • To add to your answer, oAuth may not be useful when user wants to signup using their company accounts which are not usually associated or linked with any of the social networking websites or google. Commented Oct 11, 2016 at 5:06
  • 8
    I don't know why this is the accepted answer? it doesn't answer the real question, just reforming the question in other way
    – amd
    Commented Jan 15, 2017 at 11:31
  • 2
    You say: "The data stored in the JWT is readable by the client. This may be an issue.. Why not use JWE if that is an issue?
    – Silver
    Commented Jan 31, 2017 at 10:25
  • 1
    This answer confuses apples & oranges. You should not compare these with OAuth 2.0 (the "authorization" spec). What OP needs to know about is: "Resource Owner Password Flow" — which is authentication as a grant. Commented Dec 24, 2017 at 22:42
6

Ask yourself why you need to invalidate the original token.

A user logs in, a token is generated and off the app goes.

The user presses logout, a new token is generated and replaces the original token. Once again, all is well.

You seem to be worrying about the case where both tokens hang around. What if the user logs out and then somehow makes a request using the logged in token. How realistic is this scenario? Is it just a problem during logout or are there many possible scenarios where multiple tokens can be a problem?

I myself don't think it's worth worrying about. If someone is intercepting and decoding your encrypted https data then you have much bigger problems.

You can give yourself some additional protection by putting an expiration time on the original token. So if does end up being stolen or something then it would only be good for a short period of time.

Otherwise, I think you would need to have state information on the server. Don't blacklist tokens but instead whitelist the current token's signature.

4
  • 2
    If you assume that some of your clients are malicious, then it is easy to see that a session will be copied and reused, and you need to counter this on the server. Commented Oct 5, 2015 at 16:23
  • 1
    Bad idea, this can be used later by hacker, or just brute forced ...
    – CROSP
    Commented Oct 5, 2015 at 17:41
  • 2
    Imagine a user wants to logout out from all other devices, using JWT isn't possible.
    – amd
    Commented Jan 15, 2017 at 11:34
  • @amd not possible? What if I add nonce=(random) and if user logs out, replace the nonce. Seems simple and effective.
    – Simon B.
    Commented Nov 9, 2017 at 19:11
3

You can handle the JWT issues you mentioned by storing a salt value along with the user and using the salt as part of the token for the user. Then when you need to invalidate the token, just change the salt.

I know it's been a couple of years but I would actually do this differently now. I think I would ensure that access tokens had a relatively short-lived lifetime, say an hour. I'd also be sure to use refresh tokens that were stateful on the server and then when I wanted to end someone's session, I would revoke the refresh token by removing it from the server. Then after an hour, the user would be logged out and would have to log in again to regain access.

7
  • 5
    But again it becomes state-full in this case, so what is the reason to create salt or use any other approach, you can simple store token in the table and delete when it should be invalidated
    – CROSP
    Commented Oct 5, 2015 at 4:39
  • 2
    You can also invalidate based on time. Commented Oct 5, 2015 at 5:09
  • What is the difference between expiration time in this case ? How can I invalidate token based on time when user wants to logout from mobile client ? It seems there no way API to be stateless in this case. What is the most suitable and secure solution than ?
    – CROSP
    Commented Oct 5, 2015 at 7:42
  • 2
    The most suitable for logout from a single device is to ensure that you use a clientId in addition to the salt. I suggest you look at the Oauth-jwt bearer token spec for insight. Commented Oct 5, 2015 at 15:37
  • Thanks for answer, but I don't understand why should I use OAuth in this case at all.
    – CROSP
    Commented Oct 5, 2015 at 17:28
0
  1. Oath is NOT an authentication protocol but an authorization standard or protocol. So if you use the add to Google calendar function for example, that's oath. The app will list Google's API for the elements or the URL links to the various hooks it's looking for to pass over information. If you want authorization, than you want OIDC or openID connect.

  2. For your use case I would recommend a lil of all of the above. If you use OIDC, the user credentials would authenticate via HTTPS to an authentication server. Inside the request would be the user's username, and password plus the app's unique randomly generated (client) ID. If the credentials are valid and the client ID is valid the server responds back with a one time password. The user app then takes that password and passes it to the web service. The web service passes the password back to the authentication server to validate that the password is legit. If it is, the authentication server will respond back to the web service with an authorization/access token (AK). Now you can take one of two approaches:

    2.1 You can store that token in your client app as an access token. Then have the web service respond back with a refresh token. The authorization token could have a life of a few hours or days and the refresh token would have a shorter time life. You should use a JWT for the refresh token but you can use a smaller randomly generated string as refresh token. This way you don't necessarily have to pass the AK with every request. If say 5 mins goes by and the server doesn't get a refresh token from the user it then disconnects the user and invalidates all tokens (AK & refresh). Only down side here is if the AK is compromised you risk the user season being hijacked.

    2.2 (most recommended) the access token and authorization together are usually the same but can technically be two different tokens. This is great if the user authenticated already and you're using his or her fingerprint or face ID thru the phones OS hardware API. If the phone says yes this is him or her, you simply send the client ID to access a key store/repo thru a credential-less API gateway. The gateway would respond with your authentication token you generated earlier. The app can then sent that token to the web service and web service would respond back with an access token and refresh token. You can then discard the auth token and keep the access and refresh token.

    The idea here is after the user authenticate the first time and the auth token is generated, it could have a life span of 3 months. Now you don't want to keep that on your client phone because if it's compromised the user is screwed. Hence why you'd keep it in a keystore not on the phone. Now the access token the web service responds with can have a life span of an hour and the refresh token would have a life span of 5 mins. As long as the refresh token is in play the session stays alive. When you stop receiving that refresh token you invalidate the refresh and access token, kill the session and you still get to preserve the auth token. Your authorization then should be a JWT with ES-256 algorithm. Your access token should or could use RS-256 and your refresh token could use HS-256. Do not RS & ES use asymmetrical encryption meaning you need a public key and private key to generate it. While HS uses symmetrical encryption which means only one password or key is used to generate it.

2
  • 1
    Hi. "Oath is NOT an authentication protocol but an authorization standard or protocol." Can you clarify what you mean to be the difference between an "autentification protocol" vs an "authentification standard or protocol"? Commented Nov 3, 2019 at 14:21
  • Authentication is about determining which user it is. Authorization is about what access that user is allowed.
    – Chad Clark
    Commented Apr 17, 2021 at 19:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.