Search code examples
authenticationasp.net-web-apiasp.net-web-api-helppagesasp.net-mvc-5

Put the Web Api Documentation behind a login page so that only valid user can browse the Web Api help documentation


We have created a web api project in which we have used Basic authentication for time being. We have used the nuget package to generate the Web Api help documentation, so it has added new area, controller and views for Web Api Help. We have hosted the web api on IIS. Right Now, any one can browse the Web Api help just by browsing the Web Api url "http://localhost/WebApi/Help". We want to authenticate the help pages (which are implemented in MVC). The question here is my web api uses basic authentication and I want to create a mechanism so that web api help will be authenticated before any request for Web Api help page.

To achieve this, I have created an "AccountController", "Login" page. I have also created an authentication filter and decorated the "HelpController" (which has all the actions for rendering help pages). Login Page Code:

public ActionResult Login(LoginViewModel model)
{
    bool isValidated = //Code for validating the users
    if (ModelState.IsValid && isValidated)
    {
      var identity = new HelpAuthenticationIdentity(model.UserName, model.Password);
      var principal = new WindowsPrincipal(identity);
      ControllerContext.HttpContext.User = principal;

      return RedirectToAction("Index", "Help", new { area = "HelpPage" });
    }
    else
      return View();
}

I have created a class for identity which inherits WindowsIdentity class

public class HelpAuthenticationIdentity : WindowsIdentity
{
  public HelpAuthenticationIdentity(string userName, string password)
        : base(userName, "Basic")
  {
     this.Password = password;         
  }
  public string Password { get; set; }
}

When I click on login after entering the valid credentials, it will be redirected to Index action of Help controller. As I have the authentication filter it will first call the "OnAuthentication" method. Here it is always getting the "context.HttpContext.User.Identity.IsAuthenticated" flag as false. The authentication filter attribute is as follows:

/// <summary>
/// Authentication filter to authenticate the request for Web Api Help
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class HelpAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext context)
    {
        if (!context.HttpContext.User.Identity.IsAuthenticated)
        {
            context.Result = new HttpUnauthorizedResult();
        }
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext context)
    {
        if(context.Result == null || context.Result is HttpUnauthorizedResult)
        {
            context.Result = new RedirectToRouteResult("Login",
                new System.Web.Routing.RouteValueDictionary{
                    {"controller", "Account"},
                    {"action", "Login"}
                });
        }
    }
}

Please provide your inputs.


Solution

  • The issue is resolved. I have modified my login action:

    [HttpPost]
    public ActionResult Login(LoginViewModel model)
    {
        bool isValidated = //Code for validating the users
        if (ModelState.IsValid && isValidated)
        {
            //Set the authentication cookie for the logged in user.
            FormsAuthentication.SetAuthCookie(model.UserName, true);
            return RedirectToAction("Index", "Help", new { area = "HelpPage" });
        }
        else
        {
            return View();
        }                
    }
    

    I have implemented "Application_AuthenticateRequest" method in Global.asax.cs

    protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        try
        {
            if (Context.Request.Cookies[".ASPXAUTH"] != null)
            {
                var authCookie = FormsAuthentication.Decrypt(Context.Request.Cookies[".ASPXAUTH"].Value);
                var identity = new GenericIdentity(authCookie.Name);
                Context.User = new GenericPrincipal(identity, null);
            }
            else
            {
                Context.User = null;
            }
        }
        catch(Exception ex)
        {
            Context.User = null;
        }
    }
    

    After entering valid credentials, the user is authenticated an It will be redirected to help page.