0

there's an up and running self-serve customer portal built that I'm trying to make a bit better when it comes to displaying proper items for different client types and auto-logging users. Here are a few considerations:

  • Built on ASP.NET MVC (4.7.2)
  • Authentication Mode = Forms
  • Uses custom Membership Provider
  • Uses various cookies and the session to store relevant data
  • Hosted in the cloud. Load balancers and everything. Traffic is increasing, and fast.

And here are some requirements

  • The portal has a 'remember me' functionality. If the session has expired and a customer types www.sampleSite.com/sampleController/sampleAction, it should automatically log them in.
  • The portal has a log out functionality, of course.
  • There are different customer types that need to see different menu items and UI items. I need this information both on clientside and on serverside.

For better maintenance (it's not fairly decoupled as it is) and some issues with the load balancing, I'm doing some code maintenance and here's what I want to get rid of:

  • if (this.Session["CurrentUserIsTypeA"] == true) {...} else if (this.Session["CurrentUserIsTypeB"] == true) {...}
  • Queries to the database e.g. var customer = loginsService.GetByEmail(this.User.Identity.Name) and then passing data to e.g. ViewBag

So basically I need to either somehow extend the IIdentity so it includes the data I need, use a custom Profile Provider and call it as this.Profile.PropertyValues or even migrate to ASP.NET Identity following Microsoft's docs. (I am fairly familiar with the roles and claims from .NET Core projects, unlike profiles and membership).

  1. Which of these would you choose? I'd say using a custom profile provider is faster and easier, but is ASP.NET Membership still a good choice for ASP.NET MVC applications in 2019?
  2. How to implement the 'remember me' functionality with minimal risk for customers? What I'm doing right now is I'm generating a random token that I save to the database and then send as a cookie. When the session expires and the client is auto-logged via that token, it gets replaced with a new one. Security-wise, I'm worried about stealing the cookie and logging on a different computer. What would be some best-practices for protecting a cookie?
  3. What's the best practice for "Remember Me" and "Log Out"? If someone manually clicks log out, it would be fair to say they want the cookie gone, right?
  • Are you using Microsoft Identity integration? It uses a type of Attribute Based Authroization Control called Claims Based Identity. The set of roles is simply one of the claims. Querying the user or identity for the appropriate role or claim is much more highly preferred than setting session variables. You can even leverage attributes to protect actions filtering on both roles and claims. – Berin Loritsch May 8 '19 at 13:35
  • No, currently it's not using Microsoft Identity. – Daniel Tsvetkov May 9 '19 at 9:18
0

What is increasingly common these days is a single page app using a token like JSon Web Tokens (JWT). That's a very heavy lift from where you are now, so it may not be feasible at the moment. It's something to consider if your customer/company is willing to invest in some re-engineering.

The biggest issue you have right now is that your load balancing requires session affinity for your application to function as designed, or replicating sessions between your servers. Both of those have performance impacts. This will hamper your ability to scale by simply standing up more instances of your application going forward. That's even more true if you are replicating session information between servers.

  1. Which of these would you choose? Custome profile provider is faster and easier.... Is Membership still a good choice?

Identity is a bit more current, but if you have to do anything custom with it, you will run into the need to re-implement those extensions if you want to migrate to MVC Core.

Identity uses a flavor of ABAC called Claims-Based Authentication which matches more complicated scenarios. It also allows you to federate authentication to leverage 3rd party identity servers like Google, Facebook, Microsoft, and Twitter.

  1. How to implement the 'remember me' functionality with minimal risk for customers?
  2. What's the [best/common] practice for remember me?

The way that big applications like Facebook manage this is by using a pair of tokens: session and refresh.

The refresh token identifies the user in lieu of an actual authentication process. NOTE: the refresh token does have an expiration date so that if the user doesn't access your service after N hours (or days) they have to log back in.

The refresh token is used to obtain a session token. The session token has all the user's attributes for ABAC. The most common token format for this purpose is Json Web Tokens (JWT) since it can be queried client side and server side without hitting another service to verify the information again.

Session tokens have a short time to live so that if a user's roles change, they will get the new role as soon as the current token expires and they have to get a new session token.

There's other variations of this, but it does require client side and server side negotiation to manage it.

I don't think Identity manages this scenario for your application, but it does for your 3rd party login servers (i.e. Google, Facebook, etc).

  1. What's the [best/common] practice for log out?

Best would be to kill the session. If you have session tokens, remove the session token but leave the refresh token.

If you have any other means of positively identifying a user automatically like PKI or enterprise level identity management, use that in lieu of the more complicated refresh token logic.

  • I've followed your advice for two different tokens: refresh and session. As you said, I generate a JWT in the session token. As right now we don't have the manpower to re-engineer the website, I'm handling the application PostAuthenticateRequest to read the session token and swap HttpContext.User for a custom membership class that implements IPrincipal + access control attributes. Overrided the User getter in the base controller and in a newly created base page type for easier access. Looks like a step in the right direction. Thank you! – Daniel Tsvetkov May 9 '19 at 9:32
  • @DanielTsvetkov, no problem. The more you can get out of the session variables, and into your JWT, the fewer resources needed to stand up new instances of your site. Very few teams have a team/budget for a project overhaul. – Berin Loritsch May 9 '19 at 13:42

Your Answer

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

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