6

I'm working a web application, which is MVC 5 + Angular JS hybrid. There is no authentication in the web app and an anonymous user can come and ask for price for certain services. To get the price the user needs to answer some questions spread across few pages. Here is the flow of app.

  1. User clicks button to get price

  2. A unique URI the request is generated and user is redirect to the questions page

  3. User answers questions and user submits the answers. The questions are spread across multiple pages navigated through angular routing. The answers are saved back to server on page navigation.

  4. Once, the user submits the answers, the system (server) generate the price and display it to user.

Currently, if the user has bookmarked the URI, he can come back after days and continue from where he left. I want to prevent this behaviour.

What are the different options do I have in MVC? I can think of following:

  1. Using HttpCookie with expiration time

  2. Save the last access time in DB and validate if the user has come within a stipulated time frame?

I would like to avoid HttpSession. I'm inclined towards using HttpCookie since it looks to be the simplest option.

  1. If we go with HttpCookie option, are there any side effect that I need to keep in mind?

  2. Are there any other alternative within MVC I can look for?

Ankit Vijay
  • 3,752
  • 4
  • 30
  • 53
  • As you are not having login module, you can also opt for localStorage which will get updated every time. – geminiousgoel May 19 '17 at 05:34
  • If you dont want user to access the page from start only, you can use sessionStorage. once user close the window/tab, sessionStorage will be deleted automatically and you can form user to start from beginning. – Ashish May 19 '17 at 06:00
  • Thanks guys for your suggestions, for my scenario I would like to control it through my MVC app/ server. localStorage/ sessionStorage are client side only. – Ankit Vijay May 21 '17 at 22:49
  • Why avoid `HttpSession`? it is probably more suited to this scenario than `HttpCookie`. Unless you *want* the user to be able to return up to a certain point in the future. – Jon P May 22 '17 at 04:13
  • My application will be hosted on a load balance environment. With `HttpSession` I may have to go for out-of-proc session management. I want to avoid this complexity. Besides, lately `HttpSession` does not look like to be favoured: https://brockallen.com/2012/04/07/think-twice-about-using-session-state/ – Ankit Vijay May 22 '17 at 04:31
  • Do you save the unique identifier for that particular user in DB? – User3250 May 22 '17 at 06:43
  • @User3250 I do. – Ankit Vijay May 22 '17 at 07:00
  • Ok, another approach could be to save expiration time in DB against your unique user id and on each page load check against DB expiration time. – User3250 May 22 '17 at 07:15
  • That's option 2, i mentioned. This is certainly the way. My ask was if HttpCookie is good enough and what are precautions I need to take with HttpCookie? – Ankit Vijay May 22 '17 at 13:14
  • @AnkitVijay : Why don't you simply use `ViewBag`? In viewbag you can store some field to know that the current user is active. only if the user is active the following pages shall be displayed, else redirect to the first page or login page. The data you put in the ViewBag/ViewData is only available during the life-cycle of the request within which you populated it. – ViVi May 24 '17 at 12:37
  • HI @ViVi, I have a redirection scenario where `ViewBag` won't work. I also looked into `TempData`. But, `TempData` won't work for refresh browser scenario. I have stick with `HttpCookie` for now. – Ankit Vijay May 24 '17 at 22:32

3 Answers3

4

If You want to expire some link without storage involved and your service need to be scaled I think You just need to add expiration date in your link and sign it.

I believe you can create your URL in a way like this

Pseudocode:

var info = [Payload any info you need to store(questionnaire id or so)] + [expirationDate]
var sign = HMAC256(info + [SERVER_SECRET])
var clientLinkParameter = info + sign
var clientLink = [baseURL] + [delimiter] + Base64(clientLinkParameter)

*HMAC256 - it's just example you can create signature using any algorithm you want

Now you can just check your link for expiration by parsing serialized data in the part before delimiter. You can also check that date was not modified by checking:

HMAC256([partBeforeDelimiter] + [SERVER_SECRET]) and [partAfterDelimiter] for equality. If they match this is the link your server sent (as only your servers know what the [SERVER_SECRET] is) otherwise it was modified by the client.

Now you can store any non secret data in user link allow user to share this link and other great things that you can do with a link without worrying that someone modify our link. Client can deserialize first part as well if its widely known serialization algorithm like JSON.

I think this flow will bring better user experience in case of suddenly closed browser (that will clean cookies in your case) and also sharing link with someone (if you need)

Hope this will help.

Alex Lyalka
  • 1,484
  • 8
  • 13
  • This is indeed a nice approach. I however, have gone for session cookie for now. Will look into this if I need something similar in future. – Ankit Vijay May 23 '17 at 22:40
3

I finally, went with session-cookie. I hashed the unique id and saved it in the cookie with salt. I feel this is a reasonable approach for following reasons:

  1. The anonymous user session is going to be short lived. Once, he closes the browser the cookie gets removed.

  2. If the user bookmarks the URI, I look for session-cookie in the Http Request. If the session cookie is not found, I redirect the user to the challenge page.

I have gone for MD5 algorithm for hashing. I understand it is collision prone, but is faster than SHA. Since I do not store sensitive information like password in the cookie, I guess it should be fine.

Ankit Vijay
  • 3,752
  • 4
  • 30
  • 53
3

I'd rather generate a token for a unique user session and store it on the server along with CreatedDate. So URL will have a token query string parameter that will be validated against the date.

  • It's more secure than relying on cookies
  • Allows for adding analytics to your site, where you start storing q/a combinations along with generated prices for a given user session. Start collecting data early. :)
Vlad
  • 51
  • 2