devise_saml_authenticatable
devise_saml_authenticatable copied to clipboard
ActiveRecord::RecordInvalid "Password must exist"
Hi all,
I don't undestand why I've got this issue -> ActiveRecord::RecordInvalid "Password must exist" I use google app saml
Here is my routes.rb
Rails.application.routes.draw do
devise_for :users, skip: :saml_authenticatable, controllers: { registrations: "user/registrations", sessions: "user/sessions" }
as :user do
get 'experts/sign_up', to: 'user/registrations#new_expert'
end
# opt-in saml_authenticatable
devise_scope :user do
scope "users", controller: 'devise/saml_sessions' do
get :new, path: "saml/sign_in", as: :new_user_sso_session
post :create, path: "saml/auth", as: :user_sso_session
get :destroy, path: "sign_out", as: :destroy_user_sso_session
get :metadata, path: "saml/metadata", as: :metadata_user_sso_session
match :idp_sign_out, path: "saml/idp_sign_out", via: [:get, :post]
end
end
end
and my devise.rb
# Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
server_url = 'https://localhost:3000'
config.saml_configure do |settings|
# assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
settings.assertion_consumer_service_url = "#{server_url}/users/saml/auth"
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
settings.issuer = "#{server_url}/users/saml/metadata"
settings.authn_context = ""
settings.idp_slo_target_url = ""
# similar to https://accounts.google.com/o/saml2/idp?idpid=xxxxxx
settings.idp_sso_target_url = "https://accounts.google.com/o/saml2/idp?idpid=C02f7ydiq"
settings.idp_cert = <<-CERT.chomp
-----BEGIN CERTIFICATE-----
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAs87ETynlv8yuF3ivvYYz4vav6aoiD3V4/J4ewlq6XdirMNICPhKhQnr+3sdfNafy
LYLq4V2RgoZu7+y2/oq3quc7R6H83X1pTK75XXJcdgbskBmDcmdqUEL0Q/r19+KZsJipVdkeuGU8
NvVOHTIyvPySL0/8vLj/Z33aSibHCPguCr6oTLvcORqH+xY9JVR2tT1EGyyEsYUrsWLx2ICZL1tv
-----END CERTIFICATE-----
CERT
end
It sounds like there's a model validation for password. Can you share your model code too?
yes
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :saml_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# .....
end
validatable is adding that validation for you. If you want to allow either form of authentication, you'll need to write your own validations so that password is not required. You'll probably also want to only allow database login for people who have passwords!
How it is possible to generate a password for each sign up with saml_auth ? I don't understand the flow to create a user.
That's an option. Here's the create user flow: https://github.com/apokalipto/devise_saml_authenticatable/blob/master/lib/devise_saml_authenticatable/model.rb#L54-L66.
If you set devise.saml_create_user = true, you can set devise.saml_update_resource_hook to be a proc that accepts the user and generates a password. In config/initializers/devise.rb:
Devise.setup do |config|
config.saml_create_user = true
config.saml_update_resource_hook = ->(user, response, auth_value) {
# Maintain the default behavior of setting attributes from the SAML response
Devise.saml_default_update_resource_hook.call(user, response, auth_value)
# Add your behavior to generate a password
user.update!(password: '12345')
}
end
I have still this error :(
AbstractController::ActionNotFound (The action 'create' could not be found for Devise::SamlSessionsController):
That's surprising, because the Devise::SamlSessionsController inherits from Devise::SessionsController, which definitely implements create. Have you modified either of those classes in your codebase?
@adamstegman yes I have override devise controller like this.
class User::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
def new
@list_email = params[:email]
super
end
def new_expert
new
end
# POST /resource
def create
super
end
# GET /resource/edit
# def edit
# super
# end
# PUT /resource
# def update
# super
# end
# DELETE /resource
# def destroy
# super
# end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# end
protected
# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_up_params
# devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
# end
# If you have extra params to permit, append them to the sanitizer.
# def configure_account_update_params
# devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
# end
#def after_sign_up_path_for(resource)
# end
# The path used after sign up.
# def after_sign_up_path_for(resource)
# super(resource)
# end
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
end
and my routes.rb is
devise_for :users, skip: :saml_authenticatable, controllers: { registrations: "user/registrations", sessions: "user/sessions" }
as :user do
get 'experts/sign_up', to: 'user/registrations#new_expert'
end
- Why do you have
skip: :saml_authenticatablein your routes? I'm not sure that's causing the error, but it does seem odd. - Have you made any changes to the
Devise::SamlSessionsControllerorDevise::SessionsControllerclasses?
it seems from the validatable module. had to allow null on the password db column and add to the devise model:
def password_required?
false
end