Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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 web apps as well.

All the documentation for MVC 5 Authentication, which I believe is all based on OWIN stuff, have it "baked" into a single web app using EF Code First no less.

What I am trying is to have an another Web App that I strip everything out of except for the Account stuff and then try to "point" my web apps Authentication to that and have it return a "token", I'm guessing, of my Authenticated User and his/her "Roles".

Am I on the right track? Am I WAY over complicating this? I'm new to Web Development but this seems like a fairly reasonable and straightforward request. Dumbfounded that I can't find it anywhere.

share|improve this question
    
Are you looking for single place of authentication for multiple webapps? –  jd4u Nov 6 '13 at 15:35
    
Yes, an internal one that works with MVC 5. –  Refracted Paladin Nov 6 '13 at 15:37
    
you want to use ASP.NET Forms Authentication? OWIN Forms Authentication is good to implement in new apps. Review blogs.msdn.com/b/webdev/archive/2013/07/03/… –  jd4u Nov 6 '13 at 15:41
    
No, I want to use OWIN Forms Authentication but I don't know how to do what I need... –  Refracted Paladin Nov 6 '13 at 15:44
    
Are you looking for a single sign on solution for all you web applications, or are you simply asking for a shared authentication assembly that you can reuse in all your applications? –  Olav Nybø Nov 6 '13 at 20:26
show 1 more comment

4 Answers

up vote 4 down vote accepted
+150

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.

share|improve this answer
    
So I would implement IdentityAuthenticationManager in a web-api service and then call in with your second example? Thanks for the help, just trying to get the Architecture/Structure correct. –  Refracted Paladin Nov 7 '13 at 19:33
    
Yes. Follow that. This is the right way that you can work with OWIN. –  AmirHossein Mehrvarzi Nov 7 '13 at 19:48
    
I'll give it a try. I understand the concept but am a little foggy with implementation. Where would I find examples of the various virtual methods for the service? –  Refracted Paladin Nov 7 '13 at 19:59
    
I just putted that at the end of answer. –  AmirHossein Mehrvarzi Nov 7 '13 at 20:04
    
Awesome, thanks. I'll look at this in detail today. Very much appreciate your time! –  Refracted Paladin Nov 7 '13 at 20:42
show 6 more comments

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

share|improve this answer
    
Thanks, I will try and wrap my head around this. Would I put this in a seperate web-api service for reuse from my WebApps? –  Refracted Paladin Nov 7 '13 at 20:44
add comment

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.)
share|improve this answer
    
And the oAuth Server would pass back the User Token? –  Refracted Paladin Nov 6 '13 at 16:29
    
Yes, like the Facebook, Google, Twitter. You need to implement your own features. –  jd4u Nov 6 '13 at 16:39
    
Alright, I'll look into it. I can't understand why I can't simply have a "Authentication" MVC project that I add to each WebApp Solution and simply change my Login/Register type routes to point to it... –  Refracted Paladin Nov 6 '13 at 16:44
    
are you looking to reuse the same code? –  jd4u Nov 6 '13 at 16:50
    
if so, the above is not required at all –  jd4u Nov 6 '13 at 16:50
show 2 more comments

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.

share|improve this answer
    
So what would my web-api do? Would I need recreate all the methods generated by Identity Framework in the WebAPI? So CreateUserAsync and FindUserByID() etc...? –  Refracted Paladin Nov 7 '13 at 15:17
    
You would expose the identity framework through the web service and in that way authentication and authorization would be independent of the web sites that consume the service. –  Mike Beeler Nov 7 '13 at 15:33
    
If the requirement is just to authenticate with user tables in a database a web API service would implement the methods to login and is valid for username and password pairs. More is required if users can self help for password changes. If support is needed for other apps that already support oauth, this is much easier than identity federation –  Mike Beeler Nov 7 '13 at 18:10
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.