2

I have an MVC 5 web app. Currently the application is using Individual Accounts to login. There are also roles in place for authorization. The users login using their username and password.

The problem is like this. I need to authenticate and authorize users requests that are coming via a reverse proxy.

enter image description here

  • User make's a request to for the app (reverse proxy url) http://myapp.domain.com
  • Reverse proxy will make additional calls and verify that the user is authorized to access the app content. (missing from diagram for simplicity).
  • If everything ok with the user the call is redirected to the actual MVC application where the request will contain a header with the username.
  • The MVC must check that the request is coming from the reverse proxy (not a problem to do that, IP check, plus some key sent as headers.)
  • MVC should read the request header, get the username, authenticate it and authorize it based on the role or roles he has.
  • Deny the request if the request doesn't come from the reverse proxy, deny the request if the user doesn't have appropriate roles. Example user is in role Visitor but he's trying to access admin role content.

My problem is in the authentication and authorization of the request when there is present just the username.

As the application uses already username and password for authentication, I'm thinking to do the following:

  • The reverse proxy will send the request to https://realapp.domain.com/account/login.
  • In the action login from account controller I can implement the logic to read the request and get the username from the header
  • At this point we know that user X is authenticated because the reverse proxy and additional systems will check that. So basically all requests arriving are considered safe (from the reverse proxy server)
    • If the username doesn't exists within the database (first time call to the application) the MVC app will create the user with a dummy password (Password123).
    • If the username exists within the database then log him in using the username and the dummy password Password123 var result = await SignInManager.PasswordSignInAsync("username", "Password123", false, shouldLockout: false);
  • User is authenticated and authorized.

Basically my idea is to set for each user same password in order to authenticate them within the application and make use of roles.

What do you think?

user2818430
  • 5,853
  • 21
  • 82
  • 148

1 Answers1

2

Since Identity is claim based. You don't need any password or even any user object to authenticate users. So using storage in Identity is totally optional also. You just need create some claims and authorize your users based on those. Consider this simple example as a clue:

// imaging this action is called by proxy
public ActionResoult Login()
{
    // this custom method extract username from header and check IP and more
    var username=_myUserManager.GetUserName();

    if(username!=null)         
    {

        // optionally you have own user manager which returns roles from username
        // no matter how you store users and roles
        string[] roles=_myUserManager.GetUserRoles(username);

        // user is valid, going to authenticate user for my App
        var ident = new ClaimsIdentity(
            new[] 
            {  
                // adding following 2 claim just for supporting default antiforgery provider
                new Claim(ClaimTypes.NameIdentifier, username),
                new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),

                // an optional claim you could omit this 
                new Claim(ClaimTypes.Name, username),

                // populate assigned user's role form your DB 
                // and add each one as a claim  
                new Claim(ClaimTypes.Role, roles[0]),
                new Claim(ClaimTypes.Role, roles[1]),
                // and so on
            },
            DefaultAuthenticationTypes.ApplicationCookie);

        // Identity is sign in user based on claim don't matter 
        // how you generated it             
        HttpContext.GetOwinContext().Authentication.SignIn(
            new AuthenticationProperties { IsPersistent = false }, ident);

        // auth is succeed, without needing any password just claim based 
        return RedirectToAction("MyAction"); 
    }
    // invalid user        
    ModelState.AddModelError("", "We could not authorize you :(");
    return View();
}

Now we authorized our users without any password so we could use Authorize filter as well:

[Authorize]
public ActionResult Foo()
{
}

// since we injected user roles to Identity we could do this as well
[Authorize(Roles="admin")]
public ActionResult Foo()
{
    // since we injected our authentication mechanism to Identity pipeline 
    // we have access current user principal by calling also
    // HttpContext.User
}

Note: Your proxy must handle your apps generated cookies and deliver them to your users properly. Since your app based on cookie.

You could download Token Based Authentication Sample from my Github repo and also read my other answer which is closes to your scenario.

Community
  • 1
  • 1
Sam FarajpourGhamari
  • 14,601
  • 4
  • 52
  • 56
  • Thanks, sounds good. However one thing, The proxy doesn't deliver's anything to the MVC app, after makes the authentication of the logged in user (windows auth), the proxy will just make a call/redirect the user to the app, and add's the username as a header. That's it. It doesn't provides any cookie so ever. So now the MVC app has a valid/authenticated user. It must log him in, set the cookie and assign the right roles.... when cookie/session expires, normally an MVC app will redirect you to Accoun/Login instead now you are redirected to the proxy and the cycle repeats. – user2818430 Sep 02 '15 at 20:29
  • 1
    If it is just a simple redirect with additional header. Everything works great. We don't need any additional thing from proxy. Identity takes care of making cookies. I said if user **always** behind the proxy then the proxy server must deliver our generated cookies to user. – Sam FarajpourGhamari Sep 02 '15 at 20:38