Programmatically add [AllowAnonymous] attribute to all my controller methods











up vote
0
down vote

favorite












I have a WebAPI2 REST api with several controllers. I use role based authentication. I put [Authorize] attributes on all my controllers and some methods. However, in the DEV environment I want to disable authentication. I was hoping that I can put some code into the WebApiConfig such as:



public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

//==============================================
// NOTE: disable all authentication in the DEV_ENVIRONMENT

if (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1")
{
config.Filters.Add(new AllowAnonymousAttribute());
}
}
}


However, this does not compile, because



error CS1503: Argument 1: cannot convert from 
'System.Web.Http.AllowAnonymousAttribute' to
'System.Web.Http.Filters.IFilter'


Is there a way at runtime to turn off all authentication in my REST api?










share|improve this question


























    up vote
    0
    down vote

    favorite












    I have a WebAPI2 REST api with several controllers. I use role based authentication. I put [Authorize] attributes on all my controllers and some methods. However, in the DEV environment I want to disable authentication. I was hoping that I can put some code into the WebApiConfig such as:



    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    config.MapHttpAttributeRoutes();
    config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

    //==============================================
    // NOTE: disable all authentication in the DEV_ENVIRONMENT

    if (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1")
    {
    config.Filters.Add(new AllowAnonymousAttribute());
    }
    }
    }


    However, this does not compile, because



    error CS1503: Argument 1: cannot convert from 
    'System.Web.Http.AllowAnonymousAttribute' to
    'System.Web.Http.Filters.IFilter'


    Is there a way at runtime to turn off all authentication in my REST api?










    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I have a WebAPI2 REST api with several controllers. I use role based authentication. I put [Authorize] attributes on all my controllers and some methods. However, in the DEV environment I want to disable authentication. I was hoping that I can put some code into the WebApiConfig such as:



      public static class WebApiConfig
      {
      public static void Register(HttpConfiguration config)
      {
      config.MapHttpAttributeRoutes();
      config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

      //==============================================
      // NOTE: disable all authentication in the DEV_ENVIRONMENT

      if (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1")
      {
      config.Filters.Add(new AllowAnonymousAttribute());
      }
      }
      }


      However, this does not compile, because



      error CS1503: Argument 1: cannot convert from 
      'System.Web.Http.AllowAnonymousAttribute' to
      'System.Web.Http.Filters.IFilter'


      Is there a way at runtime to turn off all authentication in my REST api?










      share|improve this question













      I have a WebAPI2 REST api with several controllers. I use role based authentication. I put [Authorize] attributes on all my controllers and some methods. However, in the DEV environment I want to disable authentication. I was hoping that I can put some code into the WebApiConfig such as:



      public static class WebApiConfig
      {
      public static void Register(HttpConfiguration config)
      {
      config.MapHttpAttributeRoutes();
      config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

      //==============================================
      // NOTE: disable all authentication in the DEV_ENVIRONMENT

      if (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1")
      {
      config.Filters.Add(new AllowAnonymousAttribute());
      }
      }
      }


      However, this does not compile, because



      error CS1503: Argument 1: cannot convert from 
      'System.Web.Http.AllowAnonymousAttribute' to
      'System.Web.Http.Filters.IFilter'


      Is there a way at runtime to turn off all authentication in my REST api?







      asp.net-web-api authorization






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 9 at 22:35









      John Henckel

      3,21313044




      3,21313044
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          I wouldn't 'remove' authorization. Suppose you have a customer and CustomerId is a claim, then you can't test the code because claims are missing. Instead I would choose to add an identity for development purposes.



          It's probably a hack, but my strategy would be to add a filter where the current user is set including the required roles(s):



          using System.Security.Principal;
          using System.Web;
          using System.Web.Http.Controllers;
          using System.Web.Http.Filters;

          public class AddIdentityFilter : AuthorizationFilterAttribute
          {
          public override void OnAuthorization(HttpActionContext actionContext)
          {
          HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new { "Admin" });
          base.OnAuthorization(actionContext);
          }
          }


          In WebApiConfig.cs add the filter:



          public static class WebApiConfig
          {
          public static void Register(HttpConfiguration config)
          {
          config.SuppressDefaultHostAuthentication();

          // Add some logic here to determine the environment
          var isDevelopment = true;

          if (isDevelopment)
          config.Filters.Add(new AddIdentityFilter());

          // ...
          }


          This way you can define multiple scenarios for testing while developing.






          share|improve this answer





















          • Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
            – John Henckel
            Nov 15 at 19:27


















          up vote
          1
          down vote













          I will share a couple of ways to do this. The way my services work, we have a base controller class FooController that has all the logic in it for service. Per environment (please don't ask!) we have DevFooController that derives from FooController.



          In the Register method we have something that looks a lot like this:



          var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

          /// api/{tenant}/{id}
          config.Routes.MapHttpRoute(
          name: "RouteName",
          routeTemplate: "api/{tenant}/{id}",
          defaults: new { controller = controller, action = "actionName" });


          The attributes are applied at the corresponding controller.



          Hokey? Yup. Works? Also Yup.



          A different system I used to work on used dependency injection. All controllers were always registered. On each request the injector had some juicy bits about the request (dev/prod, flights, geo, etc.) and was able to select the correct concrete controller. The classes looked similar but FooController also implemented IFooController and the multiple registered class were all available simultaneously vs. the above example where only one staticly configured route is available.



          I would prefer the IoC approach but I wasn't around when the service I support now was being drawn up on the whiteboard.



          One notable feature we also implement this way is CORS support. It's not available on any of the pre-production endpoints.



          Finally we have an ActionFilter on several of our methods that might work like you want. The "allow anonymous" logic is in the ActionFilter itself. If your condition is true the filter just continues without verifying any identity. We perform our own AuthZ but can configure it like you describe.



          Hope one of these suggestions can work for you.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234135%2fprogrammatically-add-allowanonymous-attribute-to-all-my-controller-methods%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            I wouldn't 'remove' authorization. Suppose you have a customer and CustomerId is a claim, then you can't test the code because claims are missing. Instead I would choose to add an identity for development purposes.



            It's probably a hack, but my strategy would be to add a filter where the current user is set including the required roles(s):



            using System.Security.Principal;
            using System.Web;
            using System.Web.Http.Controllers;
            using System.Web.Http.Filters;

            public class AddIdentityFilter : AuthorizationFilterAttribute
            {
            public override void OnAuthorization(HttpActionContext actionContext)
            {
            HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new { "Admin" });
            base.OnAuthorization(actionContext);
            }
            }


            In WebApiConfig.cs add the filter:



            public static class WebApiConfig
            {
            public static void Register(HttpConfiguration config)
            {
            config.SuppressDefaultHostAuthentication();

            // Add some logic here to determine the environment
            var isDevelopment = true;

            if (isDevelopment)
            config.Filters.Add(new AddIdentityFilter());

            // ...
            }


            This way you can define multiple scenarios for testing while developing.






            share|improve this answer





















            • Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
              – John Henckel
              Nov 15 at 19:27















            up vote
            1
            down vote



            accepted










            I wouldn't 'remove' authorization. Suppose you have a customer and CustomerId is a claim, then you can't test the code because claims are missing. Instead I would choose to add an identity for development purposes.



            It's probably a hack, but my strategy would be to add a filter where the current user is set including the required roles(s):



            using System.Security.Principal;
            using System.Web;
            using System.Web.Http.Controllers;
            using System.Web.Http.Filters;

            public class AddIdentityFilter : AuthorizationFilterAttribute
            {
            public override void OnAuthorization(HttpActionContext actionContext)
            {
            HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new { "Admin" });
            base.OnAuthorization(actionContext);
            }
            }


            In WebApiConfig.cs add the filter:



            public static class WebApiConfig
            {
            public static void Register(HttpConfiguration config)
            {
            config.SuppressDefaultHostAuthentication();

            // Add some logic here to determine the environment
            var isDevelopment = true;

            if (isDevelopment)
            config.Filters.Add(new AddIdentityFilter());

            // ...
            }


            This way you can define multiple scenarios for testing while developing.






            share|improve this answer





















            • Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
              – John Henckel
              Nov 15 at 19:27













            up vote
            1
            down vote



            accepted







            up vote
            1
            down vote



            accepted






            I wouldn't 'remove' authorization. Suppose you have a customer and CustomerId is a claim, then you can't test the code because claims are missing. Instead I would choose to add an identity for development purposes.



            It's probably a hack, but my strategy would be to add a filter where the current user is set including the required roles(s):



            using System.Security.Principal;
            using System.Web;
            using System.Web.Http.Controllers;
            using System.Web.Http.Filters;

            public class AddIdentityFilter : AuthorizationFilterAttribute
            {
            public override void OnAuthorization(HttpActionContext actionContext)
            {
            HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new { "Admin" });
            base.OnAuthorization(actionContext);
            }
            }


            In WebApiConfig.cs add the filter:



            public static class WebApiConfig
            {
            public static void Register(HttpConfiguration config)
            {
            config.SuppressDefaultHostAuthentication();

            // Add some logic here to determine the environment
            var isDevelopment = true;

            if (isDevelopment)
            config.Filters.Add(new AddIdentityFilter());

            // ...
            }


            This way you can define multiple scenarios for testing while developing.






            share|improve this answer












            I wouldn't 'remove' authorization. Suppose you have a customer and CustomerId is a claim, then you can't test the code because claims are missing. Instead I would choose to add an identity for development purposes.



            It's probably a hack, but my strategy would be to add a filter where the current user is set including the required roles(s):



            using System.Security.Principal;
            using System.Web;
            using System.Web.Http.Controllers;
            using System.Web.Http.Filters;

            public class AddIdentityFilter : AuthorizationFilterAttribute
            {
            public override void OnAuthorization(HttpActionContext actionContext)
            {
            HttpContext.Current.User = new GenericPrincipal(new GenericIdentity("John"), new { "Admin" });
            base.OnAuthorization(actionContext);
            }
            }


            In WebApiConfig.cs add the filter:



            public static class WebApiConfig
            {
            public static void Register(HttpConfiguration config)
            {
            config.SuppressDefaultHostAuthentication();

            // Add some logic here to determine the environment
            var isDevelopment = true;

            if (isDevelopment)
            config.Filters.Add(new AddIdentityFilter());

            // ...
            }


            This way you can define multiple scenarios for testing while developing.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 10 at 19:34









            Ruard van Elburg

            4,97321125




            4,97321125












            • Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
              – John Henckel
              Nov 15 at 19:27


















            • Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
              – John Henckel
              Nov 15 at 19:27
















            Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
            – John Henckel
            Nov 15 at 19:27




            Awesome! this totally works. I had to remove the line config.SuppressDefaultHostAuthentication(); because I am not using OWIN. But apparently it is not necessary.
            – John Henckel
            Nov 15 at 19:27












            up vote
            1
            down vote













            I will share a couple of ways to do this. The way my services work, we have a base controller class FooController that has all the logic in it for service. Per environment (please don't ask!) we have DevFooController that derives from FooController.



            In the Register method we have something that looks a lot like this:



            var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

            /// api/{tenant}/{id}
            config.Routes.MapHttpRoute(
            name: "RouteName",
            routeTemplate: "api/{tenant}/{id}",
            defaults: new { controller = controller, action = "actionName" });


            The attributes are applied at the corresponding controller.



            Hokey? Yup. Works? Also Yup.



            A different system I used to work on used dependency injection. All controllers were always registered. On each request the injector had some juicy bits about the request (dev/prod, flights, geo, etc.) and was able to select the correct concrete controller. The classes looked similar but FooController also implemented IFooController and the multiple registered class were all available simultaneously vs. the above example where only one staticly configured route is available.



            I would prefer the IoC approach but I wasn't around when the service I support now was being drawn up on the whiteboard.



            One notable feature we also implement this way is CORS support. It's not available on any of the pre-production endpoints.



            Finally we have an ActionFilter on several of our methods that might work like you want. The "allow anonymous" logic is in the ActionFilter itself. If your condition is true the filter just continues without verifying any identity. We perform our own AuthZ but can configure it like you describe.



            Hope one of these suggestions can work for you.






            share|improve this answer



























              up vote
              1
              down vote













              I will share a couple of ways to do this. The way my services work, we have a base controller class FooController that has all the logic in it for service. Per environment (please don't ask!) we have DevFooController that derives from FooController.



              In the Register method we have something that looks a lot like this:



              var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

              /// api/{tenant}/{id}
              config.Routes.MapHttpRoute(
              name: "RouteName",
              routeTemplate: "api/{tenant}/{id}",
              defaults: new { controller = controller, action = "actionName" });


              The attributes are applied at the corresponding controller.



              Hokey? Yup. Works? Also Yup.



              A different system I used to work on used dependency injection. All controllers were always registered. On each request the injector had some juicy bits about the request (dev/prod, flights, geo, etc.) and was able to select the correct concrete controller. The classes looked similar but FooController also implemented IFooController and the multiple registered class were all available simultaneously vs. the above example where only one staticly configured route is available.



              I would prefer the IoC approach but I wasn't around when the service I support now was being drawn up on the whiteboard.



              One notable feature we also implement this way is CORS support. It's not available on any of the pre-production endpoints.



              Finally we have an ActionFilter on several of our methods that might work like you want. The "allow anonymous" logic is in the ActionFilter itself. If your condition is true the filter just continues without verifying any identity. We perform our own AuthZ but can configure it like you describe.



              Hope one of these suggestions can work for you.






              share|improve this answer

























                up vote
                1
                down vote










                up vote
                1
                down vote









                I will share a couple of ways to do this. The way my services work, we have a base controller class FooController that has all the logic in it for service. Per environment (please don't ask!) we have DevFooController that derives from FooController.



                In the Register method we have something that looks a lot like this:



                var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

                /// api/{tenant}/{id}
                config.Routes.MapHttpRoute(
                name: "RouteName",
                routeTemplate: "api/{tenant}/{id}",
                defaults: new { controller = controller, action = "actionName" });


                The attributes are applied at the corresponding controller.



                Hokey? Yup. Works? Also Yup.



                A different system I used to work on used dependency injection. All controllers were always registered. On each request the injector had some juicy bits about the request (dev/prod, flights, geo, etc.) and was able to select the correct concrete controller. The classes looked similar but FooController also implemented IFooController and the multiple registered class were all available simultaneously vs. the above example where only one staticly configured route is available.



                I would prefer the IoC approach but I wasn't around when the service I support now was being drawn up on the whiteboard.



                One notable feature we also implement this way is CORS support. It's not available on any of the pre-production endpoints.



                Finally we have an ActionFilter on several of our methods that might work like you want. The "allow anonymous" logic is in the ActionFilter itself. If your condition is true the filter just continues without verifying any identity. We perform our own AuthZ but can configure it like you describe.



                Hope one of these suggestions can work for you.






                share|improve this answer














                I will share a couple of ways to do this. The way my services work, we have a base controller class FooController that has all the logic in it for service. Per environment (please don't ask!) we have DevFooController that derives from FooController.



                In the Register method we have something that looks a lot like this:



                var controller = (Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "1") ? "DevFoo" : "Foo";

                /// api/{tenant}/{id}
                config.Routes.MapHttpRoute(
                name: "RouteName",
                routeTemplate: "api/{tenant}/{id}",
                defaults: new { controller = controller, action = "actionName" });


                The attributes are applied at the corresponding controller.



                Hokey? Yup. Works? Also Yup.



                A different system I used to work on used dependency injection. All controllers were always registered. On each request the injector had some juicy bits about the request (dev/prod, flights, geo, etc.) and was able to select the correct concrete controller. The classes looked similar but FooController also implemented IFooController and the multiple registered class were all available simultaneously vs. the above example where only one staticly configured route is available.



                I would prefer the IoC approach but I wasn't around when the service I support now was being drawn up on the whiteboard.



                One notable feature we also implement this way is CORS support. It's not available on any of the pre-production endpoints.



                Finally we have an ActionFilter on several of our methods that might work like you want. The "allow anonymous" logic is in the ActionFilter itself. If your condition is true the filter just continues without verifying any identity. We perform our own AuthZ but can configure it like you describe.



                Hope one of these suggestions can work for you.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 11 at 2:41

























                answered Nov 10 at 17:14









                No Refunds No Returns

                5,09121932




                5,09121932






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53234135%2fprogrammatically-add-allowanonymous-attribute-to-all-my-controller-methods%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Xamarin.iOS Cant Deploy on Iphone

                    Glorious Revolution

                    Dulmage-Mendelsohn matrix decomposition in Python