Module Crumblr::InstanceMethods
In: vendor/plugins/crumblr/lib/crumblr.rb

Methods

Public Instance methods

Issue a crumb to verify at the receiving end of the form submission that the request came from a trusted source.

issue_crumb is intended to be used by view helper crumb_tags only. It calculates the value for the hidden tag _crumb that crumb_tags renders.

This value is the SHA1 hash of the following values concatenated:

request.remote_ip:The IP address of the remote client
timestamp:The timestamp at which the crumb was issued
cookies[:_session_id]:The session‘s ID
crumb_scope:A class attribute in the ActionController where crumblr is used.
session[:crumb_secret]:A random string acting as salt

[Source]

    # File vendor/plugins/crumblr/lib/crumblr.rb, line 60
60:     def issue_crumb(timestamp)
61:       session[:crumb_secret] = String.rand(6) unless session[:crumb_secret] 
62:       signature = "#{request.remote_ip}#{timestamp}#{cookies[:_session_id]}#{@@crumb_scope}#{session[:crumb_secret]}"
63:       logger.debug("_session_id = #{cookies[:_session_id]}
64: signature = #{signature}")
65:       OpenSSL::Digest::SHA1.hexdigest(signature)
66:     end

Verify that a crumb is valid. A crumb consists of query parameters _crumb and _timestamp, both if which are rendered by view helper crumb_tags. There is no validation on http GET as GET is commonly used w/o form submission.

Verify_crumb lets the request through if the crumb is valid. The client will be redirect back to where it came from when the crumb is not valid and the request includes an HTTP referer. Requests with invalid crumbs and no HTTP referer receive a 404.

[Source]

     # File vendor/plugins/crumblr/lib/crumblr.rb, line 78
 78:     def verify_crumb 
 79:       if (request.post? || request.put? || request.delete?) then
 80:         logger.debug("Crumb window = #{@@crumb_window}\nCrumb flash msg = #{@@crumb_flash_msg}")
 81:         if (defined?(params[:_crumb]) && 
 82:               defined?(params[:_timestamp]) && 
 83:               Time.at(params[:_timestamp].to_i) + @@crumb_window > Time.now &&
 84:               (params[:_crumb] == OpenSSL::Digest::SHA1.hexdigest("#{request.remote_ip}#{params[:_timestamp]}#{cookies[:_session_id]}#{@@crumb_scope}#{session[:crumb_secret]}"))) then
 85:           return true
 86:         else
 87:           logger.warn("Invalid crumb:
 88: _crumb = #{params[:_crumb]}
 89: _timestamp = #{params[:_timestamp]}
 90: remote_ip = #{request.remote_ip}
 91: _session_id = #{cookies[:_session_id]}
 92: scope = #{@@crumb_scope}
 93: crumb_secret = #{session[:crumb_secret]}
 94: digest = #{OpenSSL::Digest::SHA1.hexdigest("#{request.remote_ip}#{params[:_timestamp]}#{cookies[:_session_id]}#{session[:crumb_secret]}")}")
 95:           # Return the visitor to the origin of the request. Most
 96:           # often this will be local URL and this redirect will
 97:           # re-issue new crumbs. No harm done if the referrer is an
 98:           # external site. Crumblr's goal is to only accept requests
 99:           # from specific local origins.
100:           if request.env['HTTP_REFERER']
101:             flash[:warning] = @@crumb_flash_msg
102:             redirect_to request.env['HTTP_REFERER'] 
103:           else
104:             # Return standard 404 message. Let the ActionController's
105:             # rescue mechanisme handle this routing error rather then
106:             # explicitly returning the default public/404.html
107:             # file. Only report the lowest stack level in the error
108:             # log.
109:             raise ActionController::RoutingError, "Invalid crumb: #{params[:_crumb]}", caller(0)[0]
110:           end
111:         end
112:       else
113:         return true
114:       end
115:     end

[Validate]