Reputation: 69
I have a routing question in Rails (3.2.1).
I am using omniauth-saml for authentication (https://github.com/PracticallyGreen/omniauth-saml). The doc says:
"The service provider metadata used to ease configuration of the SAML SP in the IdP can be retrieved from http://example.com/auth/saml/metadata. Send this URL to the administrator of the IdP."
When I go to myserver.com/auth/saml/metadata, I get a routing error (No route matches). The only relevant route I have in routes.rb is /auth/:provider/callback. What route do I need to add to be able to access the metadata URL?
The authentication itself is working as expected. I am only having problems with the metadata.
Thanks a lot!
Upvotes: 1
Views: 1390
Reputation: 226
You can generate a metadata route by adding the following matcher to routes.rb*:
devise_scope :user do
match "/users/auth/:action/metadata",
constraints: { action: /saml/ },
to: "omniauth_callbacks",
as: :user_omniauth_metadata,
via: [:get, :post]
end
Resulting in the following route (sans "(.format)"):
user_omniauth_metadata GET|POST /users/auth/:action/metadata omniauth_callbacks#(?-mix:saml)
This is in addition to the standard omniauth routes:
user_omniauth_authorize GET|POST /users/auth/:provider omniauth_callbacks#passthru {:provider=>/saml/}
user_omniauth_callback GET|POST /users/auth/:action/callback omniauth_callbacks#(?-mix:saml)
which results from:
devise_for :users, controllers: { omniauth_callbacks: "omniauth_callbacks" }
Note: I am doing this with devise in the :user scope, but outside the scope it would look more like:
match( "/auth/:action/metadata",
constraints: { action: /saml/ },
to: "omniauth_callbacks",
as: :omniauth_metadata,
via: [:get, :post]
)
You also need to define a callback for "other_phase"; e.g. add something like the following to your SAML strategy
module OmniAuth
module Strategies
class Saml
include OmniAuth::Strategy
def other_phase
if on_path?("#{request_path}/metadata")
# omniauth does not set the strategy on the "other_phase"
@env['omniauth.strategy'] ||= self
setup_phase
response = OneLogin::RubySaml::Metadata.new
settings = OneLogin::RubySaml::Settings.new # set whatever params you want on this guy
Rack::Response.new(response.generate(settings), 200,
{ "Content-Type" => "application/xml" }).finish
else
call_app!
end
end
end
end
end
Upvotes: 1