I'm trying to implement a single-page app. I carried over some of my working code from another project (MVC4) to implement authentication. Right now I see cookies being set, but WebSecurity
/ User.Identity
do not seem to be working for some reason. After logging in, subsequent requests never validate as authenticated, either via WebSecurity.IsAuthenticated
, or User.Identity.IsAuthenticated
. Does anyone know why this is happening?
Controller code:
public class AccountController : ApiController {
private readonly UserService _userService;
public AccountController() {}
public AccountController(UserService userService) {
_userService = userService;
}
[AllowAnonymous]
[HttpGet]
[Route("api/authpayload")]
// This gets called when the app loads. Always, User.Identity.IsAuthenticated is false.
public HttpResponseMessage AuthPayload() {
var payload = new AuthPayloadDto();
try {
var userId = WebSecurity.GetUserId(User.Identity.Name);
if (User.Identity.IsAuthenticated && userId > 0) {
payload.Username = User.Identity.Name;
} else {
LogOut();
payload.IsAuthenticated = false;
}
return Request.CreateResponse(HttpStatusCode.OK, payload);
} catch (Exception e) {
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
[HttpPost]
[Route("api/login")]
[AllowAnonymous]
public HttpResponseMessage LogIn(LoginModel model) {
if (!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
try {
if (WebSecurity.IsAuthenticated)
return Request.CreateResponse(HttpStatusCode.Conflict, "already logged in.");
if (!WebSecurity.UserExists(model.Username))
return Request.CreateResponse(HttpStatusCode.Conflict, "User does not exist.");
if (WebSecurity.Login(model.Username, model.Password, persistCookie: model.RememberMe)) {
// This code always gets hit when I log in, no problems. I see a new cookie get sent down as well, using Chrome debugger.
var payload = new AuthPayloadDto();
return Request.CreateResponse(HttpStatusCode.OK, payload);
}
LogOut();
return Request.CreateResponse(HttpStatusCode.Forbidden, "Login Failed.");
} catch (Exception e) {
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
Web.config:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/" timeout="2880" />
</authentication>
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear />
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
</system.web>
The cookie that gets sent after login is not expired, and it does get sent back on subsequent requests, but IsAuthenticated
is always false. What am I doing wrong?
Update:
I updated my web.config to the following to get everything working:
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear />
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
But I'd like to leave this open in case anyone has an explanation of why this works; I'm pretty lost.