Showing posts with label (REST) MVC WEB API. Show all posts
Showing posts with label (REST) MVC WEB API. Show all posts

Tuesday, 14 July 2026

Apply Filter Dynamically on WebApi Controller based on Header Value and modify the response in Filter

 In this post we are going to see how to apply filter on web api controller based on the api version which is passed on http request header. we will pass a header key "version" which may contain value "v1" or "v2". if we get the value as "v1" we will apply version 1 Filter for others different version filter. First we will see the Filters sample.

ApiV1Filter

  internal class ApiV1Filter : Attribute, IActionFilter
  {
      public void OnActionExecuted(ActionExecutedContext context)
      {
          var res = context.Result;

          if (res is ObjectResult jsonData)
          {

              string data = JsonConvert.SerializeObject(jsonData.Value);

              JObject jsonPayload = new JObject();

              jsonPayload["data"] = JArray.Parse(data);
              jsonPayload.Add(new JProperty("version", "v1"));

              context.Result = new Microsoft.AspNetCore.Mvc.ContentResult
              {
                  Content = jsonPayload.ToString(),
                  ContentType = "application/json",
                  StatusCode = 200
              };
          }
      }

      public void OnActionExecuting(ActionExecutingContext context)
      {
         Console.WriteLine("ApiV1Filter: Action executing.");
      }
  }


ApiV2Filter
internal class ApiV2Filter : Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { var res = context.Result; if (res is ObjectResult jsonData) { string data = JsonConvert.SerializeObject(jsonData.Value); JObject jsonPayload = new JObject(); jsonPayload["data"] = JArray.Parse(data); jsonPayload.Add(new JProperty("version", "v2")); context.Result = new Microsoft.AspNetCore.Mvc.ContentResult { Content = jsonPayload.ToString(), ContentType = "application/json", StatusCode = 200 }; } } public void OnActionExecuting(ActionExecutingContext context) { Console.WriteLine("ApiV2Filter: Action executing."); } }

FilterFactory

internal class VersionFilterFactory : Attribute, IFilterFactory { public bool IsReusable => false; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { if (serviceProvider != null) { var http = serviceProvider.GetService<IHttpContextAccessor>(); var version = http.HttpContext.Request.Headers["version"]; if (version == "v1") { return serviceProvider.GetService<ApiV1Filter>(); } return serviceProvider.GetService<ApiV2Filter>(); } throw new InvalidOperationException("Service provider is null."); } }

In the above code we have two filters in FilterFactory we are applying one filter dynamically to the Controller based on header version. Next step is register the filters in program.cs and apply it on controller.

builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ApiV1Filter>();
builder.Services.AddScoped<ApiV2Filter>();

When you give request with header V1 or with out header we will get different response for testing purpose i am returing json with custom property version with value v1 or v2. you can see below.




From this post you can learn the applying filter dynamically to controller using IFilterFactory

Monday, 11 February 2019

Using the OwinMiddleware in AspNet Core (or) use IAppBuilder in IApplicationBuilder

In this post we are going to see how to use the OwinMiddleware in Asp.net Core or use the IAppBuilder in IApplicationBuilder.

First we will see the custom OwinMiddleware which will authenticate the user in Web Api Request.

