RailsでAPIでのOAuth2認証をdoorkeeper + deviseで実装する

RailsをAPIサーバーとしてアプリを開発する上で認証処理を実装する方法をメモしておきます。

# doorkeeper + devise というgemを使う
deviseというのはRailsでユーザー認証を実装するときによく使われるGemで、doorkeeperはOAuth2認証を実装するGemです。

この２つを組み合わせて、APIでのOAuth2認証を実装します。

## 必要なGemのインストール

必要なgemをGemfileに追加します。

```` ruby:Gemfile
# 認証機能を使うためのgem
gem 'devise'
gem 'omniauth'
gem 'doorkeeper'
gem 'oauth2'

````

その後にbundle installします。

```` 
$ bundle install

````

## deviseのセットアップ

以下のコマンドを実行します。
コマンドを実行するとdeviseに必要な設定ファイルが作成されます。

````
$ bundle exec rails g devise:install
````

そのあと、deviseでユーザー認証に対応したUserモデルを作成します。

````
$ bundle exec rails g devise user
$ bundle exec rake db:migrate
````

これでユーザー認証を行うためのUserモデルが作成されました。

## doorkeeperのセットアップ
次にOAtuh2認証に対応するためのdoorkeeperをセットアップします。

````
$ bundle exec rails g doorkeeper:install
$ bundle exec rails g doorkeeper:migration
$ bundle exec rake db:migrate

````

これでDoorkeeperに必要な設定ファイル・DBの作成は完了です。

次にDeviseでのユーザー認証に対応するためにinitializers/doorkeeper.rbのresource_owner_authenticatorブロックを以下のように変更します。

```` ruby:initializers/doorkeeper.rb
resource_owner_authenticator do
  current_user || warden.authenticate!(:scope => :user)
end

````

次にUserのemailとpasswordでのアクセストークン取得のために以下の設定を追記します。

````ruby:initializers/doorkeeper.rb

resource_owner_from_credentials do |routes|
    request.params[:user] = {:email => request.params[:username], :password => request.params[:password]}
    request.env["devise.allow_params_authentication"] = true
    request.env["warden"].authenticate!(:scope => :user)
  end
````

これで設定は以上になります。

# doorkeeperでのOAuth2認証の使い方

## アプリケーションの登録

doorkeeperではFacebookやTwitterのAPIのようにアプリケーションを登録でき、そのアプリケーションに対してApplication_id, Secret_id, Callback_urlが設定できます。
そしてのApplication_idとSecret_id、そして、ユーザーのemail,passwordを使ってaccess_tokenを取得します。

bundle exec rails s でRailsサーバーを立ち上げて、/oauth/applicationsにアクセスすると今登録されているアプリケーションの一覧が表示されます。

![Doorkeeper_applist.png](https://qiita-image-store.s3.amazonaws.com/1260/26205/8662189a-9ea8-ff92-979a-25140ae930f4.png)

New Applicationボタンを押すとアプリケーション作成フォームが表示されますので、そこでアプリケーション名とリダイレクトURLを入力すると、以下のようにアプリケーションが作成され、Application_idとSecret_keyが取得できます。

![Doorkeeper_created.png](https://qiita-image-store.s3.amazonaws.com/1260/26205/6cb8733a-14b5-f34f-16db-da212ad936e7.png)



access_tokenをもっていないクライアントからのアクセスを制限するのはControllerに対して設定を入れることで実現します。

````ruby
class Api::V1::ProductsController < Api::V1::ApiController
  before_action :doorkeeper_authorize! # Require access token for all actions

  # your actions
end

````


## APIでemail, passwordでのOAuth2認証のテスト
rubyの標準パッケージのirbで以下のスクリプトを実行していくとOAtuh2認証の確認が行えます。

````ruby
require 'oauth2'

client_id     = '...' # your client's id generated with rake db:setup
client_secret = '...' # your client's secret
site          = "http://localhost:3000" # your provider server, mine is running on localhost
user_email    = '...' 
user_password = '...'


client = OAuth2::Client.new(client_id, client_secret, :site => site)
token  = client.password.get_token(user_email, user_password)

token.get('/api/v1/controller/action') 

````

# 参考URL
https://github.com/doorkeeper-gem/doorkeeper
https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Resource-Owner-Password-Credentials-flow
https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-your-provider-with-OAuth2-gem
https://github.com/plataformatec/devise#getting-started