Setting up Forms Authentication for multiple Web Apps in MVC 5 based on OWIN

那年仲夏 提交于 2019-12-03 04:42:37

Work with new OWIN Identity API that wraps everything that you need to work with Application and External sign in cookies like bellow:

public class IdentityAuthenticationManager
{
    public IdentityAuthenticationManager();
    public IdentityAuthenticationManager(IdentityStoreManager storeManager);

    public string ClaimsIssuer { get; set; }
    public string RoleClaimType { get; set; }
    public IdentityStoreManager StoreManager { get; set; }
    public string UserIdClaimType { get; set; }
    public string UserNameClaimType { get; set; }

    public virtual void Challenge(HttpContextBase context, string authenticationType, string redirectUrl);
    public virtual Task<bool> CheckPasswordAndSignIn(HttpContextBase context, string userName, string password, bool isPersistent);
    public virtual Task<bool> CreateAndSignInExternalUser(HttpContextBase context, string loginProvider, IUser user);
    public virtual IEnumerable<Microsoft.Owin.Security.AuthenticationDescription> GetExternalAuthenticationTypes(HttpContextBase context);
    public virtual Task<ClaimsIdentity> GetExternalIdentity(HttpContextBase context);
    public virtual Task<IList<Claim>> GetUserIdentityClaims(string userId, IEnumerable<Claim> claims);
    public virtual Task<bool> LinkExternalIdentity(ClaimsIdentity id, string userId, string loginProvider);
    public virtual Task SignIn(HttpContextBase context, string userId, bool isPersistent);
    public virtual Task SignIn(HttpContextBase context, string userId, IEnumerable<Claim> claims, bool isPersistent);
    public virtual Task<bool> SignInExternalIdentity(HttpContextBase context, ClaimsIdentity id, string loginProvider);
    public virtual void SignOut(HttpContextBase context);
    public virtual bool VerifyExternalIdentity(ClaimsIdentity id, string loginProvider);
}

And The following shows the login code for the ASP.NET MVC template:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        // Validate the user password
        if (await AuthenticationManager.CheckPasswordAndSignIn(HttpContext, model.UserName, model.Password, model.RememberMe))
        {
            return RedirectToLocal(returnUrl);
        }
    }

    // If we got this far, something failed, redisplay form
    ModelState.AddModelError("", "The user name or password provided is incorrect.");
    return View(model);
}

For more information visit this.

Detailed explanation I was searching for a way to use OWIN istead of FormsAuthentication, but without all that usermanager, userstore stuff. I suppose you want the same.

In your Login Action check for user credentials in DB with your own code and if user is correct then create Claims with desired info and call AuthenticationManager.SignIn with those Claims:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
    ,new Claim(ClaimTypes.Name, user.UserName)
    ,new Claim(ClaimTypes.Email, user.Email)
};
var identity = new ClaimsIdentity(claims,
                            DefaultAuthenticationTypes.ApplicationCookie);

HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

Now you are logged in just like FormsAuthentication.SetAuthCookie method.

Now you can get User info through claims:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (filterContext.HttpContext.User.Identity.IsAuthenticated)
    {
        var ctx = filterContext.HttpContext.Request.GetOwinContext();
        var identity = (ClaimsPrincipal)filterContext.HttpContext.User;
        var enumerable = identity.Claims as IList<Claim> ?? identity.Claims.ToList();
        var username = enumerable.Where(x => x.Type == ClaimTypes.Name).Select(x => x.Value).FirstOrDefault();
        var userId = enumerable.Where(x => x.Type == ClaimTypes.NameIdentifier).Select(x => x.Value).FirstOrDefault();

    }
    base.OnActionExecuting(filterContext);
}

You have it under your control, instead of all the EF Code fist stuff that comes with MVC template

Single place of authentication for multiple webapps, can be added with many different approach. To start, here are two.

  1. Using the OWIN framework's OAuthAuthorizationServerProvider: Create one application as a oAuth Server. Setup others to redirect to your oAuth Server for authentication.
  2. Using Identity Federation approach: Look into Windows Identity Federation. (Thinktecture IdentityServer V2 is an easy to implement Security Token Service. IdentityServerV2 has many feature apart from being STS.)

If all you are looking for is a common authentication scheme where a user is authenticated by a common database for example, implement an asp.net MVC web service. In this way each web site can consume your authentication service and would be hosted and managed by IIS. Info about web API can be found here http://www.asp.net/web-api/overview. Service is deployed to the web server with the standard publish deeply model in visual studio.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!