public class PinBasedAuthenticationMiddleware : OwinMiddleware
    {
        public PinBasedAuthenticationMiddleware(OwinMiddleware next) : base(next)
        {
        }

        public override async Task Invoke(IOwinContext context)
        {
            bool authorised = IsAuthorised(context.Request.Headers);
            if (authorised)
            {
                IEnumerable<Claim> claimCollection = new List<Claim>
                {
                    new Claim(ClaimTypes.NameIdentifier,"123456"),
                    new Claim(ClaimTypes.Country, "India"),
                    new Claim(ClaimTypes.Gender,"Male"),
                    new Claim(ClaimTypes.Email,"test@gmail.com"),
                    new Claim(ClaimTypes.Role, "SA"),
                    new Claim(ClaimTypes.Sid,Guid.NewGuid().ToString())
                };
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, 
                                              "Pin_Based");
                IPrincipal principal = new ClaimsPrincipal(claimsIdentity);
                context.Request.User = principal;
                await Next.Invoke(context);
            }
            else
            {
                context.Response.ReasonPhrase = "UnAuthorized";
                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }           
        }

         private bool IsAuthorised(IHeaderDictionary requestHeaders)
        {
            string[] pinValues;
         bool pinHeaderPresent = requestHeaders.TryGetValue("x-token-auth", 
                                       out pinValues);
            if (pinHeaderPresent)
            {
                string[] valuesInHeader = pinValues.ToList()[0].Split(
                                           new char[] { '|' }, 
                                          StringSplitOptions.RemoveEmptyEntries);
                if (valuesInHeader.Length == 2)
                {
                    int pin;
                    if (int.TryParse(valuesInHeader[1], out pin))
                    {
                        if (pin >= 10000)
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }
        
    }

Now we will see how to use this middleware in Asp.Net Core, Normally we cant do this straight away. because in Asp Net core it is using the IApplicationBuilder, but to configure the owin middleware we need the IAppBuilder.

Let we do a Extension Methods which will do this.
First install the following package in application install package Microsoft.AspNetCore.App
to use the UseOwin method

internal static class ApplicationBuilderExtension {
    public static IApplicationBuilder UseOwinMiddleware(
    this IApplicationBuilder coreApp,
    Action<IAppBuilder> configuration) {
        return coreApp.UseOwin(setup => setup(next => {
            AppBuilder owinBuilder = new AppBuilder();
            IApplicationLifetime coreLifeTime = 
                        (IApplicationLifetime)coreApp.ApplicationServices
                            .GetService(typeof(IApplicationLifetime));
            AppProperties owinProp = new AppProperties(owinBuilder.Properties);
            owinProp.OnAppDisposing = coreLifeTime?.ApplicationStopping ?? 
                                               CancellationToken.None;
            owinProp.DefaultApp = next;
            configuration(owinBuilder);
            return owinBuilder.Build<Func<IDictionary<string, object>, Task>();
        }));

    }
}


How to use this extension method in asp.net core, let we see that.

public class Startup {
 public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
  /* install package Microsoft.AspNetCore.App */
  app.UseOwinMiddleware((build) => {
           build.MapWhen((ctx) => {
                          return ctx.Request.Headers.ContainsKey("rsh");
                         },
                         (appbuilder) => {
                           appbuilder.Use<PinBasedAuthenticationMiddleware>();
                         });
            });
 }
}


I am applying a middleware based on condition whenever the request contains the headers "rsh" following middleware will be apply, this middleware will authenticate the request.


From this post you can learn how to use the OwinMiddleware in Asp.net Core. or use IAppBuilder in IApplicationBuilder.

Saturday, 15 September 2018

Intercept the HttpRequest for create a custom authentication using AuthenticationMiddleware Owin in WebApi


In this post we are going to see how to intercept HttpRequest for create a custom authentication using AuthenticationMiddleware owin in WebApi. For this we will take scenario like Pin based token authentication. For example users have to send the following header in each request for validate

Header Name: x-token-auth

This header must contain a value of pin token, that must be greater than 10000 for authorize, if it is less then we will state it as unauthorized.

Sample:
*********
x-token-auth: token|50000

In my previous post we did same kind of authentication using OwinMiddleware, Now we are going to do that using AuthenticationMiddleware Link for the previous post Create custom authentication using Owin Middleware


Steps to follow:
****************

  1. Create a class PinBasedAuthenticationOptions derive from AuthenticationOptions
  2. Create a middleware derive from AuthenticationMiddleware<PinBasedAuthenticationOptions>
  3. Create a Handler derive from AuthenticationHandler<PinBasedAuthenticationOptions>
  4. Create a another middleware derive from OwinMiddleware.
  5. Create a extension method which is used to map the middleware in the HttpRequest.
  6. Call the extension method in the startup.cs

Step 1:
********
Create a class PinBasedAuthenticationOptions derive from AuthenticationOptions and set the authentication type as PinBased_Token

public class PinBasedAuthenticationOptions : AuthenticationOptions
{
  internal const string Authentication_Type = "PinBased_Token";       

  public PinBasedAuthenticationOptions() : base(Authentication_Type)
  {
  }
}



Step 2:
********
Create a middleware derive from AuthenticationMiddleware<PinBasedAuthenticationOptions> we have to create a second parameter in the constructor which takes input param as PinBasedAuthenticationOptions and that constructor should be public.


    public class PinBasedMiddleware :                 
             AuthenticationMiddleware<PinBasedAuthenticationOptions>
    {
       public PinBasedMiddleware(OwinMiddleware next, PinBasedAuthenticationOptions options)           : base(next, options)
        {
        }

        protected override AuthenticationHandler<PinBasedAuthenticationOptions>                      CreateHandler()
        {
            return new PinAuthenticationHandler();
        }
    }



Step 3:
********
Create a Handler derive from AuthenticationHandler<PinBasedAuthenticationOptions>, Here in this handler we are checking the Request headers for the PinBased token if it is authorized then populate the ClaimsIdentity in the AuthenticationTicket, This will internally populate the user object in the Request.


public class PinAuthenticationHandler : AuthenticationHandler<PinBasedAuthenticationOptions>
    {
        public PinAuthenticationHandler()
        {
        }

        protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
        {           
            AuthenticationProperties properties = new AuthenticationProperties();
            var authenticationResult = new AuthenticationTicket(null, properties);
            bool authorised =  IsAuthorised(Request.Headers);
            if(authorised)
            {
                IEnumerable<Claim> claimCollection = new List<Claim>
                {
                    new Claim(ClaimTypes.NameIdentifier,"123456"),
                    new Claim(ClaimTypes.Country, "India"),
                    new Claim(ClaimTypes.Gender,"Male"),
                    new Claim(ClaimTypes.Email,"test@gmail.com"),
                    new Claim(ClaimTypes.Role, "SA"),
                    new Claim(ClaimTypes.Sid,Guid.NewGuid().ToString())
                };
      ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection,"Pin_Based");
      authenticationResult = new AuthenticationTicket(claimsIdentity, properties);                
            }
            return await Task.Run(() => authenticationResult);           
        }


        private bool IsAuthorised(IHeaderDictionary requestHeaders)
        {
          string []pinValues;
          bool pinHeaderPresent = requestHeaders.TryGetValue("x-token-auth", out pinValues);
            if (pinHeaderPresent)
            {
                string[] valuesInHeader = pinValues.ToList()[0].Split(new char[] { '|' }, 
                                              StringSplitOptions.RemoveEmptyEntries);
                if (valuesInHeader.Length == 2)
                {
                    int pin;
                    if (int.TryParse(valuesInHeader[1], out pin))
                    {
                        if (pin >= 10000)
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }

    }




Step 4:
********
Create a another middleware derive from OwinMiddleware.In this middleware we are checking whether user object in the request is populated or not, if it is not populated then we are setting the StatusCode for response as UnAuthorized.

    public class PinBasedPostAuthenticationMiddleware : OwinMiddleware
    {
        public PinBasedPostAuthenticationMiddleware(OwinMiddleware next) : base(next)
        {
        }

        public override async Task Invoke(IOwinContext context)
        {
            if (context.Request.User == null)
            {
                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }
            else
            {
                await Next.Invoke(context);
            }
        }
    }


Step 5:
********
Create a extension method which is used to map the middleware in the HttpRequest. Here in this extension method we are using the middleware based on the pipeline stage, so middleware will run stage by stage , one by one.


    public static class PinAuthenticationExtension
    {
        public static void UsePinBasedAuthentication(this IAppBuilder builder)
        {
            builder.MapWhen((context) => true, (app) =>
               {
                   app.Use<PinBasedMiddleware>(new PinBasedAuthenticationOptions());
                   app.UseStageMarker(PipelineStage.Authenticate);

                   app.Use<PinBasedPostAuthenticationMiddleware>();
                   app.UseStageMarker(PipelineStage.PostAuthenticate);
               });            
        }
         }


Step 6:
********
Call the extension method in the startup.cs

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UsePinBasedAuthentication();
        }       
    }



Controller:
***********
public class ValuesController : ApiController
    {
        // GET api/values
        public IHttpActionResult Get()
        {           
            var data = new string[] { "value1""value2" };
            return Ok(data);
        }

        // GET api/values/5
        public string Get(int id)
        {
            var data = "Rajesh";
            return data;
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
       
    }


Output:
**********

Make a call to the endpoint with pin value less than 10000 using postman will result in UnAuthorized






Make a call to the endpoint with pin value greater than 10000 using postman will result in success authentication




From this post you can learn how to intercept the HttpRequest for create a custom authentication using AuthenticationMiddleware Owin in WebApi