I am in process of setting up my 1st MVC Web App. I know I need to provide a Forms Based Authentication model as well as I know I will be reusing it for multiple other internal
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.
Single place of authentication for multiple webapps, can be added with many different approach. To start, here are two.
OAuthAuthorizationServerProvider
: Create one application as a oAuth Server. Setup others to redirect to your oAuth Server for authentication. 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.
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