10

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,

Community
  • 1
  • 1
Carlos Jimenez Bermudez
  • 1,070
  • 1
  • 14
  • 36
  • If there are dislikes it would be good to know why, please at least leave a comment. – Carlos Jimenez Bermudez Jun 24 '16 at 15:49
  • 2
    Check your Startup.cs file, you should have a call to services.AddIdentity(...) in the ConfigureServices method, and similarly in the Configure method there should be a call to app.UseIdentity(...). My suggestion is to generate the sample app with authentication and compare with what you have. But it seems likely you don't have the services injected. – guysherman Jun 24 '16 at 15:58
  • @guysherman That is for ASP.Net Core, not for MVC5 which is what this question is about. – DavidG Jun 24 '16 at 16:06
  • Nonetheless, checking I noticed that I am missing a few OWIN configuration files that I suppose are necessary for Identity to work well. – Carlos Jimenez Bermudez Jun 24 '16 at 16:11
  • @DavidG in that case the file is Startup.Auth.cs in App_Startup, and it is probably OWIN calls that are missing. – guysherman Jun 24 '16 at 16:13
  • @guysherman - good advice on troubleshooting, then compare packages.config files... – SRQ Coder Jun 24 '16 at 16:16
  • How would your `isLoginValid` method *ever* under *any* circumstances return `true`?? `return (user.ToLower() == "someUser" && password.ToLower() == "myPassword");` -- A lowecase string can't be equal to a string with uppercase characters in it! – BrainSlugs83 Apr 06 '17 at 20:47
  • Good point, I should mention I modified the original strings to not have the real credentials hard coded credentials here since anyone can see them and the app is live... – Carlos Jimenez Bermudez Apr 13 '17 at 21:10

2 Answers2

6

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.

App_Start for a normal ASP.NET Project

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.

enter image description here

enter image description here

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.

enter image description here

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.

Carlos Jimenez Bermudez
  • 1,070
  • 1
  • 14
  • 36
  • 2
    FWIW, in situations like this, the best thing to do is to simply create a new project *with* individual auth, and then copy over the code you need into your application. That way, you don't miss things like this. It's very difficult to set up something like Identity correctly without a reference project. – Chris Pratt Jun 24 '16 at 17:22
  • 1
    That's what I ended up doing in the end, perhaps I should clarify that in my answer. – Carlos Jimenez Bermudez Jun 24 '16 at 17:24
1

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

Microsoft.AspNet.Identity
Microsoft.AspNet.Identity.EntityFramework
Microsoft.AspNet.Identity.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.Security
elfico
  • 450
  • 1
  • 6
  • 13