JQ Blog

Doorkeeper Gemについて

Doorkeeperとは

OAuth2による認証機能をアプリに追加するGemです。

インストール

  • Gem
1
gem 'doorkeeper'
  • db migration
1
2
3
rails generate doorkeeper:install
rails generate doorkeeper:migration
bundle exec rake db:migrate

すると、自動にroutes.rbuse_doorkeeperが追加される。それから以下のルートが生成される。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GET  /oauth/authorize/:code(.:format)
GET   /oauth/authorize(.:format)
DELETE    /oauth/authorize(.:format)
POST  /oauth/authorize(.:format)
POST  /oauth/token(.:format)
POST  /oauth/revoke(.:format)
GET   /oauth/applications(.:format)
POST  /oauth/applications(.:format)
GET   /oauth/applications/new(.:format)
GET   /oauth/applications/:id/edit(.:format)
GET   /oauth/applications/:id(.:format)
PATCH /oauth/applications/:id(.:format)
PUT   /oauth/applications/:id(.:format)
DELETE    /oauth/applications/:id(.:format)
GET   /oauth/authorized_applications(.:format)
DELETE    /oauth/authorized_applications/:id(.:format)
GET   /oauth/token/info(.:format)

このルートを利用してアプリケーション毎認証を作ってアクセストークンなどを出したりするのもできる。

使い方

POST /oauth/authorizeで取得できるcodeを利用してPOST /oauth/tokenでアクセストークンを取得。

1
2
3
4
5
6
7
8
curl -F response_type=code \
-F grant_type=authorization_code \
-F client_id=9b36d8c0db59eff5038aea7a417d73e69aea75b41aac771816d2ef1b3109cc2f \
-F client_secret=d6ea27703957b69939b8104ed4524595e210cd2e79af587744a7eb6e58f5b3d2 \
-F code=456b683f8c1e5ccde47bdfac47ee3ec96e0f1bec2546734b92980dcb806df207 \
-F redirect_uri=http://localhost:3000 \
-F resource_owner_id=1 \
-X POST http://localhost:3000/oauth/token
  • parameter
    • grant_type
      • initializers/doorkeeper.rbに設定したgrant_flows
    • client_id
      • doorkeeperで作ったアプリのApplication Id
    • client_secret
      • doorkeeperで作ったアプリのSecret
    • code
      • 取得したコード
    • redirect_uri
      • doorkeeperで作ったアプリのCallback urls
    • resource_owner_id
      • initializers/doorkeeper.rbに設定したresource_owner_authenticator
  • 結果
1
{"access_token":"51ebde838061a87f4b2ea318386387f6d265a7328b3edfacb4b7deee7c3bfa73","token_type":"bearer","created_at":1481614521}

こういうふうにアクセストークンが取得できる。

その他

場合によってcurlじゃなくて他のライブラリを使うこともできる。

  • Oauth2

Oauth2 gemをインストールする。それから

1
2
client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, site: SITE_URL)
token = client.auth_code.get_token(CODE, :redirect_uri => REDIRECT_URL, :grant_type => 'client_credentials')

