Asp.net Verification Email - c#

After the user finishes registration process, we need to send verification email to the user.
I know how to send email but i need to know what is the process of sending a verification link, should i create a column in the table to save the verification token and send it encrypted. If we have to save the verification token what is the perfect way to generate this token. I do not try any solution.

I would recommend generating a GUID when the user successfully registers, like this:
Guid theVerificationCode;
theVerificationCode = Guid.NewGuid();
Now store this GUID value in a database column, presumably in a User-like table.
Now when you are sending the email, you can provide this verification code value as part of a URL via the query string, like this:
string theVerificationCode = GetVerificationCodeFromDatabase();
string theEmailLink = "https://www.yoursite.com/YourApp/Verify.aspx?code=" + theVerificationCode;
Finally, you will need to build logic into the Verify.aspx page that will match what was passed in the query string matches what is in the database, if they match then you can allow the user to authenticate, if not then display an error message.

Yes, you should create a column in the table to save the verification token.
You can have activation code as "GUID"
A simple way of do the same is:
Build your Query String by combining User-ID, verification token and Creation-date.
Do encoding of the combined string
"?user=" + Convert.ToBase64String(Encoding.Unicode.GetBytes(String.Format("user={0}&code={1}&cd={2}", User-ID, verification, Creation-date)));
Send the link to the user
When your user clicks on the link, decode the Query String
Separate the combined values by spiting it using "&"
Encoding.Unicode.GetString(Convert.FromBase64String(ActivationDetails)).Split(new Char[] { '&' });
You have all values required to activate the account. Also, you can add your logic and encryption methods. However, the base remains same.
Hope this helps.

