I have found many threads discussing this problem but getting any of them to work has eluded me so far.
I have been trying to follow ProDinner as a way of learning how to implement role based authentication in my app. But I cannot work out what I am missing. Every time I try to log in I get
No owin.Environment item was found in the context
After a lot of debugging and searching I have found the Startup
class is not being called. I've tried to resolve by stepping through the proDinner code to see, how Startup
is being called and googled (a lot!). My searches lead me to adding (although neither exist in the proDinner project)
<add key="owin:AutomaticAppStartup" value="Tjs.Startup, Tjs" />
then
<add key="owin:AutomaticAppStartup" value="Tjs.Web.Admin.Startup, Tjs" />
Below I have added all of what I believe is the relevant code, but please let me know if I am missing anything.
The AccountController is a copy paste of ProDinner, with the addition of a parameterless constructor, I was unable to work out how that parameter is being passed in the Prodinner project (could that be the problem?)
Tjs: solution name
Tjs.Web.Admin: namespace
Owin packages
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Security.Cookies" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net45" />
root of project
using Microsoft.Owin;
using Owin;
using Tjs.Web.Admin;
using Tjs.Web.Admin.App_Start;
[assembly: OwinStartup(typeof(Startup))]
namespace Tjs.Web.Admin
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
OwinConfig.ConfigureAuth(app);
}
}
}
App_Start
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
namespace Tjs.Web.Admin.App_Start
{
public static class OwinConfig
{
public static void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/SignIn")
});
}
}
}
AccountController
private readonly IUserService userService;
public AccountController()
{
}
public AccountController(IUserService userService)
{
this.userService = userService;
}
private IAuthenticationManager Authentication
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
private void SignInOwin(string name, bool rememberMe, string role)
{
var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, name) },
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name, ClaimTypes.Role);
//foreach (var role in roles)
//{
// identity.AddClaim(new Claim(ClaimTypes.Role, role));
//}
identity.AddClaim(new Claim(ClaimTypes.Role, role));
Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = rememberMe
}, identity);
}
public ActionResult SignIn()
{
return View(new SignIn { Email = "o", Password = "1" });
}
[HttpPost]
public ActionResult SignIn(SignIn input)
{
if (!ModelState.IsValid)
{
input.Password = null;
input.Email = null;
return View(input);
}
Staff staff;
//ACHTUNG: remove this in a real app
if (input.Email == "o" && input.Password == "1")
{
staff = new Staff { Email = "o", Role = new Role { Description = "admin" } };
}
else
{
staff = userService.Get(input.Email, input.Password);
}
if (staff == null)
{
ModelState.AddModelError("", "Try Login: o and Password: 1");
return View();
}
SignInOwin(staff.Email, input.Remember, staff.Role.Description);
return RedirectToAction("index", "home");
}
public ActionResult SignOff()
{
Authentication.SignOut();
return RedirectToAction("SignIn", "Account");
}
}
it fails at
private IAuthenticationManager Authentication
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}