DoorkeeperとDeviseでOAuth2によるログイン機能を作る


こちらの記事を参考にしました。
http://qiita.com/kyonsuke19101/items/407f3cdfec38d1108e9d

下記の内容は、参考程度でお願いします。
vagrant環境ではhttpsを用意していたいので、上手くいきませんでいた。
httpsを用意して、グローバルIPとドメインを用意して環境構築することをお勧めします。

```Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.define "doorkeeper_provider" do |node|
    node.vm.box = "centos_6.6"
    node.vm.hostname = "provider"
    node.vm.network :private_network, ip: "192.168.43.202"
  end
end

Vagrant.configure(2) do |config|
  config.vm.define "doorkeeper_client" do |node|
    node.vm.box = "centos_6.6"
    node.vm.hostname = "client"
    node.vm.network :private_network, ip: "192.168.43.203"
  end
end
```

Rubyのinstallはこちらを参照して下さい
You can check it here how to install ruby
http://qiita.com/joji/items/0dd0e4a113b65b4c9c09

#### Ruby setting in doorkeeper_provider in Both server

This is root user

```bash
gem install rails -v 4.2.7.1 --no-rdoc --no-ri
```

```bash
yum -y install mysql-sever
```

```bash
yum -y install mysql-devel
```

```
chown -R vagrant:vagrant /srv/www
```

```
exit
```

This is vagrant user from now.
in doorkeeper_provider

```bash
cd /srv/www
```

```bash
rails new doorkeeper_provider -d mysql
```

in doorkeeper_client

```bash
cd /srv/www
```

```bash
rails new doorkeeper_client -d mysql
```

####Gem setting in doorkeeper_provider

```bash
cd doorkeeper_provider/
```

```bash
vi Gemfile
```

Comment in

```Gemfile
gem 'therubyracer', platforms: :ruby
```

Add these lines

```Gemfile
gem 'devise'
gem 'doorkeeper'
gem 'omniauth'
gem 'oauth2'
```

```bash
bundle install
```

####Gem setting in doorkeeper_client

```bash
cd doorkeeper_client/
```

```bash
vi Gemfile
```

Comment in

```Gemfile
gem 'therubyracer', platforms: :ruby
```

Add these lines

```Gemfile
gem 'devise'
gem 'omniauth'
gem 'omniauth-oauth2'
gem 'oauth2'
```

```bash
bundle install
```

####Setting in doorkeeper_provider

```bash
rails g devise:install
```

```bash
rails g devise user
```

```bash
sudo service mysqld start
```

```bash
sudo chkconfig mysqld on
```

```bash
rake db:create
```

```bash
rake db:migrate
```

```bash
rails g doorkeeper:install
```

```bash
rails g doorkeeper:migration
```

```bash
rake db:migrate
```

```initializers/doorkeeper.rb
resource_owner_authenticator do
  current_user || warden.authenticate!(scope: :user)
  #fail "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
end
```

comment in

```config/routes.rb
root 'welcome#index'
```

You can access from this URL

```
http://192.168.43.202:3000/oauth/applications
```

![スクリーンショット 2016-08-30 22.17.25.png](https://qiita-image-store.s3.amazonaws.com/0/39073/8402a5c3-bbc8-0fc7-a1c2-d2f25ce5fb24.png "スクリーンショット 2016-08-30 22.17.25.png")

```app/controllers/api/api_controller.rb
module Api
  class ApiController < ::ApplicationController
    # ApplicationControllerでauthenticate_userを呼び出している場合、
    # ここでも処理がはしり、401エラーの元なので、切っておく
    before_action :authenticate_user!, only: []

    protected

    def current_resource_owner
      User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
    end
  end
end
```

```app/controllers/api/credentials_controller.rb
module Api
  class CredentialsController < ApiController
    # loginメソッドを外部から呼び出す際にdoorkeeperで認証処理する
    before_action :doorkeeper_authorize!

    # ユーザーのデータをjson形式で送る
    def login
      render json: { user: current_resource_owner }
    end
  end
end
```

####Setting in doorkeeper_client

```bash
rails g devise:install
```

```bash
rails g devise user
```

```bash
sudo service mysqld start
```

```bash
sudo chkconfig mysqld on
```

```bash
rake db:create
```

```bash
rake db:migrate
```

Add omniauthable

```user.rb
class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :recoverable,
         :rememberable, :trackable, :validatable, :confirmable, :omniauthable
end
```

```bash
rails g migration AddUidToUser
```

```bash
rake db:migrate
```

```bash
mkdir -p lib/omniauth/strategies
```

```lib/omniauth/strategies/doorkeeper.rb
module OmniAuth
  module Strategies
    class Doorkeeper < OmniAuth::Strategies::OAuth2
      option :name, :doorkeeper # strategyの名前　ここで指定した名前をdeviseで呼び出す
      option :client_options, site: "http://doorkeeper_provider", authorize_path: '/users/oauth/authorize'

      # uidとして設定するデータを指定
      uid { raw_info['user']['id'] }
      # providerから送られてきたデータの内、どれを使いたいか
      info do
        { email: raw_info['user']['email'] }
      end

      # providerのAPIを叩いて、データを取ってくる
      def raw_info
        @raw_info ||= access_token.get('/api/login.json').parsed
      end
    end
  end
end
```

You can create these data from here

```
http://192.168.43.202:3000/oauth/applications
```

```config/devise.rb
require File.expand_path('lib/omniauth/strategies/doorkeeper', Rails.root)
Devise.setup do |config|
      config.omniauth(:doorkeeper, '07d752c7ebf7a3bf574a10ef86b2b9c83c13697cd687a25d7faec96db872bc8f', '4d6b947a76c40b9aa854af62df04ee0edabe74641fc2bca6b38ad0606d0b1fb5')
  end
```

```config/routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
```

```bash
mkdir app/controllers/users
```

```app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def doorkeeper # メソッド名はstrategyで指定した名前
    @user = User.find_or_create_with_doorkeeper(request.env['omniauth.auth'])

    if @user.persisted?
      sign_in(@user)
      set_flash_message(:notice, :success, kind: 'doorkeeper') if is_navigational_format?
      redirect_to root_url
    else
      session['devise.doorkeeper_data'] = request.env['omniauth.auth']
      redirect_to root_url, alert: 'Doorkeeper ログインに失敗しました'
    end
  end
end
```

```app/model/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :omniauthable

  class << self
    def find_or_create_with_doorkeeper(auth)
      user = self.find_by(provider: auth.provider, uid: auth.uid )
      return user unless user.nil?

      self.create(
        email: auth.info.user.email,
        provider: auth.provider,
        uid: auth.uid,
        password: Devise.friendly_token[0, 20]
      )
    end
  end

end
```

```bash
rails g controller welcome
```

```bash
class WelcomeController < ApplicationController
  def index
  end
end
```

```config/routes.rb
root 'welcome#index'
```

```app/views/welcome/index.html.erb
<%= link_to 'login', user_doorkeeper_omniauth_authorize_path %>
```

####Start ruby both server

```bash
su -
```

```bash
rails s -b 0.0.0.0 -p 80
```

You have to change /etc/hosts in your local

```/etc/hosts
192.168.43.202 doorkeeper_provider
192.168.43.203 doorkeeper_client
```