0

I have a web application in which users can log in. Due to technical constraints, the application is not allowed to store any session information on the disk.

To identify requests from the same user without storing sessions to disk, I have devised the following scheme:

The application has a long, randomly generated server side secret S, created at the time of installation. There is an user with an username u and a password p.

In order to log in, the user presents (u, p) to the web application for authentication at time t. If the authentication is successful, it sends out a cookie c in the response, containing Encrypt(u || t, S). Encrypt in this case is AES-256 in CBC mode of operation.

Later, when a request containing c arrives, the application decrypts the contents of c with S to obtain u and t. Obviously, if u is not a valid user, the request is rejected. Also, the request is rejected if the difference between the current time and t is greater than x. Rejecting the request involves asking the client to delete c and redirecting the user to the login page.

If the user sends a request at time t + y, such at k <= y <= x, the application refreshes c by updating it to Encrypt(u || t + y, S). k is chosen to be some suitable value, such as x/3.

Logging out simply involves asking the browser to delete c.

Is this method of authentication secure?

8
  • 1
    You say "the application is not allowed to store any session information on the disk" then you store a cookie, so assume you are trying to avoid not storing sessions on the server. The whole system looks like it is trying to recreate existing authentication mechanisms. This has no protection against session hijacking and depending how you are encrypting the whole thing (?) it may be possible to derive the encryption key. JWT would be a better choice for this type of authentication. Oct 11, 2017 at 15:10
  • @Trickycm I don't see how this makes session hijacking any worse, and it would only be possible to derive the encryption key if the encryption algorithm were horribly broken. Oct 11, 2017 at 15:18
  • Session can be hijacked either way if the underlying connection isn't secured. Still - @Trickycm has a point i.e. why is OP rolling their own when this already exists (JWT being one example).
    – Hector
    Oct 11, 2017 at 15:19
  • What encryption method are you using 'horribly broken' means different thing to different people, i remember arguing with someone once when they tried to tell me 10 rounds of sha1 hashing was strong encryption. As for the session hijacking you have no checks for IP changes in the cookie payload (or any other additional machine/user identifiers.) Oct 11, 2017 at 15:21
  • 1
    @Trickycm Encrypt in this case is AES in CBC mode. Also, I'm not storing the cookie on the server. It is generated and sent out as part of the HTTP response.
    – user22260
    Oct 11, 2017 at 16:05

2 Answers 2

2

First off as always why are you trying to roll your own? As pointed out in the comments something like JWT performs the same job.

A brief look suggests this should work. Although i'd suggest making it more transparent. You could instead for the cookie value use -

username:[Username]&tokengeneratedat:[GenerationTime]&Sig:[Signature]

This makes development, debugging and user inspection far simpler since the underlying details are in plain-text. This approach is also more flexible seeing as you can do things like cycle keys - just use the Generation Time to identify which key to use.

I would suggest verifying the user exists in the table at the very least on token refresh / ideally every request to support instant access revoke.

0

Leaving aside the somewhat absurd and unexplained constraint, the mechanism is basically ok as long as you don't try to store too much data in the session.

But as presented it is somewhat innefficient and you are losing the scalabilty benefit of client side sessions - you have not included a mechanism to check if the decrypted username is valid. Checking the timestamp provides some protection, however, if it were me, I would include additional controls to validate that the cleartext is something which was encrypted by the service, e.g. json encoding and compressing before encryption and vice versa after decryption.

I suspect that this might be more vulnerable to cryptoanalysis - the attacker can know the cleartext as well as the ciphertext - than in a more conventional application of symmetric encryption. You would need to ask someone who knows a lot about cryptography. But this would be mitigated by appropriate use of initialization vectors and random padding inside the cleartext.

You must log in to answer this question.