1

The web app I'm developing makes use of the concepts of "access token" and "refresh token", even though it uses its own auth scheme.

In certain situations, the web app needs to get an "impersonation token" from the OS it's running under, with the credentials of the user, when the user logs in.

This is fine, if the refresh token is used while the session is running, as in that case the server keeps the impersonation token alive, but poses the question of how to implement the case of a "cold start" of the application without asking the user to relogin: in that case the credentials must necessarily be provided automatically to the server, for the impersonation to work without the user explicitly logging in, and the question arises about where and how to store them.

The credentials would have to be encrypted, of course, with a key that is not stored alongside them.

So, let me guide you through my thought process.

Scenario 1: the refresh token might itself contain the credentials, encrypted with authenticated encryption

If refresh token is encrypted with a key on the server, in theory I could store the credentials in the refresh token itself. However, it feels very risky: in case the key were to be exfiltrated from the server, any refresh tokens in the open could be decrypted and credentials stolen.

It feels like a no go.

Scenario 2: the refresh token, itself encrypted with authenticated encryption, might contain a key that was used to encrypt the credentials.

Say the refresh token contained a token id and an encryption key. This key is used to encrypt the user's credentials with authenticated encryption. The whole token is then encrypted with a separate key on the server, with authenticated encryption.

When the server is presented with the refresh token, it first decrypts it, then it extracts from it the token id and the user's credentials encryption key. Then it looks for this token id in the database and tries to decrypt the corresponding user's credentials.

This scenario feels more secure, since an exfiltration of the server's key is not enough anymore to decrypt the users' credentials, one would need to have access to the whole server's database to do that, and to the refresh token.

Yet, I'm not an expert in this field and I'm wondering if any of that makes sense.

The question for you is: does it?

I still have the option to ask the users whose impersonation token is necessary to relogin any time they reopen the app, yet I'd avoid that if possible.

10
  • What are the credentials? The user password? An API token? And what does the server need them for? An external service? The web application itself?
    – Ja1024
    Commented Jun 4 at 11:46
  • They are username and password, and the server needs them for impersonation. No way around it.
    – Fabio A.
    Commented Jun 4 at 11:49
  • Impersonation towards what? If you just have to authenticate as the user in your own application or an external service under your control, there's no (good) reason to do that with the user password.
    – Ja1024
    Commented Jun 4 at 11:55
  • Impersonation towards the operating system, specifically on Windows, which doesn't allow impersonation of as user without their password.
    – Fabio A.
    Commented Jun 4 at 11:59
  • This would be handled via NTLM or Kerberos Authentication. You can't impersonate without it. That's a "negotiate" in the browser with SPNEGO: en.wikipedia.org/wiki/SPNEGO Commented Jun 4 at 19:43

1 Answer 1

1

The difference between both options is not as big as it may seem.

If an attacker has managed to obtain the token encryption key from the server (which should be one of the best-protected assets), then trying to “hide” the encrypted credentials in the database as proposed in the second option likely won't make much of a difference. Databases are usually compromised long before key stores, e.g., with SQL injection vulnerabilities.

So the truth is: Once an attacker has obtained a refresh token from the client and compromised the server, all protection is gone. I think it's important to understand this and take great care protecting the server key. Ideally, use a hardware-based key store where the key cannot be extracted (like a hardware security module or, if the budget is limited, a TPM chip). Otherwise, use the key store of your operating system like the Kernel Key Retention Service in the case of Linux.

Nevertheless, the second option is preferable, because it allows you to delete the encrypted credentials after a while. If you hand them over to the client, nobody knows when they will be removed – if ever. The client may also not understand that the token actually contains their encrypted (permanent) credentials and is not just a temporary credential. This can make them treat the token with less care than they should.

So given the choice between both options, use the second one. Additionally, implement both an expiration and a revocation mechanism for the refresh token. If an attacker has managed to obtain a token, they shouldn't be able to use it forever.

In general, the approach of collecting plaintext user passwords isn't great. I'm fairly sure that there are better options and suitable standard protocols, but I'm going with your requirements here.

1
  • Thanks for the answer, it provides me with valuable info. The requirement isn't strict, and if there are better ways of doing what ultimately I need to do I can only be happy. With yours and @browsermator input I started investigating Kerberos: do you confirm it can be used to impersonate a user - in my case, to access the filesystem as-if it was said user accessing it - without having the user manually input the password each time?
    – Fabio A.
    Commented Jun 4 at 20:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .