duplicate ID in aspx c# when sending emails - c#

Im creating a tracking system in aspx c# and I want the user to submit a ticket and it'll assign it an ID and send the email.
I got everything to work but the problem is if two or more users are on the same page it'll assign them the same ID when they send the email (#150 and #150). However in Sql, it would be (#150 and #151).
aspx.cs page (Im getting the current ID from SQL)
id.Text = ds.Tables[0].Rows[0]["id"].ToString();
Then I'm incrementing it by 1 (to send the email) Because I dont want the current users that's sending the request to have an old ID.
id = id + 1;
Note that this works perfectly if only one users is on the page submitting the request.
Can someone get a work around this? Thanks!

In case you are using the logged-in user's id on the url to handle a user's session and also set the email ID (check example below):
.aspx?user_id=150&email_id=150
Then you need to use the appropriate user's session that opens your webpage as shown below to get the appropriate ID as an email ID.
id.Text = Session[user_id].ToString();
For that reason when both users are logged in simultaneously you only get the same id for both. You probably have a static site that handles only one session per user.

Related

Secure way to Delete a record in ASP.Net MVC

I want to delete a product from my ASP.Net MVC 5 website. I want to know if adding [AntiForgeryToken] and [Authorize] is enough to secure the Delete operation?
View
<p>Delete: #Model.Name</p>
#using (Html.BeginForm("Delete", "ProductController", FormMethod.Post, new { ProductId = Model.ProductId }))
{
#Html.AntiForgeryToken()
<button type="submit">Delete</button>
}
Controller
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Delete(long ProductId)
{
/* Do I need to check if the logged in User has permission to delete the product?
var product = ProductRepository.Get(Id);
if (product.Creator == User.Identity.GetUserId<long>())
{
ProductRepository.Delete(ProductId);
}
*/
// or, can I avoid the trip to DB and just delete the record?
ProductRepository.Delete(ProductId);
}
Scenario: A hacker registers on my website and create a valid account. Now the hacker views his own product and obviously he has an AntiForgeryToken. Can he now just change the ProductId in the browser and Post a request to delete someone else's Product?
Short answer. That is not enough.
Antiforgery tokens just say that the person making the original page request is the person making the update.
The base authorize attribute just verifies that the user is logged in.
What you are looking for is data security. There's an example of this on microsoft's own site.
What you've stated in your last paragraph, a hacker can sign up for an account create their own list of products and given what you show them in the url could guess legitimate other records to edit
Say you have a url
https://example.com/product/edit/13
what is preventing the user/hacker from guessing at
https://example.com/product/edit/12
or
https://example.com/product/edit/14
Without security at the data level that says what records a user can or can't access/update, you run into a situation where a malicious user could see or edit all kinds of information.
This is the exact scenario that FISERV found to expose other client information
from the article
Hermansen had signed up to get email alerts any time a new transaction
posted to his account, and he noticed the site assigned his alert a
specific “event number.” Working on a hunch that these event numbers
might be assigned sequentially and that other records might be
available if requested directly, Hermansen requested the same page
again but first edited the site’s code in his browser so that his
event number was decremented by one digit.

MVC logout all active sessions after same user login

I have c# mvc web application.There is simple login page according to email and password. Now I have a need like that:
When a user login to the system, all active sessions that same email address will logout.
How can I achieve this?
You can use Session.Abandon() or Clear() to abandon the current session, but if there are multiple people logged in with the same address, this will not address that.
You'd have to build that detection in; for instance, you could update a flag on the table that represents your users and then in the other user's sessions periodically check the table if they were re-logged in. OR when a user logs in, create a token in a database table with an expiration date; associate that token to a user in a cookie. When logged out or logging back in, you could invalidate the token associated to that email address, and each user, when they attempt to access the application, could be rejected by your application checking whether the token is expired.
The Abandon method should work (MSDN):
Session.Abandon();
If you want to remove a specific item from the session use (MSDN):
Session.Remove("YourItem");
If you just want to clear a value you can do:
Session["YourItem"] = null;
If you want to clear all keys do:
Session.Clear();
If none of these are working for you then something fishy is going on. I would check to see where you are assigning the value and verify that it is not getting reassigned after you clear the value.
Simple check do:
Session["YourKey"] = "Test"; // creates the key
Session.Remove("YourKey"); // removes the key
bool gone = (Session["YourKey"] == null); // tests that the remove worked

