4

I just spent the last two days researching and implementing the new ASP.NET Identity system with my existing database. More on that here: Integrating ASP.NET Identity into Existing DbContext.

Now, I have a working UserStore and RoleStore, but I can't seem to figure out how to leverage them in my ASP.NET MVC 5 application without writing what seems like colossal amounts of code like in all the Identity samples that confuse me.

There's two things I want to achieve: 1) use cookies to maintain the authorizations and 2) use roles to limit application access both in what is rendered in the views and on the controllers.

To be able to use those I need to obviously use the Controller.User property which represents the authorized user and peek into it's roles. How do I get my Identity implementation to make that happen?

Lastly, in the Identity samples I see they're using OWIN, which I kind of get, but it seems like it's a super roundabout way, which I still don't get how to properly implement. As far as Claims, they confuse me twice as much as I understand them.

I'd appreciate any pointers in the right direction.

Community
  • 1
  • 1
Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126

2 Answers2

2

After going back into this I think I figured out a solution that simply works. I ended up creating a startup configuration class for OWIN. From what I understand since OWIN is a middleware it intercepts the requests, figures out the authentication (if any), and updates the User property of the Controller classes where User is an instance of a ClaimsIdentity class.

After that everything else works just as you would normally use the User property of ASP.NET. I did extend my base Controller with an extra property called UserId which parses the User property to get the actual Id being used in the database. My intention with that is to have the Id available to me to query for the real Employee class that my DbContext uses. We'll see if that stays or not, in the mean time, here's the code for my StartupConfiguration:

public sealed class StartupConfig {
    public void Configuration(
        IAppBuilder app) {
        this.ConfigureAuthentication(app);
    }

    public void ConfigureAuthentication(
        IAppBuilder app) {
        app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/"),
            ExpireTimeSpan = new TimeSpan(0, 60, 0)
        });
    }
}

Here's how I configured my UserId property:

protected int UserId {
    get {
        return Convert.ToInt32(base.User.Identity.GetUserId());
    }
}

Don't forget to decorate the class with [assembly: OwinStartupAttribute(typeof(namespace.StartupConfig))]. Hope this helps somebody.

Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126
  • "I did extend my base Controller with an extra property called UserId which parses the User property to get the actual Id being used in the database" -- you know, OWIN has an IIdentity extension method called GetUserId that gets this out of the user claims principal for you, no need for a base controller to do this... – danludwig Feb 09 '14 at 03:32
  • True, and I do use it, but it's easier for me to call `base.UserId` in a controller, pass it around as I need, than to constantly rewrite the code for casting the `User` into `ClaimsPrincipal` and calling the `GetUserId()` method wherever I might need it. Please look at my update above. – Gup3rSuR4c Feb 09 '14 at 03:35
  • You don't have to cast User to a ClaimsPrincipal. `User.Identity.GetUserId()` will work. The extension method is on IIdentity, so it is IPrincipal agnostic. I know what you mean about int casting though, we have a separate extension method for that. They should make that method generic... – danludwig Feb 09 '14 at 03:40
  • Welp, I learned something. I must have been pretty confused at the time when I was implementing OWIN (which I thought was a shot in the dark, but ended up working). I updated it to `return Convert.ToInt32(base.User.Identity.GetUserId());`. And, yeah, you're right, it should have been generic. I'm gonna keep the `UserId` property, for now. We'll see if it lasts or not, haven't gotten that far into the project to need it yet. Thanks for letting me know the cast was pointless. – Gup3rSuR4c Feb 09 '14 at 03:45
  • Not at all. If you had ReSharper, that would have caught it for you too. Try your best to not have a base controller sitting between your app and the MVC Controller, it ends up being a lot more trouble than it's worth, and almost always avoidable. – danludwig Feb 09 '14 at 04:01
  • Yeah, so far my base controller only has that one property on it. – Gup3rSuR4c Feb 09 '14 at 04:03
  • What does this have to do with the roles, alex? Are you just using the default role provider? – Isaac Bolinger Oct 18 '15 at 01:08
  • I'll be honest, I don't really remember much from when I was working on this. I think I did write a custom role provider as well, but it was probably being invoked by the Identity library silently... Sorry I can't be of more help. – Gup3rSuR4c Nov 07 '15 at 06:23
0

Did you remember to put your application name in your web config?

<roleManager enabled="true">
   <providers>
      <clear />
        <add connectionStringName="ApplicationServices" 
             name="AspNetSqlRoleProvider"       
             type="System.Web.Security.SqlRoleProvider" 
             applicationName="DONT FORGET THIS PART" />
    </providers>
</roleManager>       

Use one of the following in your controllers.

[Authorize] //Anyone with authorization
[Authorize(Roles="Administrator")] //Admin role only

You could also do something like this.

HttpContext.User.IsInRole("Administrator")
UserManager.IsInRole(userID, "Administrator")
stink
  • 865
  • 8
  • 19