10

I want to allow anonymous/not yet registered and registered users to post on my website.

Posts (table)
- Id (int)
- Subject (nvarchar)
- Body (nvarchar)
- UserId (uniqueidentifier)

The project uses the latest MS technologies (ASP.NET MVC 5+, C#...) How should I go about doing that?

Is ASP.NET Identity even the right solution?

What's the difference between these:

  • ASP.NET Identity
  • SimpleMembership
  • Membership Provider

Update I need to be able to differentiate not yet registered users and record their postings in the database.

Update 2 Then have the option to migrate to a registered account. Just like how stackoverflow used to allow anonymous users. Something like this but compatible with ASP.NET Identitfy http://msdn.microsoft.com/en-us/library/ewfkf772(v=vs.100).aspx

James
  • 2,811
  • 3
  • 25
  • 29
  • Identity doesn't support anonymous users.. that kind of defeats the purpose. Anonymous users are just users who haven't signed in yet. So your website has to support them simply by allowing anonymous users into those pages. – Erik Funkenbusch Apr 21 '14 at 19:25
  • No, the membership provider doesn't support anonymous users either. ASP.NET does have the concept of an anonymous user id, which the profile system can use. But this is not membership. You use the `` element in web.config to enable this. – Erik Funkenbusch Apr 21 '14 at 20:26
  • will this work with asp.net Identity? http://msdn.microsoft.com/en-us/library/ewfkf772(v=vs.100).aspx – James Apr 21 '14 at 20:28
  • No, and as I said, it doesn't work with Membership either. Membership and Identity are only about authenticated users. – Erik Funkenbusch Apr 21 '14 at 20:29
  • @James, see my answer below. I added some sample code for using Identity to determine if the user is registered or not. Does this answer your question? – Ryan Erdmann Apr 21 '14 at 20:36
  • Your confusing Anonymous profiles with Membership. It's true that when you use Anonymous profiles, a row is created in the aspnet_Users table for the anonymous user, but this is more of an implementation detail because Profiles are Membership are both based on aspnet_Users. Profiles don't work with ASP.NET Identity, so this technical detail would not apply. – Erik Funkenbusch Apr 21 '14 at 20:40
  • Is there anything equivalent to Profiles for ASP.NET Identity? – James Apr 21 '14 at 20:47
  • @James, there is a vagueness to your question. Do you need Anonymous Users to post with a Name? If not, then what is the issue? Just allow them to post anonymously. If yes, you do want a name, just include an extra input for the name... – Dave Alperovich Apr 24 '14 at 13:32
  • @DaveA it needs to be migratable to a registered account – James Apr 24 '14 at 22:11
  • @James, IC. short of registration, you can't follow users. you can ask the user for a name, but then any other user could use that displayed name to create an account. if you ask for a password, it becomes registration anyway. you could try HTML 5 local storage, with GUID (better to avoid an int) to track them, but localstorage is specific to each browser on each computer. The best option I can think of is allowing them to register or just authenticate using a social network (Google, FB, Twit, etc) Identity supports all of them. Google is very easy, the rest take a little work.\ – Dave Alperovich Apr 24 '14 at 22:12
  • The ASP.NET Identity system is designed to replace the previous ASP.NET Membership and Simple Membership systems. It includes profile support, OAuth integration, works with OWIN, and is included with the ASP.NET templates shipped with Visual Studio 2013. – Joe May 02 '14 at 17:18

5 Answers5

6

I want to answer one of the original questions: "I need to be able to differentiate not yet registered users and record their postings in the database.".

I have used Simple Membership before and I am using Asp.Net Identity Framework 2.2.1. In both cases I use anonymous identification to differentiate not yet registered users and authenticated users.

  1. Enable anonymous identification in your Web.config by adding <anonymousIdentification enabled="true" cookieName="YOUR_COOKIE_FOR_ANONYMOUS_IDENTIFICATION" />.
  2. You can get the anonymous id by Request.AnonymousID. That id is a GUID in string format.
  3. As other users mention, you can use whatever identity system you want, just remember to clear the anonymous id during the log out process. Typically after a user is successfully authenticated, you save either the username / userId with the anonymousId into persistence storage. By clearing the anonymousId when the user logs out, you can make sure the other authenticated users won't be able to associate with the same anonymousId.
  4. You can clear the anonymousId by AnonymousIdentificationModule.ClearAnonymousIdentifier(). Note: the AnonymousIdentificationModule is in System.Web.Security assembly. You can add a reference of System.Web or use CTRL + "." on the AnonymousIdentificationModule in your code to bring in System.Web.Security.
David Liang
  • 20,385
  • 6
  • 44
  • 70
  • 1
    Thank you for providing information about Anonymous Identification. Helped me a lot in an MVC project where I needed an identifier for anonymous users to cache some data, without relying on Session module. +1 – dizarter Jun 30 '22 at 18:31
  • 1
    @dizarter: my pleasure. Glad it helped. Too bad that the anonymous identification feature is gone for ASP.NET Core, and it seems like you will have to implement your own: https://stackoverflow.com/q/41992601/2410655 – David Liang Jun 30 '22 at 19:34
  • And thank you once again for info on ASP.NET Core. I do not need it right now, but it will certainly come in handy in the future. – dizarter Jun 30 '22 at 19:48
5

ASP.NET Identity is the newest revision of authentication in ASP.NET. It's predecessor was SimpleMembership, which itself was an attempt to improve on the old ASP.NET Auth. Membership providers are not a separate kind of authentication system, but instead, a way to bootstrap ASP.NET Auth or SimpleMembership with additional functionality. If you had a particular login scenario not covered by the defaults, you could create a membership provider that would allow ASP.NET to interface with that system.

ASP.NET Identity supercedes everything else, and does not use membership providers. Instead, it's provides a very extensible foundation for authentication that through the use of standard APIs allows you to customize authentication in pretty much any way you like. It also has much more robust support for OAuth and external signin providers, and interfaces better with things like Active Directory, especially the Azure version in the cloud.

If you're starting on a new project go with Identity. Saying that it will remain for the forseeable future is a bit dangerous with Microsoft's seeming flavor-of-the-week approach to authentication in the past, but from my personal experience working with it, they seem to have finally gotten it right. I think you'll only see refinements and improvements going forward, rather than complete replacements.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
1

ASP.NET Identity is a flexible framework for handling user authentication in your Web App. It's pretty awesome, and I would highly recommend you continue using it in your project.

Identity doesn't support anonymous users, per se...rather, it's a framework for letting you manage users that are authenticated. Identity will let you maintain local users, or if you want, users that authenticate with your web app via an external service (say, Facebook or Google).

It sounds like you want part of your web app to be accessible to users who are not authenticated. The way you'd achieve that is through attributes on your ASP.NET Controllers.

Adding the [Authorize] attribute to a Controller or Controller method will tell MVC to ensure the user is both authenticated and authorized. However, to allow anonymous users, simply put the [AllowAnonymous] attribute on the method you want to give public access to.

However, you'll still be able to tell if the user is authenticated or not. Consider this sample controller and method:

[Authorize]
public class PostController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()
    {
        var isAuthenticated = User.Identity.IsAuthenticated;

        return View();
    }
}

