Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise authentication when accessing directly to a pdf file unauthenticated

I have a problem when trying to see a .pdf file (generated with PDFKit) unauthenticated, just going directly from a given url host/.../profile.pdf. I, as expected, am asked to enter the credentials as shown in the image (Not in the users/sign_in path):

asking for authentication

I enter the correct credentials, the box goes up and down and asks for the credentials again. It could seem like the user or password are wrong, but they aren't. The relevant code from the controller is here:

class Entrepreneur::ProfilesController < ApplicationController
  before_filter :authenticate_user!

  def show
    respond_to do |format|
      format.pdf do
        html = render_to_string(:layout => false , :action => "show.html.haml")
        kit = PDFKit.new(html)
        send_data(kit.to_pdf, :filename => "name.pdf", :type => 'application/pdf')
      end
    end
  end
end

Nothing fancy as you can see. I tried to remove the show action from the filter (before_filter :authenticate_user!, :except => [:show]) and write myself a custom filter to redirect unauthenticated users to new_session_path, but doing so I don't know how to, once signed up, redirect the user to the pdf show.

In short, devise asks for my credentials when accessing a pdf show and doesn't accept them. How can I get the user to the sign_in page and redirect back to the pdf once signed?

I'm using Rails 3.0.7, Ruby 1.8.7 and Devise 1.1.5.

Thanks!

like image 880
scumah Avatar asked Dec 03 '22 06:12

scumah


2 Answers

First, make sure that it's actually Rails serving the PDF and not a web server in front of it. (Depending on your configuration, it could be the request is never getting to Rails in the first place.)

Assuming it is Rails serving the file, then you should check your devise.rb configuration file. You may need to make :pdf a navigational format which will allow Devise to issue a 302 redirect to your sign_in page:

config.navigational_formats = [:html, :pdf] # you may have additional formats

Also, you may need to add PDF to your mime_types.rb initializer if it's not there already:

Mime::Type.register 'application/pdf', :pdf

like image 84
Chris Hart Avatar answered Dec 26 '22 01:12

Chris Hart


Adding to the accepted answer and repeating for completeness:

Update your devise config (config/initializers/devise.rb) to include pdf as a navigational_format.

Also update your devise config to use a custom failure_app.

require 'custom_failure'

Devise.setup do |config|
  # Navigate on pdf request types (i.e. .pdf)
  config.navigational_formats = ["*/*", :html, :pdf]

  config.warden do |manager|
    # Custom app to redirect to login page on unauthenticated pdf request types
    manager.failure_app = CustomFailure
  end
end

Custom failure app (lib/custom_failure.rb)

class CustomFailure < Devise::FailureApp

  # Redirect pdf request types to the login page
  def skip_format?
    %w(html pdf */*).include? request_format.to_s
  end

end
like image 35
steakchaser Avatar answered Dec 26 '22 00:12

steakchaser