Module: Controllers::PostRedirectable

Extended by:
ActiveSupport::Concern
Defined in:
app/concerns/controllers/post_redirectable.rb

Overview

Renders a self-submitting HTML form that POSTs to a target URL. Replaces
the unmaintained repost gem (last released 2017) with a small inline
implementation.

Used for OmniAuth provider authorization endpoints that require POST
(with the CSRF token already in the URL via authenticity_token=).

Usage:
redirect_post(omniauth_authorize_path(...))
redirect_post(url, params: { foo: 'bar' })

The form auto-submits via JavaScript on load. A no-script fallback
("Continue" button) is rendered for clients without JS. CSP-friendly:
uses request.content_security_policy_nonce on the script tag when
CSP is configured (no-op when it isn't).

Instance Method Summary collapse

Instance Method Details

#redirect_post(url, params: {}) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/concerns/controllers/post_redirectable.rb', line 21

def redirect_post(url, params: {})
  helpers = ActionController::Base.helpers
  nonce = request.content_security_policy_nonce

  fields = params.map { |k, v| helpers.tag.input(type: 'hidden', name: k.to_s, value: v.to_s) }.join.html_safe
  form_attrs = { id: 'post-redirect', method: 'post', action: url }
  script_attrs = { nonce: nonce }.compact

  body = helpers.safe_join([
                             '<!DOCTYPE html>'.html_safe,
                             helpers.tag.html do
                               helpers.safe_join([
                                                   helpers.tag.head { helpers.tag.title('Redirecting…') },
                                                   helpers.tag.body do
                                                     helpers.safe_join([
                                                                         helpers.tag.form(**form_attrs) do
                                                                           helpers.safe_join([
                                                                                               fields,
                                                                                               helpers.tag.noscript { helpers.tag.button('Continue', type: 'submit') }
                                                                                             ])
                                                                         end,
                                                                         helpers.tag.script(
                                                                           "document.getElementById('post-redirect').submit();".html_safe,
                                                                           **script_attrs
                                                                         )
                                                                       ])
                                                   end
                                                 ])
                             end
                           ])

  render html: body, content_type: 'text/html'
end