diff --git a/README.md b/README.md index ef275df..25ef727 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,44 @@ The following matchers are available: * `allow_request`: allows a request with the given Rack environment, and optional principals +### Error Page Middleware + +When an authorization error occurs, the `Rails::Auth::NotAuthorizedError` +exception is raised up the middleware chain. However, it's likely you would +prefer to show an error page than have an unhandled exception. + +You can write your own middleware that catches `Rails::Auth::NotAuthorizedError` +if you'd like. However, a default one is provided which renders a 403 response +with a static page body if you find that helpful. + +To use it, add `Rails::Auth::ErrorPage::Middleware` to your app: + +``` +```ruby +app = MyRackApp.new + +acl = Rails::Auth::ACL.from_yaml( + File.read("/path/to/my/acl.yaml") + matchers: { allow_x509_subject: Rails::Auth::X509::Matcher } +) + +acl_auth = Rails::Auth::ACL::Middleware.new(app, acl: acl) + +x509_auth = Rails::Auth::X509::Middleware.new( + acl_auth, + ca_file: "/path/to/my/cabundle.pem" + cert_filters: { 'X-SSL-Client-Cert' => :pem }, + require_cert: true +) + +error_page = Rails::Auth::ErrorPage::Middleware.new( + x509_auth, + page_body: File.read("path/to/403.html") +) + +run error_page +``` + ## Contributing Any contributors to the master *rails-auth* repository must sign the diff --git a/lib/rails/auth/error_page/middleware.rb b/lib/rails/auth/error_page/middleware.rb new file mode 100644 index 0000000..0c66a58 --- /dev/null +++ b/lib/rails/auth/error_page/middleware.rb @@ -0,0 +1,21 @@ +module Rails + module Auth + module ErrorPage + # Render an error page in the event Rails::Auth::NotAuthorizedError is raised + class Middleware + def initialize(app, page_body: nil) + fail TypeError, "page_body must be a String" unless page_body.is_a?(String) + + @app = app + @page_body = page_body.freeze + end + + def call(env) + @app.call(env) + rescue Rails::Auth::NotAuthorizedError + [403, {}, [@page_body]] + end + end + end + end +end diff --git a/lib/rails/auth/rack.rb b/lib/rails/auth/rack.rb index 26feb9e..5461f4e 100644 --- a/lib/rails/auth/rack.rb +++ b/lib/rails/auth/rack.rb @@ -12,6 +12,8 @@ require "rails/auth/acl/middleware" require "rails/auth/acl/resource" +require "rails/auth/error_page/middleware" + require "rails/auth/x509/filter/pem" require "rails/auth/x509/filter/java" if defined?(JRUBY_VERSION) require "rails/auth/x509/matcher" diff --git a/spec/rails/auth/error_page/middleware_spec.rb b/spec/rails/auth/error_page/middleware_spec.rb new file mode 100644 index 0000000..ba26517 --- /dev/null +++ b/spec/rails/auth/error_page/middleware_spec.rb @@ -0,0 +1,26 @@ +RSpec.describe Rails::Auth::ErrorPage::Middleware do + let(:request) { Rack::MockRequest.env_for("https://www.example.com") } + let(:error_page) { "