Authlogic/OpenID Authentication Fails Using Warp Drive - ruby-on-rails

Warp Drive is a nice way to package an entire Rails application into a Gem for use in other Rails applications. I've gotten Warp Drive to work for a blogging engine I'm creating. There's just one problem - Authlogic OpenID authentication fails.
I created a bare-bones OpenID example application. I can compile to a gem with no problems:
$ warpify
$ rake warp_drive:compile
I then installed the compiled gem on my system. Creating a blank Rails project, I ran:
$ install_warp_drive rails-openid
You can get this project here.
In my blank Rails projects, I needed to configure gems through environment.rb (I'm probably doing this the wrong way):
config.gem "authlogic"
config.gem "authlogic-oid", :lib => "authlogic_openid"
config.gem "ruby-openid", :lib => "openid"
To get the blank Rails application working, I ran rake db:migrate, then through the console I added a user with an :openid_identifier field set to one that I control. So far so good. But trying to create a new session fails with this error:
Processing UserSessionsController#create (for 127.0.0.1 at 2009-12-31 11:35:59) [POST]
Parameters: {"commit"=>"Login", "user_session"=>{"openid_identifier"=>"richdev.myopenid.com"}, "authenticity_token"=>"BcsIKNpumqZrTV/bdSLQ6szBvq6kpaAIxJRmYgxySLU="}
OpenIdAuthentication::Association Load (0.3ms) SELECT * FROM "open_id_authentication_associations" WHERE ("open_id_authentication_associations"."server_url" = 'http://www.myopenid.com/server')
Generated checkid_setup request to http://www.myopenid.com/server with assocication {HMAC-SHA1}{4b3cf228}{mWlzhg==}
Redirected to http://www.myopenid.com/server?openid.assoc_handle=%7BHMAC-SHA1%7D%7B4b3cf228%7D%7BmWlzhg%3D%3D%7D&openid.ax.mode=fetch_request&openid.identity=http%3A%2F%2Frichdev.myopenid.com%2F&openid.mode=checkid_setup&openid.return_to=http%3A%2F%2Flocalhost%3A3001%2Fuser_sessions%2Fcreate%3Ffor_session%3D1%26_method%3Dpost%26open_id_complete%3D1%26openid1_claimed_id%3Dhttp%253A%252F%252Frichdev.myopenid.com%252F%26rp_nonce%3D2009-12-31T19%253A35%253A59ZUEd2eN&openid.trust_root=http%3A%2F%2Flocalhost%3A3001%2F
Completed in 15ms (DB: 0) | 302 Found [http://localhost/user_sessions]
Processing ApplicationController#index (for 127.0.0.1 at 2009-12-31 11:36:00) [POST]
Parameters: {"openid.mode"=>"id_res", "openid.return_to"=>"http://localhost:3001/user_sessions/create?for_session=1&_method=post&open_id_complete=1&openid1_claimed_id=http%3A%2F%2Frichdev.myopenid.com%2F&rp_nonce=2009-12-31T19%3A35%3A59ZUEd2eN", "openid.sig"=>"l+tfFAmeKsskHKlOYRoZF7yHM7Q=", "rp_nonce"=>"2009-12-31T19:35:59ZUEd2eN", "openid.op_endpoint"=>"http://www.myopenid.com/server", "for_session"=>"1", "openid.response_nonce"=>"2009-12-31T19:36:00ZBhX5fE", "openid1_claimed_id"=>"http://richdev.myopenid.com/", "openid.identity"=>"http://richdev.myopenid.com/", "open_id_complete"=>"1", "openid.assoc_handle"=>"{HMAC-SHA1}{4b3cf228}{mWlzhg==}", "openid.signed"=>"assoc_handle,identity,mode,op_endpoint,response_nonce,return_to,signed"}
ActionController::MethodNotAllowed (Only get, put, and delete requests are allowed.):
Rendered rescues/_trace (96.3ms)
Rendered rescues/_request_and_response (0.5ms)
Rendering rescues/layout (method_not_allowed)
The problem seems to occur during the redirect back from the openid provider, at which point ApplicationController#index gets called, instead of UserSessionsController#create. I'm not sure if this is an OpenID issue or a Warp Drive issue.
How can I bundle an Authlogic/OpenID application as a Warp Drive Gem and get authentication to work successfully?
Update: Adding an explicit resource definition for user_session fixes the problem. In routes.rb:
map.resources :user_sessions
Not sure why, and this doesn't seem to be required for any other controller.

Two things worked:
Add an explicit user_session resource definition in routes.rb:
map.resources :user_sessions
Remove default routes in routes.rb of the app using the warp drive gem.

Removing default routes in routes.rb
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
solved a horrific routing issue where a resource routing in the warp drive:
map.resources :users, :member => {:activate => [:post, :get]}
created a URL: /users/:id/activate(.:format)
But an HTTP request to that URL resulted in the :action and :id getting reversed when passed to the controller (as if interpreted as a default URL). e.g.
Parameters = {"action"=>"123456", "id"=>"activate", "controller"=>"users"}
Not pretty. Removing the default routes in the warp drive or the client app did it. Seems safer to do it in the client app, though.

Related

Routes behaviour inconsistent between server and local Rails with aliased resource

I have a rails app using Rails 2.2.2 and ruby 1.8.6 (i know i should update, don't go there).
I have this entry in my config/routes.rb file:
map.namespace :music_service_admin do |music_service_admin|
music_service_admin.resources :users, :as => :teachers
end
Which gives me urls like
/music_service_admin/teachers
/music_service_admin/teachers/123
etc
I just had a bug where i had accidentally used /music_service_admin/users in an ajax call. I missed the bug because on my local machine, in development OR production mode, both these routes work: I can use ALL of the /music_service_admin/teachers routes with "/users" instead of "/teachers", and they behave the same.
On our server, however, it will only accept the /music_service_admin/teachers routes - the /music_service_admin/users urls aren't recognised and therefore 404.
In both instances (server and local), if i look at rake routes it only has routes for the /music_service_admin/teachers urls: it doesn't have any for /music_service_admin/users. So, according to rake routes, i'd expect /music_service_admin/users to NOT work on my machine. So i guess it's my local rails that's anomalous, and the server is behaving as expected.
Any ideas why it might be different?

Where is the default "Welcome Aboard" page located in my app?

I scoured my app's directories, and I can't find the html page for the default rails Welcome Aboard page. I also cannot find a route for the default Welcome Aboard page in routes.rb. How does my rails app route http://localhost:3000/ to a non-existent page in my app?
The rails server produces this information:
Started GET "/" for 127.0.0.1 at 2013-07-31 02:00:13 -0600
Processing by Rails::WelcomeController#index as HTML
Rendered /Users/7stud/.rvm/gems/ruby-2.0.0-p247#railstutorial_rails_4_0/gems/railties-4.0.0/lib/rails/templates/rails/welcome/index.html.erb (0.1ms)
Completed 200 OK in 3ms (Views: 2.5ms | ActiveRecord: 0.0ms)
So it looks to me like there is a controller buried in a gem somewhere that handles the request.
Since Rails 4, the "Welcome aboard" page is no longer located in public/index.html. It is - as you've already detected - located inside one of the Rails gems.
So you already answered the question yourself; the "Welcome aboard" page is - in your case - located at /Users/7stud/.rvm/gems/ruby-2.0.0-p247#railstutorial_rails_4_0/gems/railties-4.0.0/lib/rails/templates/rails/welcome/index.html.erb
To get rid of it, following the instructions on the page. Basically they are:
Create a controller
Add a root route in config/routes.rb to route to that newly created controller.
As for how the request to your application ends up at a controller inside railties, let's dig into the gem: Inside Rails::Application::Finisher we find this:
initializer :add_builtin_route do |app|
if Rails.env.development?
app.routes.append do
get '/rails/info/properties' => "rails/info#properties"
get '/rails/info/routes' => "rails/info#routes"
get '/rails/info' => "rails/info#index"
get '/' => "rails/welcome#index"
end
end
end
This block adds a few routes to your application when running in development mode - one of those is the route to the "Welcome aboard" action: get '/' => "rails/welcome#index"
This - like any other initializer - is done when your start your application server (running rails server or however you do it). In the case of Finisher, all its initializer are run after all other initializers are run.
Note how the routes are appended so that they are appear last in the Routeset. This, combined with the fact that Rails uses the first matching route it finds, ensures those default routes will only get used if no other route is defined.

Namespaced controllers not working, RoutingError: wrong constant name

I'm trying to setup a subdirectory in my Rails 3.2.3 app to service API requests at: http://example.com/api
I have created a directory like: app/controllers/api/
and I'm following the standard convention for implementing the namespaced controllers:
module Api
class GroupsController < ApplicationController
# RESTful verbs implemented here
end
end
I've setup a namespaced route like this:
namespace :api, defaults: {format: 'json'} do
resources :groups
end
However requests to http://example.com/api/groups.json result in the following exception:
ActionController::RoutingError (wrong constant name groups):
app/controllers/api/groups_controller.rb:2:in `<module:Api>'
app/controllers/api/groups_controller.rb:1:in `<top (required)>'
As you can see, it appears that the name "groups" here isn't valid because it's lowercase. I have no idea where this is coming from though.
I have read in a few places that a version of the right-aws gem was breaking the String#camelize method and causing similar errors. However I have confirmed that this gem is not present in my Rails application's stack.
Been slamming my head against this for some time. Has anyone else ever hit this problem?
EDIT: pasted output from $ rake routes:
root / welcome#index
api_groups GET /api/groups(.:format) api/groups#index {:format=>"json"}
POST /api/groups(.:format) api/groups#create {:format=>"json"}
new_api_group GET /api/groups/new(.:format) api/groups#new {:format=>"json"}
edit_api_group GET /api/groups/:id/edit(.:format) api/groups#edit {:format=>"json"}
api_group GET /api/groups/:id(.:format) api/groups#show {:format=>"json"}
PUT /api/groups/:id(.:format) api/groups#update {:format=>"json"}
DELETE /api/groups/:id(.:format) api/groups#destroy {:format=>"json"}
So the underlying cause of this was some code from an internal gem conflicting with the routing/namespacing of Rails.
However, the code in this gem was copied/pasted from an older version of Rails, so other people may hit this same issue.
The root cause was the gem had over-ridden the String#constantize inflection method that Rails extends on the String class. The version of the method this gem copied does not play well with the latest version of Rails and recent versions of Ruby.
So, the result was that "#{controller_name}".constantize returned a camelCase name, but the first character was lowercase.
Solution is to update this String#constantize method in the gem to match the latest version from Rails core, or to simply remove/rename that method within the gem's codebase.

Handling non-existent routes in Rails 3.1 application

I just switched to rails not long ago and I'm loving it. Everything works well in my rails 3.1 application, but now at the end I want to somehow handle routes like www.myapp.com/something (off course, I dont have something controller). I get a routing error when I visit this page, but I was wandering if there was a way to do something about it, even if it's only redirecting these routes to my root_url. I tried to find the answer online with no luck.
Yes, you can put a globbing route at the very end of your routes.rb to catch all misses:
match '/*paths', :to => 'some_controller#some_action'
in your Controller / action you can access the globbed path with
params[:paths]
more information http://guides.rubyonrails.org/routing.html#route-globbing
of course you can redirect without using an extra controller by using the redirect inline rack endpoint
match '/*paths' => redirect('/')

How to override Rails 3.1 "Routing Error" when using engines with glob routes?

I'm converting a legacy app to Rails 3.1. The new app uses an engine that provides a glob route:
# myengine/config/routes.rb
Rails.application.routes.draw do
match 'foo/bar/*path' => 'myengine/foobar#index', :format => false
end
The legacy app used a final catchall wildcard route to provide custom handling (rather than the familiar Rails "Routing Error" page) for otherwise unmatched routes:
# myapp/config/routes.rb
Myapp::application.routes.draw do
# ...
match '*path' => 'failures#index', :format => false
end
Somehow this catchall route is interfering with the engine's route. If I comment out the app's catchall route, the engine's route works fine. But if I leave it in the engine route is never matched and the app's catchall route to failures#index is used instead:
Started GET "/foo/bar//projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml" for 10.71.1.136 at 2011-08-02 15:46:48 -0700
Processing by FailuresController#index as JS
Parameters: {"path"=>"foo/bar/projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml"}
Rendered failures/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 47ms (Views: 46.9ms)
How would one override the default Rails 3.1 routing error handler without breaking engine routes?
The right way to handle this used to be rescue_from and a custom error handler, rather than with an engines-hostile catchall route. However, custom error handlers are no longer supported in Rails 3.1 and this likely won't be fixed until Rails 3.2, if ever. If you need custom error handling and you use engines with routes, the vidibus-routing_error gem provides a workaround.
Another option is to put your custom error handler into a Rack endpoint at the bottom of your stack.

Resources