如何在 Azure AD 上使用 SSO 设置 RoR 应用程序
How to setup a RoR application with SSO on Azure AD
我正在努力为 omniauth 策略在 Rails、ActiveAdmin application which uses Devise for authentication. I am using the Azure AD strategy 上设置 Ruby。
我在 config/initializers/devise.rb
中添加了 omniauth 策略:
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 and https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview 不再向我显示有关如何修复它的任何线索。
任何人都可以帮助我解决我做错的地方吗?
我认为你不需要这一行:
get 'sign_in', :to => 'devise/sign_in', as: :new_admin_user_session
在 Devise Docs 上是说如果你使用:
devise_for :admin_users
Devise会自动创建登录路由,所以你只需要使用:
<%= link_to "Sign in with AzureAD", admin_user_omniauth_authorize_path(:azure_activedirectory) %>
希望对你有帮助:)
更新
登录时,您可以指定希望用户重定向到的路径,如您所见here and here,为此您可以在应用程序控制器上指定如下方法:
def after_sign_in_path_for(resource)
current_user_path
end
和
def after_sign_out_path_for(resource_or_scope)
request.referrer
end
更新 2
您正在从“/”重定向到“/admin”,因为您的 config/routes.rb
上的这一行
root to: redirect('/admin')
这是设置应用程序的根目录,默认为“/”为“/admin”。如果您删除此行,rails 会将您的应用程序的根识别为“/”。
我们在项目上做了更多的工作,能够解决 Azure AD 身份验证问题。然而,我们 运行 有一些东西。
默认情况下,azure 活动目录策略生成不带下划线的路由。因此确保用于身份验证的模型使用:
omniauth_providers: [:azureactivedirectory]
该模型还扩展了字段 "provider" 和 "uid"。
Devise 会在页面上添加一个link (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)
...
...
app/models/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
app/controllers/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
我正在努力为 omniauth 策略在 Rails、ActiveAdmin application which uses Devise for authentication. I am using the Azure AD strategy 上设置 Ruby。
我在 config/initializers/devise.rb
中添加了 omniauth 策略:
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 and https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview 不再向我显示有关如何修复它的任何线索。
任何人都可以帮助我解决我做错的地方吗?
我认为你不需要这一行:
get 'sign_in', :to => 'devise/sign_in', as: :new_admin_user_session
在 Devise Docs 上是说如果你使用:
devise_for :admin_users
Devise会自动创建登录路由,所以你只需要使用:
<%= link_to "Sign in with AzureAD", admin_user_omniauth_authorize_path(:azure_activedirectory) %>
希望对你有帮助:)
更新
登录时,您可以指定希望用户重定向到的路径,如您所见here and here,为此您可以在应用程序控制器上指定如下方法:
def after_sign_in_path_for(resource)
current_user_path
end
和
def after_sign_out_path_for(resource_or_scope)
request.referrer
end
更新 2
您正在从“/”重定向到“/admin”,因为您的 config/routes.rb
上的这一行root to: redirect('/admin')
这是设置应用程序的根目录,默认为“/”为“/admin”。如果您删除此行,rails 会将您的应用程序的根识别为“/”。
我们在项目上做了更多的工作,能够解决 Azure AD 身份验证问题。然而,我们 运行 有一些东西。
默认情况下,azure 活动目录策略生成不带下划线的路由。因此确保用于身份验证的模型使用:
omniauth_providers: [:azureactivedirectory]
该模型还扩展了字段 "provider" 和 "uid"。
Devise 会在页面上添加一个link (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)
...
...
app/models/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
app/controllers/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