5

I have developed a custom middleware in ASP.NET Core but it gets triggered with every request. My intent is to use it only when a request is authorized.

5
  • For Creating Middleware as pipline you have create 3 step, If you want I create a sample for you. Commented Oct 3, 2018 at 21:52
  • @AmirReza-Farahlagha My understanding by the OP is he does not want it to be triggered with every request, only authorized. Where the middleware will execute every request, where he would have to control said flow as you denoted in your example. Commented Oct 3, 2018 at 22:21
  • 1
    Exactly the middleware can control every request, because the middleware is a pipline, and work like other pipline. The middleware the same as the door that every thing that wants to go through, should cross from the door. Now see First section of my code, before "await _next(context);" you have to control the token. If you want I'll edit my answer with more sample. Commented Oct 3, 2018 at 22:28
  • @Greg My original intention was to use the middleware only for certain controllers which user can access only when user is authorized, If I am not wrong, the concept of UseWhen can work in this case, As in asp.net Core there is an option to use UseWhen with the specified condition while configuring the middleware. Commented Oct 4, 2018 at 15:27
  • That is similar to what the approach below is @ZainMalik. UseWhen is looking at the current HttpContext then deciding what to do. Since middleware is executed on every instance the point is controlling the flow based on criteria. UseWhen in essence is branching the flow to another pipeline then merges back. Does that make sense? Commented Oct 4, 2018 at 15:46

2 Answers 2

9

Update:

I create more sample for you and edit my answer. as you see, before the Next() method, I checked every token request. If didn't have Authorization tag in header of context request, be next(), If did check the token.

Now, may you have a question that what is the await _next(context); It is very complex and long, I want to suggest you that visit this link to know what is this issue.

For Create a Middlware you have to control and develop.

  1. Create Generally class as Middleware that work General action like you action Authorization.
  2. Create a static Extension class for relation between Middleware and startup.
  3. And finally Register in startup configuration.

Now this is good sample for you:

General Middlware:

public class RequestTokenMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly SignInManager<User> _signInManager;

        public RequestTokenMiddleware(RequestDelegate next, SignInManager<User> signInManager)
        {
            _next = next;
            _signInManager = signInManager;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                var hasAuthorization = context.Request.Headers.ContainsKey("Authorization");
            if (!hasAuthorization)
            {
                await _next(context); 
            }
            else
            {
                var shouldBeNext = false;
                foreach (var item in context.Request.Headers)
                {
                    if (item.Key == "Authorization")
                    {
                        using (var contextBudget = BudgetUnitOfWork.Get())
                        {

                            var tokenCode = item.Value.ToString().Remove(0, 7);
                            var token = await contextBudget.Db.Token.FirstOrDefaultAsync(x => x.TokenCode == tokenCode).ConfigureAwait(false);
                            if (token == null || !token.IsValid)
                            {
                                signOut(context);
                            }
                            else
                            {
                                shouldBeNext = true;
                            }
                        }
                    }
                }
                if (shouldBeNext)
                {
                    await _next(context);
                }

            }
            }
            catch (Exception exc)
            {
                signOut(context);
            }
        }

        private async void signOut(HttpContext context)
        {
            try
            {
                await context.Response.WriteAsync(JsonConvert.SerializeObject(ResultModel.Failure(null, ResultModel.StatusType.InvalidToken)));
            }
            catch (Exception)
            {
                throw new Exception();
            }
        }
    }

This is Static Extension class for Relation:

public static class ReuqestTokenMiddlewareExctention
    {
        public static IApplicationBuilder UseTokenValidator(this IApplicationBuilder applicationBuilder)
        {
            return applicationBuilder.UseMiddleware<RequestTokenMiddleware>();
        }
    }

Now Register your Middleware in startup:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<SetiaSettings> options)
{

     app.UseTokenValidator();
}
Sign up to request clarification or add additional context in comments.

6 Comments

I did the other route, where middleware defines a policy and you would use the attribute for the role to verify the request. But combined I think it should point him in the right direction, nice answer.
@Amir this seems a working solution. But can we take this authorization part in UseWhen/ MapWhen while configuring the Middleware? As I am new to asp.net core my understanding is limited
@ZainMalik Yeah dude, but it depends on that where you want to register your middleware. It means that, the middleware is a solution, that works as pipline. You have to know which where should to register the pipline.
I have a custom attribute for controller and is having its authentication; also i have middleware. The middle ware getting invoked first before the custom auth. where am i wrong?
@GvSharma unfortunately I didn't not get your question. could you explain better?
|
1

I believe you have a misunderstanding of middleware. Fundamentally middleware is software that will be assembled into the application pipeline to manage each request and response.

That means that middleware is executed every time.

An important concept though, would be how middleware handles each component. In essence top down execution, all allowed code will execute unless conditionally stated otherwise.

  • Chooses whether to pass the request to the next component in the pipeline.
  • Can perform work before and after the next component in the pipeline is invokved.

So your early statement is the behavior you should experience, but now you have to ensure the request being instantiated is allowed to execute or not. Your approach for security would basically be in your middleware, allowing that authorization to occur.

An example would be the authorize attribute, but I am not sure what authorization / authentication mechanism you are using.

To explicitly answer your question, you could do something along these lines:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdministratorRole", policy => policy.RequireRole("Administrator"));
    });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.