如何在Azure上使用SSO设置RoR应用程序
我正在努力设置Ruby on Rails,ActiveAdmin应用程序使用Devise进行身份验证。我正在使用Azure AD strategy进行omniauth策略。如何在Azure上使用SSO设置RoR应用程序
我已经加入omniauth策略config/initializers/devise.rb
:
config.omniauth :azure_activedirectory, 'app id', 'azure tenant id'
新增的Users::OmniauthCallbacksContoller
:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def azure_activedirectory
@user = AdminUser.from_omniauth(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => 'azure_activedirectory') if is_navigational_format?
else
session['devise.azure_activedirectory_data'] = request.env['omniauth.auth']
redirect_to new_admin_user_registration_url
end
end
def failure
redirect_to root_path
end
end
,并添加回调路线routes.rb
:
Rails.application.routes.draw do
devise_config = ActiveAdmin::Devise.config
devise_config[:controllers][:omniauth_callbacks] = 'users/omniauth_callbacks'
devise_for :admin_users, devise_config
devise_scope :admin_user do
get 'sign_in', :to => 'devise/sign_in', as: :new_admin_user_session
get 'sign_out', :to => 'devise/sign_out', :as => :destroy_admin_user_session
end
ActiveAdmin.routes(self)
root to: redirect('/admin')
end
新增的from_omniauth
方法models/admin_user
:
class AdminUser < ActiveRecord::Base
devise :trackable, :omniauthable, omniauth_providers: [:azure_activedirectory]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
end
但这一切,当我运行该应用程序我得到的是错误:The action 'sign_in' could not be found for Users::OmniauthCallbacksController
我在结束了,我不知道还有什么我必须做的就是它的工作。 https://github.com/AzureAD/omniauth-azure-activedirectory和https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview对于我如何修复它不再显示任何线索。
任何人都可以帮我解决我做错的事吗?
我们一直在研究这个项目,并且能够解决Azure AD身份验证问题。然而,我们遇到了一些问题。
默认情况下,azure Active Directory策略会生成没有下划线的路由。因此请确保用于身份验证的模型使用:
omniauth_providers: [:azureactivedirectory]
该模型还扩展了字段“provider”和“uid”。
设计将在页面上添加一个链接(c.q.按钮)来登录。但我们的目标是仅支持omniauth身份验证,因此不需要额外的登录页面。为了达到这个目的,我们添加了一个重定向来获得设计,将身份验证直接转发给Azure提供商。
更改映射时(在config/initializers/device.rb中)也要小心。我们添加了一种解决方法,以防Devise无法找到api作用域的认证失败处理程序。在我们的例子中,我们结束了一个循环,由于映射的原因,我们的应用程序没有正确设置认证。我们的应用程序指示我们到Azure进行身份验证,而Azure的重定向我们回,因为我们已经验证,其次是应用指导我们...等
下面是一对夫妇的代码片段,可能是有用的:
的config/routes.rb中
Rails.application.routes.draw do
devise_config = ActiveAdmin::Devise.config
# see https://github.com/activeadmin/activeadmin/wiki/Log-in-through-OAuth-providers
# for how to combine settings in devise config from ActiveAdmin and SamlSessions
devise_config[:controllers][:omniauth_callbacks] = 'omniauth_callbacks'
devise_config[:skip] = [:sessions]
devise_for :admin_users, devise_config
devise_scope :admin_user do
get 'sign_in', :to => redirect('/admin/auth/azureactivedirectory'), :as => :new_admin_user_session
get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_admin_user_session
end
ActiveAdmin.routes(self)
...
...
应用程序/模型/ admin_user.rb
class AdminUser < ActiveRecord::Base
devise :trackable, :omniauthable, omniauth_providers: [:azureactivedirectory]
def self.from_omniauth(auth)
where(provider: auth['provider'], uid: auth['uid']).first_or_create do |user|
user.email = auth['info']['email']
end
end
end
应用程序/控制器/ omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_filter :verify_authenticity_token
def azureactivedirectory
@user = AdminUser.from_omniauth(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, :kind => 'azure_activedirectory') if is_navigational_format?
else
session['devise.azure_activedirectory_data'] = request.env['omniauth.auth']
redirect_to new_admin_user_registration_url
end
end
def failure
redirect_to root_path
end
end
我不认为你需要这条线:
get 'sign_in', :to => 'devise/sign_in', as: :new_admin_user_session
在Devise Docs它的说法,如果你使用:
devise_for :admin_users
的设计会自动创建路由进行登录,所以你只需要使用:
<%= link_to "Sign in with AzureAD", admin_user_omniauth_authorize_path(:azure_activedirectory) %>
我希望它可以帮助你:)
UPDATE
您在登入时,您可以指定希望用户被重定向到的路径,你可以看到here和here,要做到这一点,你可以指定你的应用程序像这些方法控制器:
def after_sign_in_path_for(resource)
current_user_path
end
和
def after_sign_out_path_for(resource_or_scope)
request.referrer
end
UPDATE 2
将您从“/”重定向到“/管理”,因为这行你的config/routes.rb文件
root to: redirect('/admin')
这是设置你的应用程序的根,其默认情况下它“ /'到'/ admin'。如果您删除此行,则rails会将应用程序的根识别为“/”。
感谢您尝试帮助。太糟糕了,虽然这解决了错误,但引入了一个新问题:我从'/'重定向到'/ admin',反之亦然。 –
@MichaelSommer我编辑了我的答案,试图解决你的问题,希望现在适合你。 –
当我删除'root to:'人们不会被重定向到'/ admin',我不希望我的用户自己知道。我的根有一个api的入口,它使用了守望者而不是设计。 –