2

I have a PHP server and an Android/iOS client, and SSL is used for all communication.

The PHP server is a JSON API with 2 public functions (register, login) and many private functions (which require the user to be "logged in").

I have gone through a few iterations and this is the current method of becoming "logged in":

  1. User POSTs a login request to the server with a username and password.
  2. The server attempts to authenticate the username and password with what is stored in the database (password_hash() is used when storing the password, password_verify() is used when attempting to authenticate, input data is validated and sanitized etc).
  3. If the username and password are authenticated, the user is supplied with a JWT which will expire after 1 minute.
  4. The JWT contains: expiry time, username, and user type.

All private functions require a valid, non-expired JWT. 1 private function is available to request a new JWT. I prefer this way of maintaining the session because it provides a kind of heartbeat (the server knows within 1 minute of the client becoming inactive).

I implemented the system in this way so that the user only needs to send their username and password once, so that the server only needs to do 1 database lookup to authenticate the user at the start of their session.

My question is: is authenticating once and maintaining a session (whether I do it this way or another way) any more secure than sending the username and password with every request and authenticating each time?

  • 1
    Do you care about the DoS potential? Bcrypt with a decent cost setting takes much longer that verifying the HMAC on a JWT. – AndrolGenhald Apr 27 '18 at 15:04
  • Sure, I assumed verifying each JWT would be less costly than using password_verify() and doing a database lookup for each request, but I hadn't considered it in terms of more easily resulting in a DoS outcome (whether as an attack or due to an extreme increase in legitimate user requests), so this is a good point – user176830 Apr 27 '18 at 17:00
  • the token is a shortcut to established credentials, like how a stamp at a bar w/cover prevents you needing to dig out a receipt if you step outside. It's MUCH quicker for bouncers to glance at your hand than read receipt details in a noisy dark bar; same for tokens and webservers. – dandavis Apr 28 '18 at 9:11
3

If you have HTTPS in place all the time, you don't have to worry about the password leaking during the interactions between the user and the API endpoint. HTTPS will protect it during transit on the login, as it will protect the password on every request.

You are not more secure or less secure by sending login information on every request, but you are creating a unnecessary load on the application server. A lot of load.

Passwords are made to be hard to crack. The hashing algorithm expects someone to try to crack the passwords offline, so they employ multiple passes to slow down the hashing process. If the application have to hash every password for every user on every interaction, you are giving your application server a hard job to do.

So, stick with the tokens. Not from a security standpoint, but from the performance standpoint. Tokens are for that, to ensure the user is authenticated, costing a file read or database lookup.

4

If you prompt the user to newly enter a Username and Password every single time the application needs to make an API call, they're gonna have a bad time and stop using it. Especially if a situation arises where a single "action" from their perspective kicks off multiple API calls that would need authentication separately. That's just not workable. That isn't the only way that "

The alternative is having the user's Username and Password stored on their device so the application doesn't need to prompt in order to send the request. The user can't tell the difference between the application holding an arbitrary token that enables access compared to username + password that enables access, so that's good. Unfortunately, there are some flaws in that as well, and those flaws are more security-relevant.

First, unless your application does internal encryption the username and password end up effectively stored right next to each other in plaintext. Even if there is encryption, the encryption key pretty much has to be stored close to what it's encrypting which isn't really much better. I can't say with precision how much of a vulnerability this is, and a token is likely to be just as vulnerable, but an attacker getting hold of a single token is likely less damaging than one getting the full username + password.

Second is, as you are aware, tokens are expected to expire with relatively high frequency compared to usernames and passwords. From the way your question is worded, you seem to be considering username + password in every request as the "highest level" of tokens expiring quickly, but it's actually the opposite: with no token in between, username and password become the token and only expire when changed. That makes the application somewhat more vulnerable to replay attacks, and makes it much more inconvenient to the user if you ever implement controls to detect malicious behavior: with a token, you can expire the token immediately but a real user can provide username and password to get a new one while an attacker who obtained just the token is blocked. A user entering their credentials every now and then is pretty minor, but forcing random password resets is significantly more burdensome on and it leans a lot on a secure password reset function.

Last, the username and password would be transmitted a lot more frequently. Ideally the secure connection is perfect and that's not a problem, but in practice there are some vulnerabilities that are more likely to be exploitable. For example, the CRIME vulnerability exploited the size of messages sent to leak pieces of information but required a constant value exist across many messages. That exact vulnerability is probably patched, but similar ones could exist in the future and if your requests are a little leaky then always having the username and password in them lets an attack piece-together that information over a long time, compared to a token which is less impactful to leak as well as limiting the time that an attacker has to obtain it.

All of that might not add up to a large security compromise, but I wouldn't risk it.

0

Firtsly, if an username and a password are sent in every request then they could be exposed in every request, well if you have a secure channel (HTTPS), you can mitigate it, but you could open the possibility to an dictionary attack or brute force attack to be successful, because an attacker could have many pages of your web application to test a valid combination of username and password, you could limit the number of login attempts by request, but an attacker could change the request when he/she was blocked. Now, you should consider that an application must have a balance between performance and security, if your application ask for an username and password every request then its performance is affected and users could decide not use your application anymore for that reason. In my oppinion, it's better to have a management session than multiple authentication requests.

I hope this information helps you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy