ASP.NET Identity table update/migration at runtime - c#

We are creating a new web app that will update/migrate an existing DB, including the user information. Since the passwords are SHA encrypted in the user table, I would need to migrate during runtime, as the users log in.
In order to do this, I want to hook into the user validation code - if the user exists in the new Identity user table, good - we're done - use it. Else check the old user table (and validate the password with the old password validation mechanism), create a user in the new Identity table, delete the old user from the old table (or flag as migrated), then return that new Identity user.
Is this a reasonable approach? Are there any examples of this I could use as a starting point?
Note: I would like to use the standard ASP.NET Identity 2.0 table structure with the exception that user ids will be int - since the existing schema relies on an int user id.
Edit: The existing web app will go away and we will replace it with the new web app (with ASP.NET Identity) but we will still point to the existing DB (containing the old user table and other data). The addition to the DB will be the new ASP.NET Identity tables and any updates to join to those tables instead of the old user table.

A a good way to deal with legacy password hashes described in the official migration guide: http://www.asp.net/identity/overview/migrations/migrating-an-existing-website-from-sql-membership-to-aspnet-identity
On that page search for SQLPasswordHasher and see how they do the password matching.
Basically the idea is simple - when you update your system to Identity you copy all the old users and their hashes (and salts) into new Identity table. Then you tell identity to use the above-mentioned SQLPasswordHasher to try to match either the old SHA hash or (for already updated users) the new-style hash. And (optionally) you can update the hash for freshly logged in users to the new-style.
I have done this with a few projects and there was not a single problem.

Looks like a good place would be in ApplicationOAuthProvider:GrantResourceOwnerCredentials, where we are doing a userManager.FindAsync() to look for user (with pw) in new User table. If that fails (user == null check), I'll add the code to look for user in old User table and if there (and password passes hash test), will create user in new User table with old User table data and new password hash - and then mark old User table record as "migrated" or "upgraded"

Related

Editing asp.net core identity claims instead of adding them

I'm using external logins for my asp.net core mvc website, and when the login completes I want to store the social info they used to login (such as username, profile image, etc.) as claims in the user's identity...
So I run code like this in my account controller after a successful login:
var authClaim = user.Claims.FirstOrDefault(c => c.ClaimType == authToken.Name);
if (authClaim == null)
externalClaims.Add(new Claim(authToken.Name, authToken.Value));
else
authClaim.ClaimValue = authToken.Value;
if (externalClaims.Any())
await _userManager.AddClaimsAsync(user, externalClaims);
await _userManager.UpdateAsync(user);
however when I attempt to do this, the claims table is duplicating the claims rather than updating them as I expected, so every time the user logs in I get another collection of records in the table for that user that are identical to the last.
do I have to delete them and re-add them instead on every login? if not, how do I update existing claims without duplicating them?
I'm doing it on every login in case the user has changed their profile or other info (and to make sure I have the most up to date token).
I'm also curious why I add the claims to the main Identity of the user. The User has a property called ExternalClaims, but it is empty and there doesn't appear to be any way to update it. It seems to me this is a better place to put these third-party Claims, but I can't for the life of me find any way to modify it...
either way, I'm sure I'd have the same problem if I use this code, so is the proper course to delete the claim on login and always add it new, or should I be doing something differently?

Recreating a deleted user in ASP.Net Membership

I'm using an ASP.Net Membership provider to handle user accounts on my website and I've set the DeleteUser() function to only delete data from the aspnet_Membership table as I'd like to keep the user ID and details in aspnet_Users for auditing.
I've encountered a problem whereby if I delete a user "bob", when someone creates a new user with the same username, then instead of creating a new aspnet_Users record with a new UserId (it's a GUID by default) it will instead link the new aspnet_Membership table record to the previously created "bob" account.
This means rather than creating a new user that happens to have the same username, it's re-activating the old user and linking their activity history together.
Is there a way to force ASP.Net membership to create a new aspnet_users record instead of hijacking the old one?
Thanks!
Unfortunately it seems that the ASP.Net Membership SQL Provider generates the User ID GUID using the username as a seed. This means that without deleting the user (which you wouldn't want to do if you were keeping an audit history) there is no clean way of creating another user with the same User ID.
To resolve my issue I have done the following:
Allowed ASP.Net Membership to assign a membership record to the asp_user record as it does by default
Added an audit record to my audit table explicitly specifying that a user has been re-created
This will allow me to check when writing audit queries whether the user performing an action was once removed, and hence whether they're likely to be the same person or not.

AspNet Membership - Centralizing Logins

Right now we have several databases, each individual database has its own aspnet membership tables. We want to centralize all the membership to one database. For instance a main login page where they will specify the database, username and password. Then we would check on the centralized database and authenticate and redirect them to their account based on the database name they inputed on the textbox.
What is the best way to do this?, there maybe multiple usernames that are the same in different databases and this is my challenge.
ASP.Net Membership has Applications table. As long as you have different application name for different website, you can merge them into one big database; chances of duplicating user id (which is stored as uniqueid) is very low.
When user logins, you need the following 3 fields -
Application (this can be DropDownLis)
Username
Password
Create Own Validation
You cannot use custom Membership Provider to validate user which only accept username and password.
// ValidateUser method doesn't take any additional parameter
public bool ValidateUser(string username, string password)
So you need to implement own validation method to validate user from Merged Database.
Note
If you are redirecting to different website, please take a note of Form Authentication's limitation. For example, it cannot transfer authentication cookie from www.one.com to www.two.com
Are you able to assume that "user123" in database1 and "user123" in database2 are the same individual?
If so, you can just merge as DJ KRAZE suggested. If not, you'll have to create new users for the duplicated user names. You could write a fairly simple SQL script to do this by appending a number to the end of the ID.
Like.... found "john" in database 1, create "john1" user. As I recall, the aspnet_membership database comes with a pretty robust set of stored procedures for creating users and so forth that create all the proper table entries. I would definitely use those, rather than trying to freestyle insert/update statements, if you end up going that route
i believe you can select the database to connect to on your logincontrol. so create a dropdown where users can select the database to connect to and then use that selection as your database. have a look at number 4 on http://forums.asp.net/t/1403132.aspx/1
the selection can be the connectionstring name that specifies the database.
Based on my experience, the best thing you can do is prefix the usernames based on the source database on duplicates and delegate the consolidation to the end-user.

Session - Login to view user data

Before I start I would like to state that I am very VERY new to ASP.NET and C#, and programming in general really. I have created a web application with a login page looking to a custom database containing the user's data as well as their login details. I did this rather than using the ASP.NET Membership as there are complications using this over my college's network.
As the table contains many records of user data, what I would like to do is have a user log into the app and (based on their login details) allow them to view JUST their details from the table I have created as their are many records of user data.
Am I correct that I should create a session based on their username and password and with this, somehow match it to their record in the table using SQL which will display ONLY their data rather than the whole table be displayed?
If this is the case, I really don't have a clue how to implement this.
I am aware that this will be very insecure but the users are all fictional and this app will not be published to the web. I just want it to work in the simplest form for my assignment and I'll cover the security aspects in my report and state how it could be improved.
Any advice would be greatly appreciated, Cheers.
Whenever you find a user's credentials valid enough for login, add some/all of his credentials to the current session like,
Session.Add("sessionvariablename",textBoxLogin.Text);
On the other page, that comes after logging in, check the following,
if(Session["sessionvariablename"].ToString()=="xyz")
{
Do whatever you want
}
You may not want to add sensitive information to the session for security concerns. Use
Guid.NewGuid() to create a unique 32 character hexadecimal code for each user and store it in session.
You should have row in your table with with a unique identifier. Like ID or userNr or something similar, make it an integer and set to primary key and then set its identity specification (is identity) to yes by double clicking on it (I am presuming that you are using visual studio).
When the user has submitted there login info and they checked out, you save there unique identifier in a session.
when you need to pull out information specific to the user in question, you use sql WHERE ID (or userNr) is equal to the session id.
hope this is what you needed, its my first answer in here so I would like to be helpful.
If I'm getting it right, using username and password as session parameters will work but it's not the best idea. Normally you table with users contains a kind of unique identifier for each record (guid or autoincrement id). You may use this identifier as a session parameter.

How to insert data into the database using a textbox and logged in username

I am in the middle of a little project website where I have decided to create a basic messageboard that allows logged in users to write a comment (using a textbox) to which is added to the messageboard database and then displayed using a gridview.
When a user writes a comment I also want to display their username to the post (showing they are the poster) as well as the date (which I have managed to do already using GetDate()).
So far I have this.
I have a ASP.NETDB.MDF database which uses the .NET login functions to allow a user to sign up to my site and login. The default database creates IDNumber, Username etc fields.
I have a messageboard database which has the following fields. ID, UserName, Time, Comment.
So just to recap. When the user is logged in I want him to have the ability to go to the messageboard webpage and type in a comment using a textbox.
When he clicks the submit button the message typed will be added to the database and then shown through the gridview. His username and time of post needs to automatically be added to the post (which can be determined through the user being logged in to a unique login account (how I do this I have no idea!).
Should I join the tables? (i.e Username (from login table) with Username from messageboard table? Is there a better way to go about all of this?
Sorry for being noobish..! I am kind of new at this.
You should join the tables if there is data in the "login" Table that you need to show next to the comment that does not exist in the "messageboard" table.
For Example if you want to show UserName,Message then you don't need a join because username is already stored in the messageboard table. However, if you want to display FullName,Message and FullName is in the login table and message is in the messageboard table, you will need a join.
Try looking for some examples of what you are trying to do on the internet. There should be a lot out there, I have seen quite a few blog style examples with ASP.NET MVC.
Good Luck

Categories