devise_saml_authenticatable
devise_saml_authenticatable copied to clipboard
Handle missing users when saml_create_user = false
I think this might be similar to #122, but I'm not sure. My idp will authenticate all users in my company, however, I only want to grant access to my app for a select list of users. These users are in my users table, and everything works fine for a user present in the table. However, if a user is not present, devise redirects them back to the idp, which then redirects them back to the app, in a loop. What I'd like to do is if a user is not in the users table, then I want to just redirect them to a controller where I can display an error. Any suggestions?
I saw your comment on #122 and answered it there, so I'll copy it here:
What I'd like to happen is just redirect the user to a custom controller that can show them an error if they aren't present in my users table.
That I know how to solve! We use a custom Devise::FailureApp to handle failed responses in a situation like that:
class SignInFailure < Devise::FailureApp
def redirect_url
if params[:SAMLResponse].present?
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse])
invalid_user_session_url(invalid_user_email: response.name_id)
else
super
end
end
def respond
if http_auth?
http_auth
else
redirect
end
end
end
Then we have a route set up for the invalid session:
get '/users/invalid', to: 'users#invalid_saml_login', as: :invalid_user_session
And the controller:
before_action :authenticate_user!, except: [:invalid_saml_login]
and the template:
<div>
<%= params[:invalid_user_email] %> is not authorized. Please <%= link_to 'contact us', 'mailto:' %> or try to <%= link_to "login", new_user_session_path %> again.
</div>
and the devise configuration:
config.warden do |manager|
manager.failure_app = SignInFailure
end
@adamstegman thank you! I was searching for the wrong things. I did end up finding some clear documentation using your method. https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated
Another workarround that worked for me on my implementation is to override auth_options in controller and set recall option.
def auth_options
{ scope: resource_name, recall: 'users/sessions#new' }
end