I have an issue with Identity and I am not very familiar with it. Not too long ago I started a new project that was originally not meant to have any authentication attached to it. However, as the project grew we found that we should implement it. Since it wasn't originally set up that way I created a form for a login.
I found the answer to this question and implemented it:
How to implement custom authentication in ASP.NET MVC 5
However it is not working and I do not know why.
Here's my code:
Nothing much to see here it's just a plain form.
@{
ViewBag.Title = "Login";
}
<div class="container">
<h2>Login</h2>
<br />
@using (Html.BeginForm("Login", "Main"))
{
<div class="row">
<div class="form-group col-xs-6">
@Html.Label("Username", htmlAttributes: new { @class = "control-label col-sm-3" })
<div class="col-sm-8">
@Html.TextBox("username", null, new { @class = "form-control" })
@*Html.ValidationMessageFor(model => model.EnrollmentOption, "", new { @class = "text-danger" })*@
</div>
</div>
<div class="form-group col-xs-6">
</div>
</div>
<div class="row">
<div class="form-group col-xs-6">
@Html.Label("Password", htmlAttributes: new { @class = "control-label col-sm-3" })
<div class="col-sm-8">
@Html.Password("password", null, new { @class = "form-control" })
@*Html.ValidationMessageFor(model => model.EffectiveDate, "", new { @class = "text-danger" })*@
</div>
</div>
<div class="form-group col-xs-6">
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-md-offset-6 col-sm-5">
<input type="submit" id="login" value="Sign in" class="btn btn-primary" />
</div>
</div>
</div>
}
The action implemented for it is this one, this matters much more:
[HttpPost]
public ActionResult Login(string username, string password)
{
if (isLoginValid(username, password))
{
var ident = new ClaimsIdentity(
new[] {
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, username),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
new Claim(ClaimTypes.Name,username),
// No roles needed for now...
},
DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
return RedirectToAction("QuoteSearch"); // auth succeed
}
else
{
// invalid username or password
ModelState.AddModelError("", "Invalid username or password");
return View();
}
}
And there's the isLoginValid function (For now it's set to use a hardcoded login)
[NonAction]
private bool isLoginValid(string user, string password)
{
return (user.ToLower() == "someUser" && password.ToLower() == "myPassword");
}
I do not know very much of claims or how Identity works underneath. I did make sure of adding all the necessary references though. When using the authorize attribute on my actions after the login redirects I get an unauthorized request from IIS. Is there something wrong with my code?
What should I change or fix to be able to use the Authorization part of Identity?
Thanks,
After much debugging and thanks to @Carlos for the elaborate answer. If your project is created with "No Authentication" you will need to add the missing Nuget packages that the Authentication requires.
You need to install the following
After some troubleshooting and thanks to guysherman's comment I was able to find the solution. Since I had created the solution with no authentication in mind I removed the includes of references and necessary OWIN configuration code in my App_Start folder.
Because of this, nothing in Identity was defined and nothing from the authorization part occurred despite the fact that the login was working perfectly. By creating a new project and adding all the needed code to configure Identity, I was able to use the Authorize attribute properly. without any problems whatsoever.
(This answer applies for ASP.NET 4.6, I suppose this is handled differently for ASP.NET Core)
UPDATE:
To make this answer better I thought I should elaborate more into what I did to make it work.
When creating a new project with identity you will see that there are several files that aren't created if you choose to not add it, you will need those, most of them are stored in App_Start.
I copied the files I did not have and changed the namespaces to match my actual project. Once doing that it was made apparent which nuget packages I was missing, so I added the ones I hadn't yet added.
Startup.Auth.cs will have the definition for a key function for identity to work:
ConfigureAuth
This function must be called in the startup class. in the configuration method.
Finally, for everything to work, you must also include the file IdentityModel.cs that is created normally inside the Models folder. In my case, I placed all models in a different project, so I placed the class there and added references on IdentityConfig.cs so that the class would recognize that the IdentityModel exists.
And that was all. In my case I had a lot of problems with identity trying to connect to the db to look for users, since Identity didn't have a database configured, my app started crashing due to failed db connections. Removing the lines marked with red in the third image made it work for me. I did not want identity's db connection since I have my own user handling, this might not be someone else's case.