1

I'm cobbling together snippets of code from blogs and different places to try to get this to work. Normally, I'd refer to the reference documentation, but I can't find it here or anywhere else. It's just videos and demos for specific use cases that include user management or facebook or twitter.

I have a proprietary authentication service that I'm using. User accounts are not managed inside my application. So I need to be able to sign in a user that's completely constructed at run time.

Here's what I'm trying now in my MVC app.

using System.Security.Claims;

public class HomeController : Controller {
    public ActionResult Scratch() {
        var claims = new Claim[] {
            new Claim(ClaimTypes.Name, "somename"),
            new Claim(ClaimTypes.NameIdentifier, "someidentifier"),
            new Claim("foo", "bar"),
        };

        var identity = new ClaimsIdentity(claims);

        var authenticationManager = HttpContext.GetOwinContext().Authentication;
        authenticationManager.SignIn(identity);

        return Content(
            $"authentication manager type: {authenticationManager.GetType()} \n"
            + $"authenticated: {HttpContext.User.Identity.IsAuthenticated} \n"
            + $"user name: {HttpContext.User.Identity.Name} \n",
            "text/plain");
    }
}

The output is

authentication manager type: Microsoft.Owin.Security.AuthenticationManager 
authenticated: False 
user name:  

Questions:

  1. Why does the output show that the user has not been authenticated? What more do I have to do to get this user authenticated?
  2. Where is the documentation for this framework?

Update

Startup.cs

public partial class Startup {
    public void Configuration(IAppBuilder app) {
        ConfigureAuth(app);
        ConfigureAnalyticContext(app);
    }
}

Startup.Auth.cs:

(there is actually much more, but all the rest has been commented out, in search of finding a minimal configuration that works)

public partial class Startup {
    public void ConfigureAuth(IAppBuilder app) {
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    }
}

AnalyticContext.Auth.cs

(this is my Entity Framework context, I doubt it's related to this problem)

public partial class Startup {
    public void ConfigureAnalyticContext(IAppBuilder app) {
        app.CreatePerOwinContext(() => CentoAnalyticsContext.Create());
    }
}
recursive
  • 83,943
  • 34
  • 151
  • 241
  • Are you sure the user has not been authenticated? you are getting `HttpContext.User.Identity.IsAuthenticated`, maybe you should refresh the page and call it again. See if some cookie was created. Show your AuthConfig.cs / Startup.cs – Fabio Sep 24 '15 at 00:45
  • For the first question: yes, I'm sure. I've reloaded this page many times, and nothing changes. I'll investigate the cookie creation and getting those files. – recursive Sep 24 '15 at 00:46
  • @FabioLuz: I've added the contents of those files to the question. – recursive Sep 24 '15 at 00:55

3 Answers3

5

Well, it seems that you are not using ASP.NET Identity. ASP.NET Identity is new membership system of asp.net, which automatically creates database tables for storing users, encrypting password, etc.

What you are trying to do is to use the new authentication system provided by OWIN, which replaces the old FormsAuthentication style.

To make it work, you have to create the cookie authentication. Like this:

public static class AuthConfig
{
    public const string DefaultAuthType = "DefaultAppCookie";
    public const string LoginPath = "/System/SignIn";

    public static void ConfigureAuth(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthType,
            LoginPath = new PathString(LoginPath)
        });

        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; //or whatever

    }
}

In the login action:

var claims = new Claim[] {
        new Claim(ClaimTypes.Name, "somename"),
        new Claim(ClaimTypes.NameIdentifier, "someidentifier"),
        new Claim("foo", "bar"),
};

ClaimsIdentity identity = new ClaimsIdentity(claims, AuthConfig.DefaultAuthType);
IAuthenticationManager authManager = Request.GetOwinContext().Authentication;

authManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, identity);

I think that should be enough to make it work in your app. A few days ago I answered a similar question MVC Authentication - Easiest Way, take a look, it might be helpful.

Community
  • 1
  • 1
Fabio
  • 11,892
  • 1
  • 25
  • 41
  • Thank you so much! I will give this a try tomorrow. How do you go about learning this? Is there a book? Documentation i just missed? – recursive Sep 24 '15 at 01:14
  • To be honest, I don't know. I tried to find some documentation, with no success. So, I've been trying to make it work from the scratch, using intellisense and template projects from visual studio. After a lot of frustration, I finally did it. – Fabio Sep 24 '15 at 01:19
  • @recursive - The project web site has many great resources for starting out, see: http://www.asp.net/identity – Igor Sep 24 '15 at 17:47
  • @Igor: I mentioned that url in my question. It seems to have many demos and walkthroughs, but no authoritative reference documentation. If none of their walkthroughs address your particular requirements, there's no resource to find out how to compose your own solution with the given components. – recursive Sep 24 '15 at 17:53
  • @FabioLuz: It does not appear to be working. I still see no cookie set int the response header. I will try to reproduce this in a blank mvc app to see if something in my configuration is interacting. – recursive Sep 24 '15 at 19:02
  • That is strange. It should be working fine. Maybe we are missing soething... Take a look at this thread http://stackoverflow.com/questions/32095889/mvc-authentication-easiest-way Try to reproduce the steps from the scratch – Fabio Sep 24 '15 at 19:22
  • I've spent all day on this. I've crawled through the code of Identity Framework (which was actually irrelevant as you say), Owin, MS Owin (katana), System.Web.Mvc, Microsoft.Web.Mvc, and probably others. In the end, I realized that I forgot to specify the second parameter to the `ClaimsIdentity` constructor as you specified. But at least now, I know exactly why that matters! – recursive Sep 25 '15 at 01:40
2

I recently have added Active Directory authentication, constructed ClaimsPrincipal myself and signed-in the same way you do.

And you are indeed missing .UseCookieAuthentication in your ConfigureAuth(IAppBuilder app)

    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "MyAuthenticationName", // <-- this must match the AuthenticatioType name when you do sign-out
            LoginPath = new PathString("/MyLoginPath"),
            CookieName = "MyCookieName",
            CookieHttpOnly = true,
        });
    }

And you don't need UseExternalSignInCookie.

trailmax
  • 34,305
  • 22
  • 140
  • 234
1

Request.IsAuthenticated will be false with in the same request flow.

I think you still need to update the current security principal if you need to check IsAuthenticated for the request as authenticationManager.SignIn only validates the user against data store and sets the OWIN cookie which when sent back in subsequent request sets the security principal , usually a redirect takes care of this as in most cases there will be redirection in home page or something. If you still need to check with in the same request you can do something like below depending on your requirement

var claims = new Claim[] {
        new Claim(ClaimTypes.Name, "somename"),
        new Claim(ClaimTypes.NameIdentifier, "someidentifier"),
        new Claim("foo", "bar"),
    };


var identity = new ClaimsIdentity(claims,DefaultAuthenticationTypes.ApplicationCookie,
          ClaimTypes.Name, ClaimTypes.Role);

var principal = new ClaimsPrincipal(identity);

System.Threading.Thread.CurrentPrincipal = principal;
if (System.Web.HttpContext.Current != null)
    System.Web.HttpContext.Current.User = principal;

Hope this helps.

Ravi A.
  • 2,163
  • 2
  • 18
  • 26
  • On subsequent requests, `Request.IsAuthenticated` is still false. I can reload this many times, and it never changes. In fact, I can see that no cookie is being set in the HTTP response header. – recursive Sep 24 '15 at 17:47