はじめに
共通管理メニュー内の[外部連携]で、
OAuth クライアントの作成 ができるようになりました。
今回は、Ruby on Rails(以下、Rails)で作成した顧客お問い合わせサイトから入力したデータを、 OAuth 2.0 の承認を経て、kintone API でデータを追加するサンプルを紹介します。
事前に必要なもの
開発手順
kintone アプリの作成
OAuth クライアントの設定
Rails クライアントアプリケーションの開発
Heroku へのデプロイ
動作確認
1. kintone アプリの作成
kintone アプリストアより、「お客様の声管理」で検索し、表示されたアプリを追加します。
このとき作成した kintone アプリのアプリ ID をメモしてください。Rails アプリケーションの作成時に利用します。
アプリ ID は、kintone アプリを開いたときの URL で確認できます。
https://{subdomain}.cybozu.com/k/{アプリ ID}
次のテーブルを参考にフィールドコードを設定します。
フィールドの種類
フィールド名
フィールドコード
ドロップダウン
収集媒体
received_via
ドロップダウン
カテゴリ
category
ドロップダウン
テナント名
tenant_name
文字列(複数行)
ご意見内容
opinion
kintone アプリの設定は以上です。
2. OAuth Clientの設定
kintone アプリの cybozu.com 共通管理ページより、外部連携の設定画面にて、OAuth クライアントの追加をクリックします。
操作方法の詳細は、
OAuth クライアントを追加する を参照してください。
「クライアント名」と「リダイレクトエンドポイント」を入力します。
「リダイレクトエンドポイント」は、サイトを Heroku へデプロイした際に決定します。
今の段階では、次の値を仮設定しておき、のちほど変更します。
仮のリダイレクトエンドポイント: https://localhost:3000/authorize(必ず https を指定してください)
「保存」すると、以下の情報が自動生成されます。
「クライアントID」と「クライアントシークレット」をメモしてください。Rails アプリケーションの作成時に利用します。
クライアント ID
クライアントシークレット
認可エンドポイント
トークンエンドポイント
連携利用ユーザーの設定をクリックします。
API 利用を許可するユーザーを選択し、設定を保存します。
以上で OAuth クライアントの設定は終了です。
3. Rails クライアントアプリケーションの開発
Ruby on Rails でクライアントアプリケーションを開発していきます。
ステップ 1
ターミナルを開き、次のコマンドを実行して、Rails のアプリケーションを作成します。
1
rails new customer-feedback
これにより、customer-feedback というプロジェクト名で Rails のアプリケーションのひな型が生成されます。
以下のコマンドでローカルサーバーを起動し、動作するか確認します。
サーバーが起動したら、ブラウザーにて http://localhost:3000
を開き、以下のように表示されたら成功です。
1
2
cd customer-feedback
rails server
注意事項
(Windows 環境)
SQLite3 で dlopen の関数が存在しないというエラーになった場合、以下コマンドを実施してください。
1
ridk exec pacman -S mingw-w64-x86_64-dlfcn
ステップ 2
今回は、OAuth2.0 を使うので、以下のように Gemfile に 2 つの gem を追加してください。
oauth2 は、OAuth リクエストを実行するために使用し、activerecord-session_store はセッションの情報をデータベースへ記録するために使用します。
1
2
gem 'oauth2'
gem 'activerecord-session_store'
ファイルを保存後、以下のコマンドを実行します。
次に以下のコマンドを実行し、セッションの保存用のデータベースを作成します。
1
2
rails generate active_record:session_migration
rails db:migrate
ステップ 3
続いて、以下のコマンドで、「home」、「auth」と「feedbacks」というコントローラーを作成します。
1
2
3
rails generate controller home
rails generate controller auth
rails generate controller feedbacks
ステップ 4
次に「app」-「helpers」フォルダー内の「auth_helper.rb」を開き、以下を参考にコーディングします。
次の値は、利用環境に合わせて修正してください。
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# Rails x kintone OAuth client sample program
# Copyright (c) 201x Cybozu
#
# Licensed under the MIT License
# https://opensource.org/license/mit/
module AuthHelper
# kintone側のOAuth設定のクライアントID
CLIENT_ID = '{クライアントID}'
# kintone側のOAuth設定のクライアントシークレット
CLIENT_SECRET = '{クライアントシークレット}'
# kintoneのURL
SITE = 'https://{サブドメイン名}.cybozu.com'
# 認可エンドポイント
AUTHORIZE_URL = '/oauth2/authorization'
# トークンエンドポイント
TOKEN_URL = '/oauth2/token'
# APIアクセスのスコープ設定 read/write権限
SCOPES = ['k:app_record:read' ,'k:app_record:write' ]
# CSRF対策のランダムな値
STATE = SecureRandom.alphanumeric
# ログインURLの生成
def get_login_url
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
login_url = client.auth_code.authorize_url(:redirect_uri => authorize_url, # Railsの認可ページへのルートパス
:scope => SCOPES.join(' ' ),
:state => STATE)
end
# アクセストークン取得のための認可コードを送信
def get_token_from_code (auth_code)
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
token = client.auth_code.get_token(auth_code,
:redirect_uri => authorize_url,
:scope => SCOPES.join(' ' ))
end
# アクセストークンの取得
def get_access_token
# セッションから現在のアクセストークンハッシュを取得
token_hash = session[:kintone_token ]
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
token = OAuth2::AccessToken.from_hash(client, token_hash)
# アクセストークンが期限切れの場合、リフレッシュトークンからアクセストークンを取得
if token.expired?
new_token = token.refresh!
# 新アクセストークンをセッションへ保存
session[:kintone_token ] = new_token.to_hash
access_token = new_token
else
access_token = token
end
end
end
ステップ 5
今度は、「app」>「controllers」フォルダー内の「home_controller.rb」を以下のように編集します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Rails x kintone OAuth client sample program
# home_controller.rb
# Copyright (c) 201x Cybozu
#
# Licensed under the MIT License
# https://opensource.org/license/mit/
class HomeController < ApplicationController
include AuthHelper
def index
# 承認リンクの表示
@login_url = get_login_url
end
end
また、同フォルダー内の「auth_controller.rb」を以下を参考にコードを追加します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Rails x kintone OAuth client sample program
# auth_controller.rb
# Copyright (c) 201x Cybozu
#
# Licensed under the MIT License
# https://opensource.org/license/mit/
class AuthController < ApplicationController
include AuthHelper
# 認可コードからアクセストークンを取得
def gettoken
token = get_token_from_code params[:code ]
session[:kintone_token ] = token.to_hash
redirect_to feedbacks_url
end
end
最後に「feedbacks_controller.rb」を以下を参考に編集します。
次の値は、利用環境に合わせて修正してください。
12 行目 APP_ID:
1. kintone アプリの作成 で作成した kintone アプリのアプリ ID
13 行目 DOMAIN:kintone 環境のドメイン
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Rails x kintone OAuth client sample program
# feedback_controller.rb
# Copyright (c) 201x Cybozu
#
# Licensed under the MIT License
# https://opensource.org/license/mit/
class FeedbacksController < ApplicationController
include AuthHelper
# kintoenのアプリケーションID
APP_ID = '{アプリケーションID}'
DOMAIN = 'https://{サブドメイン名}.cybozu.com'
def new
# 初期ページロード状態では何もしない
end
def create
@feedback = Feedback.new(feedback_params)
if @feedback.save
token = get_access_token
if token
# アクセストークンがすでに取得されている場合、データをkintoneへポスト
# ハッシュ形式でレコードを設定
#
record = {
"app" => APP_ID,
"record" => {
"received_via" => {
"value" => feedback_params[:received_via ]
},
"category" => {
"value" => feedback_params[:category ]
},
"tenant_name" => {
"value" => feedback_params[:tenant_name ]
},
"opinion" => {
"value" => feedback_params[:opinion ]
}
}
}
response = token.post(" #{ DOMAIN} /k/v1/record.json" , {:body => record.to_json, :headers => {'Authorization' => "Bearer #{ token.token} " , 'Content-Type' => 'application/json' }})
redirect_to feedbacks_url
else
# アクセストークンが存在しない場合、ホームページへ戻り、承認のやり直し
#
redirect_to root_url
end
else
render 'new'
end
end
private
def feedback_params
# フォームからデータを取得
params.require(:feedback ).permit(:received_via , :category , :tenant_name , :opinion )
end
end
ステップ 6
「app」>「views」>「home」フォルダー内に「index.html.erb」ファイルを作成し、以下を参考にしてホームページを作成します。
「kinrtone へ接続」するためのリンクを設置しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--
* Rails x kintone OAuth client sample program
* home_controller.rb
* Copyright (c) 201x Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->
<h1>kintone OAuth 2.0 クライアントサンプル</h1>
<p>
<a href="<%= @login_url %>" role="button" id="connect-button">kintoneに接続</a>
</p>
次のようなページが生成されます。
次に、「app」>「views」>「feedbacks」フォルダー内に「new.html.erb」ファイルを作成し、以下を参考にして、お客様の声フォームを作成します。
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
31
32
33
34
35
36
37
38
39
40
41
<!--
* Rails x kintone OAuth client sample program
* home_controller.rb
* Copyright (c) 201x Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->
<h1>お客様の声</h1>
<%= form_for :feedback, url: feedbacks_path do |form| %>
<p>
<%= form.hidden_field :received_via, value: "WEBサイトから" %>
<%= form.label :category, "カテゴリ:" %><br>
<%= form.select :category,
[['---','---'],
['お褒め','お褒め'],
['お叱り','お叱り'],
['ご要望','ご要望'],
['その他','その他'],]
%>
</p>
<p>
<%= form.label :tenant_name, "テナント名:" %><br>
<%= form.select :tenant_name,
[['---',''],
['坊主食品','坊主食品'],
['サイボシューズ','サイボシューズ'],
['Cミュージックストア','Cミュージックストア'],
['施設','施設'],]
%>
</p>
<p>
<%= form.label :opinion, "ご意見内容:" %><br>
<%= form.text_area :opinion, size: "50x6" %>
</p>
<p>
<%= form.submit "送信" %>
</p>
<% end %>
次のようなページが生成されます。
ステップ 7
次に「config」フォルダー内の「routes.rb」ファイルを以下のように編集します。
1
2
3
4
5
6
7
Rails.application.routes.draw do
root 'home#index'
get '/authorize' => 'auth#gettoken'
get '/feedbacks' , to : 'feedbacks#new'
post '/feedbacks' , to : 'feedbacks#create'
resources :feedbacks
end
HTTP 動詞
パス
フィールドコード
目的
GET
/authorize
auth#gettoken
OAuth で kintone からのコールバック先
GET
/feedbacks
feedbacks#new
お客様の声を1つ作成するための HTML フォームを返す
POST
/feedbacks
feedbacks#create
お客様の声を1つ作成する
ステップ 8
次にさきほど指定した resource 名のモデルを生成します。
次のコマンドを実行し、「feedback」モデルを生成します。ここでは「feedbacks」ではなく、単数形の「feedback」を指定します。
1
rails generate model feedback received_via:string category:string tenant_name:string opinion:text
これにより以下のモデルが生成されます。
フィールド名
フィールドタイプ
received_via
string
category
string
tenant_name
string
opinion
text
以下のコマンドでマイグレーションを実行して、データベースにテーブルを作成します。
これで feedbacks テーブルがデータベース上に作成されます。
テスト環境での動作確認
以下のコマンドでローカルの Rails サーバーを起動し、エラーがないか確認します。
以下の画像のようにホームページが表示されれば、成功です。
ただし、「kintone に接続」リンクをクリックしても kintone 側の OAuth クライアントのコールバック URL の設定が異なるためエラーになります。
これは、Heroku へのデプロイが終了後、修正します。
以上で、Rails クライアントの開発は完了です。
4. Heroku へのデプロイ
今回は、テスト用のサーバーに Heroku を使用します。
Heroku では、データベースとして利用している SQLite3 はサポートされていません。
そのため、開発環境(ローカル)では SQLite3 を利用し、本番環境(Heroku)では PostgreSQL を利用するようにします。
Gemfile の SQLite3 に関する記述部分を以下のように書き換えます。
1
2
3
4
5
6
7
group :production do
gem 'pg'
end
group :development, :test do
gem 'sqlite3' , '~> 1.4'
end
以下のコマンドで、変更をローカルの開発環境に一度反映させます。
1
bundle install --without production
以下のコマンドで、今までのプロジェクトファイルの変更を Git レポジトリに反映させます。
1
2
git add -A
git commit -am "Update Gemfile for Heroku "
以下のコマンドで、Heroku アカウントにログインして、SSH キーを追加します。
1
2
heroku login
heroku keys:add
以下のコマンドで Heroku のアプリケーションを作成します。
Heroku 内に空のアプリケーションが作成されるので、次のコマンドで、作成した OAuth クライアントのアプリケーションを Heroku にデプロイします。
次のコマンドで Heroku 上にデータベースを作成します。
1
heroku run rake db:migrate
以上で Heroku のデプロイは完了です。
5. 動作確認
デプロイが完了したら、以下のコマンドで、アプリケーションを開きます。
以下の画像のように表示されれば成功です。
表示された Heroku のアプリケーションの URL をメモしてください。後述の OAuth クライアントの設定で利用します。
次に、kintone の OAuth クライアントの設定画面を開き、リダイレクトポイントの URL を Heroku のアプリケーションの URL に変更し、保存します。
「kintone OAuth 2.0 クライアントサンプル」フォームに戻り、「kintone に接続」リンクをクリックします。
kintone にログインしていない場合は、ログイン画面が表示されます。
「Ruby OAuth クライアントから次の操作が実行されます」というメッセージが表示されるので、「許可」します。
「お客様の声」フォームが表示されるので、各項目を任意に入力し「送信」ボタンをクリックします。
エラー画面が表示されず、フォームの各項目が未入力の状態にリセットされれば、成功です。
kintone アプリにレコードが追加されているか確認します。
OAuth2.0 を使って、Ruby on Rails の外部アプリから kintone API を使ってレコードの追加に成功したことを確認できました。
コードの解説
auth_helper.rb
auth_helper.rb は、認証に関する処理をまとめた helper ファイルです。
2. OAuth Clientの設定 で作成した OAuth クライアントアプリの値を元に各変数を設定します。
なお、設定したスコープの詳細は、
kintone の OAuth スコープ を参考にしてください。今回は、「read」、「write」権限を設定しています。
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# kintone側のOAuth設定のクライアントID
CLIENT_ID = '{クライアントID}'
# kintone側のOAuth設定のクライアントシークレット
CLIENT_SECRET = '{クライアントシークレット}'
# kintoneのURL
SITE = 'https://{サブドメイン名}.cybozu.com'
# 認可エンドポイント
AUTHORIZE_URL = '/oauth2/authorization'
# トークンエンドポイント
TOKEN_URL = '/oauth2/token'
# APIアクセスのスコープ設定 read/write権限
SCOPES = ['k:app_record:read' ,'k:app_record:write' ]
# CSRF対策のランダムな値
STATE = SecureRandom.alphanumeric
この関数では、ホームページの「承認」リンクに設定する URL を生成しています。
なお、authorize_url は、routes.rb で設定する authorize ページへのルートパスです。このリンクをクリックすると、kintone 側から、認可コードが送信されます。
oauth2 のプラグインのコマンドの詳細は、
A Ruby wrapper for the OAuth 2.0 protocol
を参照してください。
25
26
27
28
29
30
31
32
33
34
35
36
# ログインURLの生成
def get_login_url
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
login_url = client.auth_code.authorize_url(:redirect_uri => authorize_url, # Railsの認可ページへのルートパス
:scope => SCOPES.join(' ' ),
:state => STATE)
end
こちらの関数では、上記で取得した認可コードからアクセストークンを取得しています。
38
39
40
41
42
43
44
45
46
47
48
49
# アクセストークン取得のための認可コードを送信
def get_token_from_code (auth_code)
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
token = client.auth_code.get_token(auth_code,
:redirect_uri => authorize_url,
:scope => SCOPES.join(' ' ))
end
この関数では、セッションに保存してあるアクセストークンのハッシュから、アクセストークンを取得します。
すでにアクセストークンが期限切れの場合にリフレッシュトークンより、新アクセストークンを取得します。
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# アクセストークンの取得
def get_access_token
# セッションから現在のアクセストークンハッシュを取得
token_hash = session[:kintone_token ]
client = OAuth2::Client.new(CLIENT_ID,
CLIENT_SECRET,
:site => SITE,
:authorize_url => AUTHORIZE_URL,
:token_url => TOKEN_URL)
token = OAuth2::AccessToken.from_hash(client, token_hash)
# アクセストークンが期限切れの場合、リフレッシュトークンからアクセストークンを取得
if token.expired?
new_token = token.refresh!
# 新アクセストークンをセッションへ保存
session[:kintone_token ] = new_token.to_hash
access_token = new_token
else
access_token = token
end
end
home_controller.rb
承認リンクへの URL を取得して、ホームページにリンクを表示します。
11
12
13
14
15
def index
# 承認リンクの表示
@login_url = get_login_url
end
end
auth_controller.rb
kintone 側でコールバックされた後、返された認可コードから、アクセストークンを取得します。
12
13
14
15
16
def gettoken
token = get_token_from_code params[:code ]
session[:kintone_token ] = token.to_hash
redirect_to feedbacks_url
end
feedback_controller.rb
いったん、お客様フォームのデータをサイト内のデータベースに保存し、アクセストークンがすでに存在するかチェックします。
21
22
23
24
25
if @feedback.save
token = get_access_token
if token
# アクセストークンがすでに取得されている場合、データをkintoneへポスト
kintone に送信するデータをハッシュ形式で設定します。
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# ハッシュ形式でレコードを設定
#
record = {
"app" => APP_ID,
"record" => {
"received_via" => {
"value" => feedback_params[:received_via ]
},
"category" => {
"value" => feedback_params[:category ]
},
"tenant_name" => {
"value" => feedback_params[:tenant_name ]
},
"opinion" => {
"value" => feedback_params[:opinion ]
}
}
}
取得したアクセストークンで、kintone へデータをポストします。
47
response = token.post(" #{ DOMAIN} /k/v1/record.json" , {:body => record.to_json, :headers => {'Authorization' => "Bearer #{ token.token} " , 'Content-Type' => 'application/json' }})
アクセストークンが存在しない場合、ホームページの承認リンクへリダイレクトします。
51
52
53
# アクセストークンが存在しない場合、ホームページへ戻り、承認のやり直し
#
redirect_to root_url
お客様の声フォームより、各データを取得します。
60
61
62
63
64
private
def feedback_params
# フォームからデータを取得
params.require(:feedback ).permit(:received_via , :category , :tenant_name , :opinion )
end
routes.rb
routes.rb は、Rails アプリケーションのルーティング設定するファイルです。
リソース名に「feedbacks」を指定します。
また、ホームページには、承認リンクを表示するページを設定します。
おわりに
今回は Ruby on Rails によって、OAuth2.0 を使った外部連携をしました。
これを応用すれば、他の言語で開発した Web アプリケーションから OAuth2.0 を使った kintone API の利用も可能です。
OAuth2.0 による外部連携をすることで、ユーザ毎に kintone API へのアクセス権限をコントロールできます。
参照サイト