[Rails]SalesforceでOAuthのアクセストークンを取得してみる
業務で、SalesforceのOAuth認証機能をつけたので、
最低限の設定でひとまずアクセストークンを取得できるところまでをやっていきます。
OAuthの認証フローは、Salesforceでは複数パターン用意されています。
今回はよく見かける(?)、Salesforceの画面へ遷移してそこでID,Passwordでログインして権限を与える許可をするフロー(Web サーバフロー)で試してみます。
Salesforceアカウントを取得
- クライアントアプリ側のアカウント
- リソース側のアカウント
と二つ作成しておきます。
Salesforceは無料トライアルはあるものの、基本有料となっています。
しかし、Developer Editionという開発向けのプランがありこちらは無料で使えます。
なのでこちらを使っていきます。
アカウント設定
クライアントアプリ側として使うアカウントでOAuthの設定を行います。
左メニューのアプリケーション->アプリケーションマネージャで、右上の新規接続アプリケーションへ遷移します。
必須情報を入れて、OAuthの有効化にチェックを入れます。
OAuth範囲は今回はフルアクセスとします。
実際に業務で使うときは必要最低限の範囲を設定するのがいいかと思います。
OAuth認証実装
認証URLは以下のようになります。https://login.salesforce.com/services/oauth2/authorize
パラメータとして必須なのは
- response_type
- client_id
- redirect_uri
の3つです。
namespace :auth do
resource :salesforce, only: [:create], controller: 'salesforce' do
collection do
get "callback"
end
end
end
class Auth::SalesforceController < ApplicationController
def create
uri = URI("https://login.salesforce.com/services/oauth2/authorize")
# salesforce側でコールバックURLに127.0.0.1が使えないのでlocalhostを使っている
redirect_uri = "http://localhost#{callback_auth_salesforce_path}"
uri.query = {
response_type: "code",
client_id: ENV["SALESFORCE_CLIENT_ID"],
redirect_uri: redirect_uri
}.to_query
redirect_to(uri.to_s)
end
def callback
end
end
client_id
とredirect_uri
には以下をセットします。
- client_id
- 「コンシューマーの詳細を管理」へ遷移した先のコンシューマ鍵
- redirect_uri
- コールバックURL
これで、http://127.0.0.1:3003/auth/salesforce
へPOSTでリクエストするとsalesforceへリダイレクトします。
ここでリソース側のアカウントでログインしてみます。
その後アクセスを許可すると認可コードとともに
http://localhost:3003/auth/salesforce/callback?code=hogehoge
にリダイレクトされます。
認可コードからアクセストークンを取得します。
トークン要求エンドポイントにhttps://login.salesforce.com/services/oauth2/token
POSTします。
その時の必須パラメータは以下です。
- grant_type
- このフローの値は authorization_code である必要があります。
- client_id
- 接続アプリケーション定義の [コンシューマ鍵]。
- client_secret
- 接続アプリケーション定義の [コンシューマの秘密]。
- redirect_uri
- 接続アプリケーション定義の [コールバック URL]。
- code
- コンシューマがアクセストークンと更新トークンを取得するために使用する必要がある認証コード。
def callback
code = params[:code]
salesforce_oauth = SalesforceOauth.retrieve_access_token(code)
end
class SalesforceOauth
attr_reader :access_token
ACCESS_TOKEN_REQUEST_ENDPONT = "https://login.salesforce.com/services/oauth2/token"
class << self
def retrieve_access_token(code)
uri = URI(ACCESS_TOKEN_REQUEST_ENDPONT)
conn = Faraday.new(
headers: {
"Content-Type" => "application/x-www-form-urlencoded",
},
)
params = {
grant_type: "authorization_code",
client_id: client_id,
client_secret: client_secret,
redirect_uri: redirect_uri,
code: code,
}
response = conn.post(uri) do |req|
req.body = params.to_query
end
if response.status != 200
# TODO: エラー処理
Rails.logger.error(response.body)
raise response.body
end
parsed_response_body = JSON.parse(response.body)
new(parsed_response_body["access_token"])
end
def client_id
ENV["SALESFORCE_CLIENT_ID"]
end
def client_secret
ENV["SALESFORCE_CLIENT_SECRET"]
end
def redirect_uri
# salesforce側でコールバックURLに127.0.0.1が使えないのでlocalhostを使っている
"http://localhost#{Rails.application.routes.url_helpers.callback_auth_salesforce_path}"
end
end
def initialize(access_token)
@access_token = access_token
end
end
これでアクセストークンが取得できました。
アクセストークンで情報が取得できるか試してみる
試しに、取得したアクセストークンを使って何かデータを取得してみます。
以下のユーザー情報を取得してみます。
sub
, user_id
, name
,email
などなどユーザー情報が取得できるようです。
今回はgiven_nameだけ取ってみます。
def callback
code = params[:code]
salesforce_oauth = SalesforceOauth.retrieve_access_token(code)
salesforce_user_info = SalesforceUserInfo.retrieve(salesforce_oauth.access_token)
given_name = salesforce_user_info.given_name
render plain: "given_name: #{given_name}"
end
class SalesforceUserInfo
attr_reader :given_name
ENDPOINT = "https://login.salesforce.com/services/oauth2/userinfo"
class << self
def retrieve(access_token)
uri = URI(ENDPOINT)
conn = Faraday.new
params = {
access_token: access_token,
}
response = conn.get(uri, params)
if response.status != 200
# TODO: エラー
raise
end
parsed_response_body = JSON.parse(response.body)
new(
given_name: parsed_response_body["given_name"]
)
end
end
def initialize(given_name:)
@given_name = given_name
end
end
ブラウザでgiven_name
が表示されます。
これでアクセストークンを使って情報が取得できたことが確認できました。
記事中のコードは多少リファクタリングして以下に残しています。
アクセストークンの期限
実際に業務で使う場合には期限なども気にする必要が出てくるので注意です。
アクセストークンの有効期間は認証コードよりも長く、通常は数分~数時間です。期限が切れたアクセストークンの使用を試みると失敗します。その場合、クライアントは更新トークンを使用するか、認証フローを再開して新しいアクセストークンを取得する必要があります。
https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_tokens_scopes.htm&type=5
Discussion