Search code examples
ruby-on-railsrubyherokumiddlewarestaging

Staging Env: Password protect everything except for webhook


For staging, I'd like to password protect everything so I added the code below. However, how can I edit this so it will skip over the webhook controller so I can still test inbound emails on staging?

  config.middleware.insert_after(::Rack::Lock, "::Rack::Auth::Basic", "Staging") do |u, p|
    [u, p] == [ENV["STAGING_USERNAME"], ENV["STAGING_PASSWORD"]]
  end

Solution

  • I don't think you can do this with `Rack::Auth::Basic'. However, looking at the source, it seems that you can create your own simple authentication mechanism that takes an extra option.

    It's the same as Rack::Auth::Basic, except for the call method. Create a file called authenticate_excluding.rb in app/middleware with the following:

    class AuthenticateExcluding < ::Rack::Auth::Basic
    
      def initialize(app, options={}, &authenticator)
        @excluded_paths = options[:exclude]
        super(app, options[:realm], &authenticator)
      end
    
      def call(env)
        if @excluded_paths && @excluded_paths.include?(env['PATH_INFO'])
          return @app.call(env)
        end
        super
      end
    end
    

    You can now use it with:

    config.middleware.insert_after(::Rack::Lock, "AuthenticateExcluding", excluding: ["/webhooks/service", "/other_hook"]) do |u, p|
      [u, p] == [ENV["STAGING_USERNAME"], ENV["STAGING_PASSWORD"]]
    end
    

    That should work. If you also want to enable the realm (the previous "Staging" argument), you can also add realm: "Staging" to the options hash.