Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API custom authentication filter

I am trying to make a custom filter for my web api controllers part of a ASP.NET MVC 5 website/application to check the requests headers for a specific token which i have stored in the database. Most examples I found were containing user credentials and then the user was authenticated using identity. Not exactly what I am looking for.

This is the tutorial I found and am currently following.

The web API should only handle "external" HTTP calls, the website side will have its own controllers presently (but may be subject to change).

This filter should interface with identity 2 system already present if possible.

What I do is that I send user credentials then, assign a token to the user and then I want to use that token to authenticate the request. Is there a way I can just filter the request based on the token or do I need to use Owin identity and their token management. I am using a mobile client (currently iOS, will include android too) to make the calls. Any example or tutorial I could refer to ?

The token is currently a random combination of alphanumeric characters and symbols.

Thank you.

P.S. I can post code snippets and stuff where needed.

Edit: The HTTPRequests will be filtered based on whether they contain a token present within our database/system. Requests that do contain a token or are not present within our system will receive unauthorised error (401?)

like image 492
beowulf Avatar asked Aug 05 '16 13:08

beowulf


People also ask

How do I create a custom authentication filter in Web API?

To create a custom authentication filter in ASP.NET MVC, we need to create a class by implementing the IAuthenticationFilter Interface. This IAuthenticationFilter interface has 2 methods. Open Visual Studio 2015 or an editor of your choice and create a new project.

How do you implement custom authentication filter?

In order to test the Custom Authentication Filter in MVC, Let's add a Controller with the name Home within the Controllers folder. Once you create the Home Controller then copy and paste the following code in it. As you can see, we created the above Home Controller class with three action methods.

How do I use authorization filter in Web API?

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. You can apply the filter globally, at the controller level, or at the level of individual actions.

How do I provide authentication in Web API?

Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.


2 Answers

Suppose you thought that sending user name and password to every request is not good.Refer my below implementation with out user name and password, since we are don't send user name and password with every request.

public class AuthenticationFilter : AuthorizationFilterAttribute
    {
        /// <summary>
        /// read requested header and validated
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var identity = FetchFromHeader(actionContext);

            if(identity != null)
            {
                var securityService = actionContext.ControllerContext.Configuration.DependencyResolver.GetService(typeof(ILoginService)) as ILoginService;
                if (securityService.TokenAuthentication(identity))
                {
                    CurrentThread.SetPrincipal(new GenericPrincipal(new GenericIdentity(identity), null), null, null);
                }
                else
                {
                    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
                    return;
                }
            }
            else
            {
                actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest);
                return;
            }
            base.OnAuthorization(actionContext);
        }

        /// <summary>
        /// retrive header detail from the request 
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private string FetchFromHeader(HttpActionContext actionContext)
        {
            string requestToken = null;

            var authRequest = actionContext.Request.Headers.Authorization;
            if (authRequest != null && !string.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic")
                requestToken = authRequest.Parameter;

            return requestToken;
        }
    }
like image 176
Raj A Avatar answered Oct 26 '22 13:10

Raj A


You can make this filter unit testable by injecting the service dependencies via property(property injection). For custom attributes, we don't want to pass the dependencies via constructor. We want the attribute easy to use. To rewrite what @Raj already started, it can look like this:

   public class AuthenticationFilter : AuthorizationFilterAttribute
    {
        [Dependency]
        public ILoginService LoginService { get; set; }

        /// <summary>
        /// read requested header and validated
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var identity = FetchFromHeader(actionContext);

            if (identity != null)
            {
                if (LoginService.TokenAuthentication(identity))
                {
                    CurrentThread.SetPrincipal(new GenericPrincipal(new GenericIdentity(identity), null), null, null);

                    //IPrincipal principal = new GenericPrincipal(new GenericIdentity(identity), new string[] { "myRole" });
                    //Thread.CurrentPrincipal = principal;
                    //HttpContext.Current.User = principal;             
                }
                else
                {
                    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
                    return;
                }
            }
            else
            {
                actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest);
                return;
            }
            base.OnAuthorization(actionContext);
        }

        /// <summary>
        /// retrive header detail from the request 
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private string FetchFromHeader(HttpActionContext actionContext)
        {
            string requestToken = null;

            var authRequest = actionContext.Request.Headers.Authorization;
            if (authRequest != null && !string.IsNullOrEmpty(authRequest.Scheme) && authRequest.Scheme == "Basic")
                requestToken = authRequest.Parameter;

            return requestToken;
        }
    }
like image 37
alltej Avatar answered Oct 26 '22 13:10

alltej