Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get whether user is authenticated by custom Action Filter in ASP.NET MVC View?

Tags:

c#

asp.net

I have an action method that uses my authentication filter:

public class TutorAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var req = filterContext.HttpContext.Request;
        var auth = req.Headers["Authorization"];
        if (!string.IsNullOrEmpty(auth))
        {
            var cred = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
            var user = new { Name = cred[0], Password = cred[1] };
            if (userService.AuthorizeTutor(user.Name, user.Password))
            {
                return;
            }
        }
        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", $"Basic realm= {BasicRealm}");

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

I would like to then display on main page something for user that have been authenticated this way, but this does not work in my View :(

@if (Request.IsAuthenticated)
{
    <h1>Hello</h1>
}

I know it does not work because I don't use Identity, but is there any way that I can do this?

Thank you for answers :)

like image 609
MacakM Avatar asked Dec 23 '16 20:12

MacakM


3 Answers

I suppose, that sending login and password in header is not secure. Better solution is one time when user is verified. And after checking, you can check all request.

For example, if you use FormsAuthentication and authCookie it's very simple:

  1. Set auth mentod in web.config: <authentication mode="Forms" />

  2. When login and password is valid, use FormsAuthentication.SetAuthCookie(userName, createPersistentCookie = true); This step is performed only once, when user login to application.

  3. Then you can use property this.Request.IsAuthenticated in view or HttpContext.Current.Request.IsAuthenticated in controller (or filter).

  4. And it works attribute [Authorize] on conntrolers or actions (public methods in conntrollers). When request is not authenticated, request is redirected to default (or set in web.config) login page.

like image 182
ksciana Avatar answered Nov 08 '22 10:11

ksciana


Create a new extension method for the request object say (IsUserAuthenticated()) & in that method check if the user is valid. Once this is done, you can use this new extension method the same way you are using Request.IsAuthenticated Property.

Below is the sample code, which you will need to tweak as per your needs. (specifically for

userservice 

initialization)

public class RequestValidator
{
    public bool IsValid(HttpRequest request)
    {
       bool isValid  = false;

       //TODO: Intitialize your userService here, may be using DI or a concrete object creation depending on your implementation

       var auth = request.Headers["Authorization"];
       if (!string.IsNullOrEmpty(auth))
       {
           var cred = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
           var user = new { Name = cred[0], Password = cred[1] };

           isValid = userService.AuthorizeTutor(user.Name, user.Password))            
       }

      return isValid; 
    }
}

Your attribute will change like this

public class TutorAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var req = filterContext.HttpContext.Request;
        RequestValidator validator = new RequestValidator(); 
        if(validator.IsValid(request))
        {
            return; 
        }

        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", $"Basic realm= {BasicRealm}");

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

And the extension method to be used on view will be

public static class Extensions
{
    public static bool IsUserAuthenticated(this HttpRequest request)
    {
        RequestValidator validator = new RequestValidator(); 
        return validator.IsValid(request); 
    }
}

Use it like this

@if(Request.IsUserAuthenticated())
{
     <p>Hello</p>
}
like image 43
Mads... Avatar answered Nov 08 '22 10:11

Mads...


If you want to pass the boolean value indicating if the user is authenticated, maybe it makes sense to just use the model object and pass it to the view.

Or maybe you should review your Form Authentication to make Request.IsAuthenticated working properly. This thread will help to start digging.

Another option would be to consider using the IAuthorizationFilter instead of the custom action filter. This thread will be a starting point.

Hope that helps!

like image 39
Dmitry Pavlov Avatar answered Nov 08 '22 11:11

Dmitry Pavlov