Apps ScriptからSalesforceへ取引先を登録する手順
ユーザー名パスワードフローは新規組織で既定でブロックされています。Apps ScriptからSalesforceへ書き込む認証をクライアントクレデンシャルフローへ直し、コードに鍵を書かない実装を説明します。
なぜApps Scriptから直接書き込むのか
Googleスプレッドシートに入力した行を、そのままSalesforceの取引先として登録したい場面があります。Web-to-Leadのような受け皿が使えない社内シートが起点のときや、シート側で加工した値をそのまま流し込みたいときです。Apps ScriptからSalesforceのREST APIを直接呼べば、間に別のサービスを挟まずに実装できます。
ユーザー名パスワードフローはもう使えない
以前はUrlFetchAppで grant_type=password を指定し、ユーザー名とパスワードをそのままPOSTする実装がよく使われていました。この方法は、いまは新規組織で既定のまま動きません。Summer '23以降に作成された組織では、OAuth 2.0のユーザー名パスワードフローが既定でブロックされています。有効化するには、設定の「OAuthおよびOpenID Connect設定」で管理者が明示的にオンにする必要があります。
Salesforceはこのフローを安全でないとし、推奨していません。既存の組織で有効になっていても、新しい連携をこの方式で作るのは避けます。
いまの選び方はクライアントクレデンシャルフロー
Apps Scriptのようにユーザーの操作を挟まず、決まった処理を定期的に流すだけなら、OAuth 2.0クライアントクレデンシャルフローが向いています。クライアントIDとクライアントシークレットだけでアクセストークンを得られ、証明書の管理が要りません。
証明書を使うJWTベアラーフローという選択肢もありますが、秘密鍵の発行と保管が増える分、単純な定期連携にはクライアントクレデンシャルフローのほうが構成が軽くなります。個々のユーザーとしてログインする必要がある場合は、認可コードフローを使います。
接続アプリを準備する
外部クライアントアプリを作る
設定のクイック検索で「外部クライアントアプリ」を開き、新規作成します。外部クライアントアプリは、従来の「接続アプリケーション」とは別の新しい仕組みです。
OAuth設定を有効化する
コールバックURLを1つ入力し、スコープに「api」を追加します。
クライアントクレデンシャルフローを有効化する
ポリシーで「クライアントクレデンシャルフローを有効化」をオンにし、実行ユーザーに、必要な権限だけを与えた専用のインテグレーションユーザーを割り当てます。
コンシューマ鍵とシークレットを控える
保存後に表示されるコンシューマ鍵・コンシューマシークレットを、次の節で使います。
⚠️ 実行ユーザーに管理者権限のユーザーをそのまま割り当てないでください。取引先の作成だけができる、絞った権限セットのユーザーにします。
認証情報をコードに直書きしない
クライアントIDとシークレットを .gs のソースに直接書くと、プロジェクトを共有した相手やコピーを取った相手にも見えてしまいます。Apps Scriptにはプロジェクトごとの設定値を保存する「スクリプト プロパティ」があり、PropertiesService から読み出せます。ソースには入れず、プロジェクトの設定画面から登録します。
Apps Scriptの実装
function getAccessToken_() { var props = PropertiesService.getScriptProperties(); var response = UrlFetchApp.fetch( 'https://xxxx.my.salesforce.com/services/oauth2/token', { method: 'post', payload: { grant_type: 'client_credentials', client_id: props.getProperty('SF_CLIENT_ID'), client_secret: props.getProperty('SF_CLIENT_SECRET') }, muteHttpExceptions: true } ); return JSON.parse(response.getContentText()); }
スクリプトプロパティからクライアントIDとシークレットを読み、クライアントクレデンシャルフローでアクセストークンを取得します。
function insertAccount() { var auth = getAccessToken_(); var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Account'); var name = sheet.getRange('A2').getValue(); var response = UrlFetchApp.fetch( auth.instance_url + '/services/data/v67.0/sobjects/Account/', { method: 'post', contentType: 'application/json', headers: { Authorization: 'Bearer ' + auth.access_token }, payload: JSON.stringify({ Name: name }), muteHttpExceptions: true } ); Logger.log(response.getContentText()); }
シートのA2セルの値を、取引先のName項目として1件登録します。
muteHttpExceptions: true を付け、レスポンスをログに出しています。エラーを黙って握りつぶす実装にすると、登録できていないことに気づけません。
動作確認
シートに値を入れる
Accountシートの A2 セルに、登録したい取引先名を入力します。
スクリプトを実行する
Apps Scriptのエディタで関数「insertAccount」を選び、実行します。
実行ログを確認する
返ってきたJSONに
idが含まれていれば登録成功です。エラーならerrorCodeの内容を見ます。Salesforce側で確認する
取引先の一覧、またはREST APIのクエリで、登録した名前のレコードがあるかを確かめます。
ここで間違えやすい
| 間違い | 何が起きるか |
|---|---|
grant_type を password のまま残す | 新規組織では既定でブロックされ、認証エラーになります |
| 外部クライアントアプリでクライアントクレデンシャルフローを有効化し忘れる | トークン取得の時点で unsupported_grant_type になります |
| スクリプトプロパティを設定し忘れる | クライアントIDが null のまま送られ、認証エラーになります |
| クライアントIDとシークレットをソースに直書きする | プロジェクトを共有・コピーした相手にも認証情報が見えます |
catch でエラーを握りつぶす | 登録に失敗していても気づけません |
確認した環境
- 2026年9月/Salesforce Summer '26(APIバージョン67.0)時点の公式ヘルプで、ユーザー名パスワードフローの既定ブロックとクライアントクレデンシャルフローの仕様を確認しています
- コードはAPIバージョン67.0で書いています
まとめ
- ユーザー名パスワードフローは、Summer '23以降に作成された組織では既定でブロックされています
- Apps Scriptのような定期連携には、クライアントクレデンシャルフローが軽い構成で使えます
- 外部クライアントアプリでクライアントクレデンシャルフローを有効化し、専用のインテグレーションユーザーを割り当てます
- クライアントIDとシークレットは、ソースに書かずスクリプトプロパティに保存します
- エラーを握りつぶさず、レスポンスをログへ出す実装にします
Salesforceの導入・運用についてご相談ください
導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。