とすると、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
=> #<OAuth2::AccessToken:0x007fe8cfa51f58
 @client=
  #<OAuth2::Client:0x007fe8cea45330
   @auth_code=#<OAuth2::Strategy::AuthCode:0x007fe8cc25b3d8 @client=#<OAuth2::Client:0x007fe8cea45330 ...>>,
   @connection=
    #<Faraday::Connection:0x007fe8cc25a5c8
     @builder=
      #<Faraday::RackBuilder:0x007fe8cc2593a8
       @app=
        #<Faraday::Request::UrlEncoded:0x007fe8cecb7140
         @app=#<Faraday::Adapter::NetHttp:0x007fe8cecb7208 @app=#<Proc:0x007fe8cecb73e8@/Users/jo/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/faraday-0.12.2/lib/faraday/rack_builder.rb:154 (lambda)>, @config_block=nil, @connection_options={}>>,
       @handlers=[Faraday::Request::UrlEncoded, Faraday::Adapter::NetHttp]>,
     @default_parallel_manager=nil,
     @headers={"User-Agent"=>"Faraday v0.12.2"},
     @options=#<struct Faraday::RequestOptions params_encoder=nil, proxy=nil, bind=nil, timeout=nil, open_timeout=nil, boundary=nil, oauth=nil, context=nil>,
     @parallel_manager=nil,
     @params={},
     @proxy=nil,
     @ssl=#<struct Faraday::SSLOptions verify=nil, ca_file=nil, ca_path=nil, verify_mode=nil, cert_store=nil, client_cert=nil, client_key=nil, certificate=nil, private_key=nil, verify_depth=nil, version=nil>,
     @url_prefix=#<URI::HTTP http://localhost:3000/home/access_token>>,
   @id="c4af4d3ab6de658d55e9f0383cfec3703586f5802be991c82f3df99bc80ea853",
   @options={:authorize_url=>"/oauth/authorize", :token_url=>"/oauth/token", :token_method=>:post, :auth_scheme=>:request_body, :connection_opts=>{}, :connection_build=>nil, :max_redirects=>5, :raise_errors=>true},
   @secret="928d7220f1f112cf954871da5559a54a64eabcec9b56ffa87ad43a11a678b548",
   @site="http://localhost:3000/home/access_token">,
 @expires_at=1506062175,
 @expires_in=7200,
 @options={:mode=>:header, :header_format=>"Bearer %s", :param_name=>"access_token"},
 @params={"token_type"=>"bearer", "created_at"=>1506054975},
 @refresh_token=nil,
 @token="c7f79becd53a4f4e571b95dc9e075d39034f9e613505fdb844bd8e778eb8933c">

こういうresponseを取得できる。

  • RestClient

RestClient gemをインストールし、

1
2
client = RestClient.post 'http://localhost:3000/oauth/token', {grant_type: 'client_credentials', client_id: CLIENT_ID, client_secret: CLIENT_SECRET}
client.body

すると、

1
"{\"access_token\":\"7328d931953ce2a4db130d02575a95a80b47683c2b2f9619492285465bce4b9d\",\"token_type\":\"bearer\",\"expires_in\":7200,\"created_at\":1506055209}"

というresponseを取得できる。

Api連携

before_action :doorkeeper_authorize!を使って有効TokenのみアクセスできるようにApiと連携ができる。

1
2
3
class Api::BaseController < ActionController::API
  before_action :doorkeeper_authorize!
end

こういうふうに設定をしておく。

1
2
3
4
5
6
7
8
9
10
class Api::UsersController < Api::BaseController
  def show
    user = User.find(params[:id])
    if user.present?
      render json: {user: user}
    else
      render json: {user: "cannot found this user"}
    end
  end
end

ユーザー情報を取得するapiを試してみると、

1
2
3
4
5
6
client = OAuth2::Client.new("c4af4d3ab6de658d55e9f0383cfec3703586f5802be991c82f3df99bc80ea853", "928d7220f1f112cf954871da5559a54a64eabcec9b56ffa87ad43a11a678b548", site: "http://localhost:3000")
token = client.auth_code.get_token("536b065b6ae6ca9acdc71d33387b4e5e6dbdd5bcc6950f7fcb2e96fd307bc295", :redirect_uri => "http://localhost:3000/home/access_token", :grant_type => 'client_credentials')
user_info = token.get('/api/users/1')
body = ActiveSupport::JSON.decode user_info.body
user_email = body["user"]["email"]
=> "user@example.com"

簡単にデータが取れる。
トークン無しでアクセスしようとしたら、

1
2
RestClient.get 'http://localhost:3000/api/users/1'
=> RestClient::Unauthorized: 401 Unauthorized

こういうふうに接続できない。

Doorkeeper gemはすごく簡単にOAuth2による認証機能を実装できる。Doorkeeperと連携してさらにApiを作ったり、ログイン機能に認証機能をつけるなどの実装も可能になる。

参考

doorkeeper
Doorkeeper gem でOauth認証できるアプリケーションを作った後の事
【Rails5】Doorkeeper gemでOAuth2.0のためのAPIを作って、rubyクライアントで呼び出す