Rails
devise

devise で ActiveDirectory 認証

More than 3 years have passed since last update.

前提条件

以下の環境にて動作確認が行えました。

開発環境

  • Mac OS X Yosemite (10.10.3)
  • Bundler version 1.10.5
  • rbenv 0.4.0
  • ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin14]
  • mysql Ver 14.14 Distrib 5.6.24, for osx10.10 (x86_64)

Rails

  • rails (4.2.3)
  • net-ldap (0.11)
  • devise (3.5.1)
  • devise_ldap_authenticatable (0.8.5)

Active Directory

  • Windows Server 2012

devise のインストールと設定

Gemfile 追記

Gemfile
gem 'devise'
gem 'devise_ldap_authenticatable'

インストール

$ bundle install -j4 --path=vendor/bundle
$ rails g devise:install
$ rails g devise User
$ rails g devise_ldap_authenticatable:install

User モデル修正

app/models/user.rb
class User < ActiveRecord::Base
 devise :ldap_authenticatable, :rememberable, :trackable
end

マイグレーションファイル修正

デフォルトの email ログインを username ログインに修正。

db/migrate/YYYYMMDDhhmmss_devise_create_user.rb
class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## LDAP authenticatable
      t.string :username, null: false, default: "", unique: true
      ## Database authenticatable
      # t.string :email,              null: false, default: ""
      # t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      # t.string   :reset_password_token
      # t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :username,                unique: true
    # add_index :users, :email,                unique: true
    # add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

マイグレーション

$ rake db:migrate

devise 初期設定

修正箇所のみ。

config/initializers/devise.rb
config.ldap_logger = true
config.ldap_create_user = true
config.ldap_update_password = false
config.ldap_use_admin_to_bind = true
config.authentication_keys = [ :username ]

LDAP 設定

config/ldap.yml
development:
host: <Domain Controller を指定>
port: 389
attribute: sAMAccountName
base: dc=xxx,dc=xx,dc=xx
admin_user: "<bind user>"
admin_password: "bind user password"
ssl: false

admin_useradmin_password"" で括る必要があります。
デフォルトだと "" がありませんが、その状態だと以下のエラーが発生してかなりハマりました。。

Net::LDAP::LdapError (Invalid binding information)

ログイン用 view 作成

$ rails g devise:views

ログイン画面修正

  • :email => :username
  • email_field => text_field
app/views/devise/session/new.html.erb
<h2>Log in</h2>

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.label :username %><br />
    <%= f.text_field :username, autofocus: true %>
  </div>

  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <% if devise_mapping.rememberable? -%>
    <div class="field">
      <%= f.check_box :remember_me %>
      <%= f.label :remember_me %>
    </div>
  <% end -%>

  <div class="actions">
    <%= f.submit "Log in" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

ルーティング

設定

config/routes.rb
devise_for :users, only: [:sessions]

確認

rake routes

全ページ認証設定

app/controllers/application_controller.rb
before_action :authenticate_user!

ログアウトリンク設定

<%= link_to "Logout", destroy_user_session_path, method: :delete, :class => 'navbar-link' %>