0

I have ASP.NET MVC app with custom Authentication server. When user wants to log in, app popups window, and when he is done, token returns, and app then logs in user via WebApi,

var cl = from d in (this.User.Identity as ClaimsIdentity).Claims
         select new Claim(d.Type, d.Value);
var identity = new ClaimsIdentity(cl, "ApplicationCookie");
AuthenticationManager.SignIn(identity);
var name = cl.FirstOrDefault(x => x.Type.ToLower() == "login").Value;
Thread.CurrentPrincipal = new TaiAuthPrincipal(identity);
System.Web.Security.FormsAuthentication.SetAuthCookie(name, true);

and on every request - WebApi knows who is user, mean User.Identity is defined; But in MVC views, it's always null and none of this execute

<div class="headerPane">
    @{
        if (User.Identity.IsAuthenticated)
        {
            @Html.Partial("HeaderPartialView")
        }
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            @Html.Partial("HeaderPartialView")
        }
        if (System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated)
        {
            @Html.Partial("HeaderPartialView")
        }
    }
</div>

How to authenticate user from web api to mvc? App based on angularjs on front, so all authorization stuff is done on frontend, via webapi requests. So mvc simply doesnt know anything.

For the sake of fullness, this is TaiAuthPrincipal, there is nothing special indeed

public class TaiAuthPrincipal : IPrincipal
    {
        private IIdentity identity;
        public IIdentity Identity
        {
            get { return identity; }
        }

        public bool IsInRole(string role)
        {
            var _role = (this.Identity as ClaimsIdentity).Claims.FirstOrDefault(x => x.Type.ToLower().Contains("GroupName".ToLower()));
            return _role == null ? false : true;
        }
        public TaiAuthPrincipal(IIdentity _identity)
        {
            this.identity = _identity;
        }
        public TaiAuthPrincipal(ClaimsIdentity _identity)
        {
            this.identity = _identity as IIdentity;
        }
    }

Global.asax

void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
        {
            if (HttpContext.Current.Request.Url.AbsolutePath.StartsWith("/api/"))
            {
                System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
            }
        }

Startup.cs

public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
            app.UseOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions());
        }
    }
trailmax
  • 34,305
  • 22
  • 140
  • 234
Medet Tleukabiluly
  • 11,662
  • 3
  • 34
  • 69

1 Answers1

1

If you are making Web Api in same project of MVC appliation then your way to authenticate your web request is totally wrong. What happens is when you request your view by calling an action then your mvc project expects an authenticated request so what you need to do is save your accesstoken in a cookie on clientside and send it to server with every request and identify user from that token and set the IPrincipal. Go through this answer it will help you

ASP.NET MVC - Set custom IIdentity or IPrincipal

Your code will look like this

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        JavaScriptSerializer serializer = new JavaScriptSerializer();

        CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);

        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.Id = serializeModel.Id;
        newUser.FirstName = serializeModel.FirstName;
        newUser.LastName = serializeModel.LastName;

        HttpContext.Current.User = newUser;
    }
}
Community
  • 1
  • 1
Ankush Jain
  • 5,654
  • 4
  • 32
  • 57
  • But all UserData is stored in Claims, not cookies. So can't be deserialized – Medet Tleukabiluly Feb 09 '15 at 06:12
  • 1
    you can store your claim data in authentication cookie. http://stackoverflow.com/questions/1149996/storing-more-information-using-formsauthentication-setauthcookie – Ankush Jain Feb 09 '15 at 06:24
  • Ok, i got that. Placed all my claims inside AuthCookie, but JavaScript Deserializer throws Exception("Cannot deserialize Claims, cyclic reference") – Medet Tleukabiluly Feb 09 '15 at 08:18
  • 1
    search on Google for that. I am sure you will definitely get a solution for circular reference error in your context. – Ankush Jain Feb 09 '15 at 08:31
  • Currently ingored Claims field from serializing, but MVC identity still null, althought authorization passes. Maybe problem in something else? – Medet Tleukabiluly Feb 09 '15 at 09:24
  • 1
    This article may help you. http://www.codeproject.com/Articles/5353/Custom-Authentication-provider-by-implementing-IHt – Ankush Jain Feb 09 '15 at 09:35