How can I use a value from a session variable as part of the group name in signalR

Hi I am trying to set up signalR to distribute messages to web users the problem is that the one site holds different 'areas' and also 'user types'.
The Area is decided when the user visits the site by passing a url parameter, this is then stored in a session variable, The 'user type' is by default not logged in then changed when the user logs in to there user type (returned from a webservice) and stored in a User object.
My aim was to connect to the hub using signalR when the user visits the site and add the users connectionId to a groupname, using the 'area id' from the session and the 'user type id' from the User object in the context.
The problem I am having is that I can obtain the user id but when it comes to the area id signalR cannot access the session. I understand the reasoning behind not allowing the session available in signalR but does any one know if there is a way to enable this or an alternative way that I can gain access to the users area so that I can create these unique groups.
If you do know the users area you can simply call a function from the client once you have connected to add them to that group:
In your page load:
ClientScript.RegisterClientScriptBlock(this.GetType(), "areaKey", "var theAreaTheyBelongTo= '" + serverSideAreaTheyBelongTo + "'", true);
On your hub:
public void SubscribeToArea(string area)
{
Groups.Add(Context.ConnectionId, area);
}
On your client:
$.connection.hub.start(function () {
yourHubName.subscribeToArea(theAreaTheyBelongTo);
});

Send email to user for password reset

The flow is:
user enters email address
after submit, an email is sent to the user
The email will include a link that will take the user to a reset password page.
Now, how do I fetch user's ID based on the email address and encrypt it? Then what should link be? Like, what I want is fetch the User ID then encrypt it somehow so that the link doesn't contain the actual ID and that link will take the user to a page that will have textboxes to reset the password. I am just confused how to go about it.
Also is this the secure way? To reset a password like this?
I usually create a new table in the database:
PasswordresetRequest with the following fields:
Id: Guid - Id of password reset request.
Accountid: string - username of user
Created: DataTime - timestamp of when password reset were created
Flow is as follows:
User request password reset at web site.
A new record is created in the PasswordresetRequest table.
An email with a link to the password reset page with the password request id as request parameter is sent to the user.
User click on link in email which send him to password reset page.
Password request if fetched from database from request parameter. If request could be found or and request is not older than e.g. 12 hours a form is presented to user where he can enter a new password.
This is pretty simple to implement and is secure enough for most sites.
There is any number of ways to go about doing this. If your major concern is security, one way could be to send a link that contains a guid parameter which you create and store on your end (in a db table, file or whatever suits you) together with the user id associated with it. When the request for password reset comes in, you check for the guid and look if there is one matching value in your db/file/whatever and proceed with the password reset. Don't forget to delete the guid from your storage to prevent multiple use of the same link.
There is a railscast on exactly this subject: http://railscasts.com/episodes/274-remember-me-reset-password?view=asciicast

How can I set up ASP.NET login to allow the UserName or UserId to be retrieved later on in the session?

I'm trying to create a login system for my website, I've created a custom login.ascx and when the user clicks [ Login ] a div pops up with the contents of login.ascx.
Then after the user enters their credentials, they click on the Login button. They get validated and logged in using this code in the login click function:
if( Membership.ValidateUser( userName.Text, password.Text ) )
{
//Here is where I'm not sure what to do
}
else
{
LoginError.Visible = true;
}
So in the section where I'm not sure what to do, I would like the user to get logged in (Not sure if that means creating an authentication ticket or whatnot). What does is the next step to actually log the user in, I don't want them to get redirected anywhere since they are on the correct page already.
I would also like to be able to retrieve their user name or user id later on for use in my web services. So, for this should I do a Session.Add to create a new session value or is there some other way of storing the data that is preferred?
For authenticating the user,
FormsAuthenatication.SetAuthCookie(username, false/*true if you want to remember the user's login*/);
This logs the user in. You can later use
Page.User.Identity.Name
to retrieve username of the current user and
Page.User.Identity.IsAuthenticated
to check if the user is logged in.
There's no need to store it in Session. Just use:
FormsAuthentication.SetAuthCookie
to send an authentication ticket to the client. Then use HttpContext.Current.User.Identity to retrieve it later.
I find using the membership provider is useful, I would recommend it
Scott Guthrie posted great blog on this
http://weblogs.asp.net/scottgu/archive/2006/05/07/ASP.NET-2.0-Membership-and-Roles-Tutorial-Series.aspx

Categories