Replay original request after interrupted with Devise login
<p>I have certain actions that require a user to be authenticated. If the user attempts these actions, I want my website to automatically be able to redirect them to log in and then automatically &quot;replay&quot; whatever the original action was. I am using Devise for authentication and CanCan for role/abilities. To this end, I have the following code:</p>
<pre><code>class ApplicationController &lt; ActionController::Base

    # CanCan detected an role violation. Redirect to login page.
    rescue_from CanCan::AccessDenied do |exception|
        session[:saved_params] = params
        user_signed_in? ? render_forbidden : render_unauthorized
    end
end
</code></pre>
<hr />
<pre><code>class Users::SessionsController &lt; Devise::SessionsController
    def after_sign_in_path_for(resource)
        if session[:saved_params]
            controller = session[:saved_params][:controller].capitalize+&quot;Controller&quot;
            replay_with_params(controller, session[:saved_params][:action], session[:saved_params])
        end
    end
end
</code></pre>
<hr />
<h2>Desired Behavior</h2>
<p>The user flow would be like this:</p>
<ol>
<li>User arrives at <code>Event#new</code>form, fills out form, and submits it.</li>
<li>In <code>ApplicationController</code>, CanCan detects anonymous user attempting to do something that they are not allowed to do. App Controller saves the params of the current request and redirects to login page.</li>
<li>User logs in at Devise login page. The <code>SessionController</code>detects <code>session[:saved_params]</code> and attempts to &quot;replay&quot; the original request from Step 1.</li>
</ol>
<hr />
<h2>Attempt #1: Directly invoking the controller's action</h2>
<pre><code>class ApplicationController &lt; ActionController::Base

    # Replay's another controller's action
    def replay_with_params(controller,action,params)
        if controller.instance_of? String
            klass = Object.const_get(controller)
            c = klass.new
        elsif controller.instance_of? Class
            c = controller.new
        else
            throw &quot;Unrecognized controller type: #{controller}&quot;
        end

        c.params = params
        c.dispatch(action, request)
        c.response.body
    end

end
</code></pre>
<p>The <code>replay_with_params</code> function is something I tweaked from <a href="https://stackoverflow.com/a/7085969/86421">https://stackoverflow.com/a/7085969/86421</a>.</p>
<h3>The Problem</h3>
<p>The problem with this is that I cannot reuse the authenticity token from another request. I either need to generate a new one, or <code>skip_before_action :verify_authenticity_token</code> on the target controller. I dont think generating a new token makes sense since there is no front-end to the replayed request. Skipping verification of the token is not appealing for obvious reasons.</p>
<h2>Attempt #2: Redirection</h2>
<p>Redirection would actually make more sense, I think, but it would only be <a href="https://stackoverflow.com/a/985599/86421">feasible for GET requests</a>. In my scenario, I need to be able to work with all verbs.</p>
<h2>Fundamentally Different Solutions</h2>
<p>I could intercept with a modal popup and make the user login there while keeping the original html form intact. This may be the best solution, but I prefer the flow of my original solution better. One of the reasons why I dont like this is because now I have to build my CanCan role/ability logic into my views, or else manually add the modal code into each view. The former seems like a violation of MVC and the latter is tedious and error prone.</p>
<p>Is what I am trying to do possible? I am running into roadblocks on every angle. How can I intercept a request, force someone to login and then replay the original request?</p>