That isAuthenticated will let you know if the current user is logged in or not, and if they are, you can get more information from the User.Identity object.


In regards to your general question about the differences between the membership frameworks, I'll defer to the official documentation which gives a great overview of the differences: http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity. You definitely want to use ASP.NET Identity in your web app.


Update Check out this sample code, which will help you differentiate between not yet registered users when recording posts to the database.

[Authorize]
public class PostController : Controller
{
    [AllowAnonymous]
    public HttpStatusCodeResult CreatePost(string postText)
    {
        // Use ASP.NET Identity to see if the user is logged in.  
        // If they are, we can get their User Id (blank otherwise)
        var isAuthenticated = User.Identity.IsAuthenticated;
        var userId = "";
        if (isAuthenticated)
            userId = User.Identity.GetUserId();

        // Create a new post object
        var post = new
        {
            PostText = postText,
            Anonymous = !isAuthenticated,
            UserId = userId
        };

        // Save the post to the database here

        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
}
Ryan Erdmann
  • 1,786
  • 10
  • 11
1

One way you could handle this is by using a cookie based authentication method. Browsers will send up any cookies associated with your domain with each web request, so they're an easy way to handle authentication. The idea here is that we'll have a cookie called ident that will store a user id we generate. I'm using Guids, but you could easily create an entry in your DB instead. When we get a web request, see if the cookie exists. If it does, we have their user id in the cookie. Otherwise, generate a new user id for them and set the cookie.

It's not perfect...if your user clears cookies you'll lose your ability to identity them, but it's probably the best you can do.

Here's some working code you can drop into your project and play with:

public class PostController : Controller
{
    [HttpGet]
    public ActionResult Index(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return Content("Please specifiy a value for text.  i.e. /Post/Index?text=Message");

        var message = "";

        var isAuthenticated = Request.Cookies["ident"] != null;
        if (isAuthenticated)
        {
            var userId = Request.Cookies["ident"].Value;
            var post = new
            {
                Text = text,
                User = userId
            };
            // Save to database here
            message = "You are a previously recognized user, with UserId=" + userId;
        }
        else
        {
            var userId = Guid.NewGuid().ToString();
            var identCookie = new HttpCookie("ident", userId);
            Response.Cookies.Add(identCookie);

            var post = new
            {
                Text = text,
                User = userId
            };
            // Save to database
            message = "You are a new anonymous user. Your new UserId=" + userId;
        }

        return Content(message);
    }
}

If you do end up going this route and you want to reuse this logic among multiple requests, I'd highly recommend abstracting it out into a utility class or, better yet, override the IPrincipal User property in the controller. Take a look [here](ASP.NET MVC - Set custom IIdentity or IPrincipal for more information about setting a custom IPrincipal.

Community
  • 1
  • 1
Ryan Erdmann
  • 1,786
  • 10
  • 11
  • is the ident cookie something asp.net identity generates? can it be spoofed? – James Apr 24 '14 at 08:58
  • The ident cookie specifically isn't something ASP.NET does, but we are letting ASP.NET handle creating the cookie for the request. Yeah, it can be spoofed, but you're dealing with anonymous users anyway so I think that issue is moot. – Ryan Erdmann Apr 24 '14 at 21:09
  • I want to allow both anonymous and registered users to post. That's why I asked about ASP.NET Identitfy. updated question to make this more clear – James Apr 24 '14 at 22:13
1

The ASP.NET Identity system is designed to replace the previous ASP.NET Membership and Simple Membership systems. It includes profile support, OAuth integration, works with OWIN, and is included with the ASP.NET templates shipped with Visual Studio 2013

The ASP.NET user profile feature is designed to provide information that is unique to the current user. Profiles can work with either authenticated users or with anonymous (non-authenticated) users.

In some cases, your application might initially be maintaining personalization information for an anonymous user, but eventually the user logs in to your application. In that case, the user's identity changes from the assigned anonymous user identity to the identity provided by the authentication process.

When users log in (that is, when they stop being anonymous users), the MigrateAnonymous event is raised. You can handle this event to migrate information from the user's anonymous identity to the new authenticated identity, if necessary.

http://msdn.microsoft.com/en-us/library/vstudio/ewfkf772(v=vs.100).aspx

Best way to Migrate Anonymous Profile

http://odetocode.com/articles/440.aspx

public void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)
{
  ProfileCommon anonymousProfile = Profile.GetProfile(args.AnonymousID);

  Profile.ZipCode = anonymousProfile.ZipCode;
  Profile.CityAndState = anonymousProfile.CityAndState;
  Profile.StockSymbols = anonymousProfile.StockSymbols;

  ////////
  // Delete the anonymous profile. If the anonymous ID is not 
  // needed in the rest of the site, remove the anonymous cookie.

  ProfileManager.DeleteProfile(args.AnonymousID);
  AnonymousIdentificationModule.ClearAnonymousIdentifier(); 

  // Delete the user row that was created for the anonymous user.
  Membership.DeleteUser(args.AnonymousID, true);

}
Community
  • 1
  • 1
Joe
  • 1,649
  • 12
  • 10