Doorkeeper2.1.4でコンソールからOAuth2.0認証API用のアクセストークンを発行してみた
Doorkeeperを使うとデフォルトの認証画面を使うのが定番のようですが、自前で認証画面を用意したりRakeタスクでアクセストークンを発行したいことがあったりします。
ということで、Railsコンソールからアクセストークンの発行までやってみました。
Doorkeeper インストール
まずはRailsプロジェクトのGemfileにDoorkeeper gemを追加してbundle installします。
# Gemfile
gem 'doorkeeper'今回はdoorkeeper-2.1.4が入りました。
続いてActiveRecord用の設定&テーブルを作成します。
$ rails generate doorkeeper:install
$ rails generate doorkeeper:migration
$ rails db:migrateこうするとデータベースに
- oauth_applications
- oauth_access_grants
- oauth_access_tokens
というテーブルが作られます。
Doorkeeperを設定
Doorkeeperをインストールするとconfig/initializers/doorkeeper.rbに設定ファイルも作られます。
Deviseユーザーを認証する場合は
# config/initializers/doorkeeper.rb
resource_owner_authenticator do
current_user || warden.authenticate!(:scope => :user)
endという感じでresource_owner_authenticatorを設定します。
また、インストール時にconfig/routes.rbも更新されますが、今回はDoorkeeperのアプリケーションは使わないので元に戻しておきます。
OAuth2アプリケーションの作成
続いてRails ConsoleからOAuth2アプリケーションを作成します。
ActiveRecordの場合はDoorkeeper::Applicationオブジェクトを作ればOKです。
> client = Doorkeeper::Application.create(name: 'アプリケーション名', redirect_uri: '認証後のリダイレクトURL')作成したアプリケーションのID(Client ID)とClient Secretを確認します。
> client.uid
=> "094ce26134c0cbee97c91511b7f91137cb1963d7186066948b3126bb8e0f3ad76fce522e01634ee51e20954977c5b77f45b682c1ff4570a66598fcf19699d23b"
> client.secret
=> "49f947fceebbfd3c5e8100cbde8e410530e6a7a0d1c5a9af90705760968af4e6e719ec1776e49bf2f21673868f0ce2aa5d24fe697229e6fc6d3661614fded3cd"ということで無事OAuth2認証用アプリケーションが作成できました。
認証コードの生成
続いて認証コードの生成です。
認証コードの生成にはDoorkeeper::OAuth::CodeRequestクラスを使います。
params =
ActionController::Parameters.new(
client_id: client.uid,
redirect_uri: client.redirect_uri,
response_type: 'code'
)
pre_auth = Doorkeeper::OAuth::PreAuthorization.new(Doorkeeper.configuration, client, params)
request = Doorkeeper::OAuth::CodeRequest.new(pre_auth, user)
response = request.authorize # Doorkeeper::OAuth::CodeResponseオブジェクト
code = response.auth # Doorkeeper::OAuth::Authorization::Codeオブジェクト
grant = code.token # Doorkeeper::AccessGrantオブジェクトこんな感じでDoorkeeper::AccessGrantモデルのオブジェクトを取得します。
取得した認証コードを確認してみます。
> grant.token
=> "f001b3327b4f13f6aea35ffea3601f5d2eea0e18fa5393f928e25b52a314df36"アクセストークンの生成
認証コードを取得したので、続いてアクセストークンを生成します。
params =
ActionController::Parameters.new(
client_id: client.uid,
client_secret: client.secret,
code: grant.token,
grant_type: 'authorization_code',
redirect_uri: client.redirect_uri
)
request =
Doorkeeper::OAuth::AuthorizationCodeRequest.new(
Doorkeeper.configuration,
grant,
client,
params
)
response = request.authorize # Doorkeeper::OAuth::TokenResponseオブジェクト
access_token = response.token # Doorkeeper::AccessTokenオブジェクト取得したアクセストークンを確認してみます。
> access_token.token
=> "c8f32d02ea56979882ca8ee659a64b4088774a973655ba6cbf91ef1fcb0f739f"これでOAuth2認証に必要なアクセストークンが手に入りました。
OAuth2.0認証対応のAPIを作る
アクセストークンは作りましたが、APIがないと試せないのでGrapeを使って簡単なAPIを作ります
Grape gemをインストール
Gemfileにgrapeとgrape-active_model_serializersを追加してbundle installします。
# Gemfile
gem 'grape'
gem 'grape-active_model_serializers'バージョンはgrape-0.11.0, grape-active_model_serializers-1.3.2が入りました。
API用のディレクトリを設定
app/apiを読み込むようにします。
# config/application.rb
...
config.paths.add 'app/api', glob: '**/*.rb'
...サンプルAPIを作成
とりあえず簡単なAPIを作ります。
# app/api/api.rb
class API < Grape::API
prefix 'api'
format :json
formatter :json, Grape::Formatter::ActiveModelSerializers
content_type :json, 'application/json; charset=UTF-8'
mount V1::SampleAPI
end# app/api/v1/sample_api.rb
require 'doorkeeper/grape/helpers'
module V1
class SampleAPI < Grape::API
## OAuth2認証用の設定を追加
helpers Doorkeeper::Grape::Helpers
before { doorkeeper_authorize! }
version 'v1', using: :path
resource :samples do
get '/' do
{foo: :bar}
end
end
end
endサンプルAPIにアクセスしてみる
APIにアクセスしてみると401 Unauthorizedになっています。
$ curl -I http://localhost:3000/api/v1/samples/
HTTP/1.1 401 Unauthorized
...アクセストークンを使ってAPIにアクセスしてみる
アクセストークンの発行もAPIの用意もできたので、OAuth2 gemを使ってAPIを呼び出してみます。
require 'oauth2'
client_id = 'CLIENT_ID'
client_secret = 'CLIENT_SECRET'
site = 'http://localhost:3000'
client = OAuth2::Client.new(client_id, client_secret, :site => site)
access_token = 'ACCESS_TOKEN'
token = OAuth2::AccessToken.new(client, access_token)
response = token.get('/api/v1/samples')レスポンスの内容を確認してみます。
> JSON.parse(response.body)
=> {"foo"=>"bar"}ちゃんとOAuth2認証APIを呼び出すことができました。
まとめ
今回はDoorkeeper + GrapeでOAuth2認証APIを作ってみました。
認証機能付きAPIだと定番かと思いますのでよろしければご参考にどうぞ。
おまけ
今回GrapeでAPIを作りましたが、最初に試した時はGrapeのバージョンが古くて
undefined local variable or method `settings' for #<Grape::Endpoint:0x007fb15f9fa7c8>とか
undefined method `head' for #<Grape::Endpoint:0x007f9f172bd280>というエラーが出たりしました。
こういう時はbundle update grape grape-active_model_serializersでバージョンを上げればOKです。
また、grape-active_model_serializersのバージョンを上げるとactive_model_serializersのバージョンも上がります。
このとき古いDraperを使っている場合は
uninitialized constant ActiveModel::ArraySerializerSupportというエラーが出たりします。
そういう場合はbundle update draperでDraperのバージョンも上げましょう。