1
\$\begingroup\$

I have an asp.net/MVC5 app that for reasons that are outside of my control needs to hang onto (some) user credentials (username and password) to facilitate certain operations they may perform. I don't like it - but with that as a given, I would like some QC on the approach I'm thinking of taking to keep their credentials relatively secure.

When the application initializes - create a AES 256 key using RNGCryptoServiceProvider and partial IV - this is retained in a static class.

private const int AesBlockSize = 128;                  // block size in bits
private const int AesKeySize = 256;                    // key size in bits

// ...

var rngCrypto = new RNGCryptoServiceProvider();
_encryptionKey = new byte[AesKeySize/8];
rngCrypto.GetBytes(_encryptionKey);                    // generate key
_encryptionIV = new byte[AesBlockSize/8];
rngCrypto.GetBytes(_encryptionIV);                     // generate partial IV

When a user authenticates, if their username and password passes validation, serialize them into a JSON string and encrypt it with the AES 256 key using as the IV the partial IV combined with their username (lowercase).

Create a custom FormsAuthenticationTicket and store the encrypted value as user data inside the ticket.

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
            (
                ticketVersion,
                username,
                ticketIssueDateTime,
                ticketExpireDateTime,
                ticketPersist,
                encryptedCredentials
            );

            // Encrypt the ticket 
            string encTicket = FormsAuthentication.Encrypt(ticket);

            // Create the cookie
            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) {HttpOnly = true};
            HttpContext.Current.Response.SetCookie(cookie);

My understanding is that the forms authentication cookie is encrypted with machine key and then inside the user credentials are encrypted with a temporary AES 256 key that will live the lifecycle of the application.

When I need their credentials, I retrieve it from the cookie, decrypt, deserialize and use them

There is a small possibility of the app pool recycling under them invalidating their stored credentials since in the in-memory key will change - in that case I just catch the failure to decrypt, log them out and send them to log in again. (App pool recycles are scheduled so this won't be an issue at any rate.)

Thoughts? Improvements? Condemnations?

\$\endgroup\$

Your Answer

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

Browse other questions tagged or ask your own question.