I would recommend having a field called something like "ActivationToken" and have a GUID generated. You can do this in SQL directly by calling the newid() function, or in C# by calling Guid.NewGuid(). This is a very unique/random value that is next to impossible to brute force.
So when the user registers, you would do something like:
insert into tblUsers (Username, Password, Active, ActivationToken) values ('johndoe', 'mypassword', 0, newid())
The link would be like: http://yoururl.com/Activate.aspx?token={yourActivationGuid}
Update tblUsers set Active=1 where ActivationToken={yourActivationGuid}
If your UserID is already a GUID, you could probably get away with just using that (such as if you're using aspnet_user tables). As for not allowing the login, just check if the Active flag is set to true. If not, disallow the login.
So to validate login you could do:
select * from tblUsers where Username="johndoe" and Password="mypassword" and Active=1

Related

Assign user based on another table in asp.net mvc4

I'm not even sure how to search for this question, so forgive me if I'm asking a duplicate question and would be grateful for any redirection needed.
I have data (Account Number, Password, Internal Y/N) that is being submitted to an Account Table from Navision. I want to use this data to automatically create a user in the UserProfile table (Username = Account Number, Password = Password) and assign that user to the Admin role if Internal = Y and DealerAdmin if Internal = N.
The data will continue to be maintained for Account numbers in Navision, but the DealerAdmin can add additional users from the website. Is this possible? If so, please provide any pointers to tutorials as to where to start? I presume it's a simple SQL statement. Where do I add this code in MVC so that it gets updated every time there's new data in the Account Table?
If you are using SQL why not use a trigger to create a new record in your User UserProfile when your conditions are met?
If this does not work for you can take a look at the post below and call your proc to move the data over if needed.
ASP.NET MVC 4 intercept all incoming requests

Flow of validating a user with hashed password?

I was reading this article about hashing passwords when I came to this part:
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same
hash function.
Compare the hash of the given password with the hash from the
database. If they match, the password is correct. Otherwise, the
password is incorrect.
But I am a little confused with the flow this would follow, for example lets assume I have a database with a user table with id,name,password and email and in order to login to some app I need to input my email and password.
Following the the steps above, I first need to get the salt+hashed password of said user stored in the database.
Question:
Assuming I am using a simple stored procedure would the only way be to do it like this...
CREATE PROCEDURE [dbo].[sp_validate_user]
#us_email VARCHAR (MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT us_id,
us_name,
us_pass,
us_email
FROM Users
WHERE us_email = #us_email
END
Then following step two and three:
public static bool ValidatePassword(string inputPassword, string storedPassword)
{
// Extract the parameters from the hash
char[] delimiter = { ':' };
string[] split = storedPassword.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(inputPassword, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
My concern comes from the fact that if I am creating objects with the data pulled from the table, doesn't that make the information within vulnerable somehow?
Also does that mean that the only way to use this validation is pulling all the user's information based only on a username/email just to check in runtime if the input password and the hashed one match and then letting said user access the information?
I'm sorry if this sounds confusing but any insight would be great.
It looks like you may be thinking of it backwards. The salt is added to the cleartext password before passing to the hash function. Store the end result in the database.
Commonly, the salt is the username. Something unique to each user to thwart dictionary attacks. (A dictionary attack relies on the economy of scale by cracking one password and then looking for other instances of the same crypto-text. It used to work especially well on very large user databases like well known sites that have millions of users, but hopefully those sites use proper salting and key derivation nowadays).
So for username u, password p, assume SHA2 is hash function. Concatenate u + p to get a salted value, then hash it.
hashtext = SHA2(u + p) // in this case, + is concatenate
hashtext is what you store in the database.
For the login, user enters his username u2 and password p2:
tryhash = SHA2(u2 + p2)
Query database for a user record matching u2, with password hashtext of tryhash
Lets say you have an MVC action receiving loginViewModel which is populated with cleartext email or username as well as cleartext password, entered from the page:
var loginUser = new User(loginViewModel);
CalcHash(loginUser);
var realUser = users.Find(loginUser.username);
if(realUser.HashPassword == loginUser.HashPassword)
// success
While it is also possible to add the hashed password as a second argument to your Data Access method, ie. users.Find(username, hashPass), it is usually not done this way, because you need to access the user record even if the password fails, in order to increment password failure count and lockout the account.
The article covers ASP.NET (C#) Password Hashing Code but you seem to want to use a database?
You have three things to worry about; the unique key for the user (username), your chosen hashing algorithm and adding a salt to the password attempt (prevents rainbow table attacks).
To validate a password you should create a sql stored procedure that accepts the username and password attempt as parameters. This data is in plain text and has been entered into the web form, passed to the web server and will be passed into the database server via the stored procedure.
The stored procedure will do the following;
Lookup the data row for user based on matching the username parameter with the username field and
select the stored salt field
Append the salt from (1) to the password parameter and hash the result
Lookup the data row for the user based on matching the username parameter with the username field
and the hash result from (2) with the hashed password field.
If there is no row found the password hashes don't match and are wrong so return a suitable error code
If there is a row found return the useful user data i.e. First Name, Address
If the stored procedure handles all this then the web server never needs to know what the salt is or the hashing algorithm. At no point does the hash result or the salt get transmitted out of the database server.
I think you understood it correctly, this is the usual workflow:
Get the password-hash by username SELECT password_hash FROM user WHERE email=?.
Extract the salt from the password_hash, or get the salt from a separate field.
Calculate the hash of the entered password with the extracted salt and compare the hashes.
Validating the password cannot be done in a single query, because you first have to extract the salt. Appropriate hash functions like PBKDF2, BCrypt or SCrypt are often not supported by the database system, so you have to do the validation in your code. Additionally to the salt you also have to store other parameters like the cost factor and the algorithm (to be future-proof), so it is a good idea to store all these parameters in the same database field.
The salt should be a random string of at least 20 characters, so it is not safe to use the username as salt, or to derrive the salt from other information.

Populating SecurityStamp for legacy users in database in ASP.NET Identity

I have a legacy database that I am using with ASP.NET Identity. In order to use the Identity functions a SecurityStamp value is required in the database for each user.
Some have mentioned in other questions relating to this that the value can be 'any random value, EG a random int' but that doesn't sound right to me!?
I created a new user in the database using this code:
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
and it populated it with the following value: cea9a659-e965-4e76-8203-ed1c79491fa7
That seems like a more 'secure' value to me than a random int, especially when it's called the SecurityStamp, it seems like it should be populated in the same manner for all users in my database.
How can I populate the SecurityStamp values for my Users database, properly?
Security Stamp by default is GUID and I have not seen any way to modify it. So you if you want to populate that value for all existing users just run sql:
update AspNetUsers
set SecurityStamp = NEWID()
where SecurityStamp is null
So the security stamp can be any string you like, its just used to as a comparison point, so you are free to seed all of these to whatever value you want initially (even a constant empty string would work fine), by default the UserManger will generate a new guid for the stamp automatically during these methods:
Create
RemovePassword
ChangePassword
AddPassword
RemoveLogin
SetEmail
SetPhoneNumber
ChangePhoneNumber
SetTwoFactorEnabled
And you can always call UpdateSecurityStamp directly.
Finally if you are using the Identity.EF implementation, you can always just directly set the field as well:
user.SecurityStamp = generateAString();
await userManager.UpdateAsyc(user);

RavenDB Querying to check Username and Password

I'm fairly new to C# and RavenDB, so please excuse my lack of understanding.
I currently have a Windows Form Application. In one of the forms, I have two text boxes and one button. These two text boxes serve as the username and password inputs and the button is obviously there so that the user can login. When the user clicks on the button, a method is called and saves the content of the two inputs in two string variables.
At the moment, in my RavenDB Database, I have created two samples of username and password.
How do I appropriately check whether the username and password given from the user exists in the database.
Any help is really appreciated.
There are two ways to answer this question.
a) You can query for multiple properties using the Linq provider
session.Query<User>().Where(user=> user.Name = username && user.Password = pass).ToList();
b) The problem with this is that this assumes that you are storing the password as plain text in the database, which you should never do.
You can see how we implemented that in RaccoonBlog's RavenDB's sample application:
https://github.com/ayende/RaccoonBlog/blob/master/src/RaccoonBlog.Web/Models/User.cs
https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Areas/Admin/Controllers/LoginController.cs
As a matter of good security practice you don't store passwords at all, rather you you store the password's hash.
To store your password
Read the values on the server and generate a hashcode of the password. You should use crypto functions to generate hash (such as via SHA256)
Store a document in Raven DB of type User with his username and hashed password
To check if the user with the passed credentials is in the database
Query Raven DB and look for the user with the given name and password hash.
Sample code
var user = session.Query<User>()
.Where(u => u.UserName == "Alice" && u.HashedPassword == "hashPwd");

I don't understand how email activation works

I want to verify that the user email is valid and turn this email into his id in my system.
Yet I don't know how to make a link in the mail, that activates the account like(facebook and others
) and I don't really understand what happens when the link is selected.
I thought of generating a key like "sdklbsdgk4493" to enter once- so that guessing is hard, yet for many people copy and paste is not trivial and I may annoy them with this solution.
Any thoughts or ideas?
p.s: I'm working in c# so if it can be done with c#... it will be great :)
Thanks Asaf
When you insert a new user in the Database, their status should be "Deactivated" and you insert a "GUID" you generate alongside. You send them a link to your activation Page which would contain this GUID in the Query String. It will look like this:
www.YourSite.com/Activation.aspx?GUID=jdfhg43h98234
In the Activation.aspx page, you take this GUID from the Query String and compare it to the one you have in the Database. You then activate the Account having that GUID.
Create the user
Generate a unique string for the user
Have a Table that stores the unique string, the user Id ,a boolean that holds whether it got activated or not, the generation date, the expiration date and if you have different uses for these activation strings, the type(link to another table)
Now within the email you should get the string and write it within the email along with a link to the page you're going to use for validation such as whatever.com/verify.aspx?activationString=hd3fd33fen342n43
Within this page you do a query search within the table that holds the keys and if its not already validated
You have your users table in the DB (or where ever it is that you store your list of users), just add a column stating if the user's mail is validated.
To the validation mail add a link that fires some PHP with a user-specific code (like it's index in the DB). The PHP will set the user's "validated" column to true, and it'll be done.
It's not as complicated as it may seem at first.
The idea is to create a random key, save it to the database connected to the useraccount, supplying a link to the users e-mail which could point to a webservice(or regular website) which takes the key as a querystring which will then activate the account connected to that specific key.

Categories

Resources