VBAからSalesforceのAPIを呼び出す現行の認証手順
SalesforceへログインしてレコードをまとめてExcelへ持ってくるVBAは、いまも現場で使われています。ただし当時の記事のようにユーザー名とパスワードをSOAP APIのlogin()へそのまま渡す書き方は、APIバージョン65.0以降では使えず、Summer '27ですべてのバージョンで廃止されます。認証をどう組み立て直すか、VBAでどこまでできるかを説明します。
なぜいまの書き方を直すのか
当時の記事では、SOAP APIのlogin()呼び出しへユーザー名とパスワードをそのまま埋め込み、セッションIDを取得する作りでした。動くこと自体は否定しませんが、認証情報をコードへ直接書く形は、いまのSalesforceが強く避けている書き方です。SOAP APIのlogin()は、APIバージョン65.0以降で使えず、Summer '27ですべてのバージョンで廃止されます。同じようにユーザー名とパスワードを渡すOAuth 2.0のユーザー名パスワードフローも、Summer '23以降に作成された組織では既定でブロックされています。この記事では、Connected Appを使った現行の認証の組み立て方と、VBAだけで完結しない部分を整理します。
ユーザー名パスワードフローがブロックされている理由
Summer '23以降に作成された組織では、OAuth 2.0のユーザー名パスワードフローが既定でブロックされます。有効化すること自体は可能ですが、Salesforceはこのフローを推奨していません。代わりに、OpenID Connectの動的クライアント登録、クライアント認証情報フロー、PKCE拡張つきのWebサーバーフローなどへ切り替えるよう案内されています。ExcelのVBAのように対話的なログイン画面を持たない自動処理では、サーバー間連携向けのJWTベアラーフローが現実的な選択肢です。
| 変更前 | 変更後 |
|---|---|
SOAP APIのlogin()にユーザー名とパスワードを直接渡す | Connected AppでJWTベアラーフローを設定し、署名済みJWTと引き換えにアクセストークンを得る |
| セッションIDをそのままAPI呼び出しに使う | アクセストークンとinstance_urlを使ってREST APIを呼ぶ |
JWTベアラーフローの準備
OAuth 2.0のJWTベアラーフローは、対話的なログインなしにアクセストークンを得るための仕組みです。クライアントが署名済みのJWTをSalesforceのトークンエンドポイントへ送り、Salesforceが署名を検証してからアクセストークンを発行します。準備するものは次の3つです。
X509証明書を用意する
4KB以下のX509証明書を作成します。大きい場合はDER形式へ圧縮します。
Connected Appに証明書を登録する
デジタル署名を使うオプションを有効にし、証明書をアップロードします。登録するとclient_idとclient_secretが発行されます。
RS256で署名したJWTを用意する
ヘッダーに
{"alg":"RS256"}、クレームにiss(client_id)・sub(ログインするユーザー名)・aud(ログインURL)・exp(有効期限)を含め、証明書の秘密鍵で署名します。
⚠️ このフローはリフレッシュトークンを発行しません。アクセストークンの有効期限が切れたら、署名済みJWTを使ってもう一度トークンエンドポイントを呼び直します。
VBAで実装するときの制約
トークンエンドポイントへのPOSTと、そのあとのREST API呼び出し自体は、VBAのHTTPオブジェクトでそのまま書けます。ただし、JWTのRS256署名はVBAの標準機能だけでは作れません。署名には秘密鍵を使ったRSA暗号処理が必要で、VBA単体にはその機能がないためです。実務では、署名済みJWTを外部のツールやサービスで作ってExcel側へ渡す、または証明書を扱えるライブラリをVBAから呼び出す構成になります。この記事では、その手前のトークン取得とAPI呼び出しの形を示します。
Dim http As Object Set http = CreateObject("MSXML2.XMLHTTP") Dim tokenUrl As String tokenUrl = "https://xxxx.my.salesforce.com/services/oauth2/token" Dim body As String body = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=" & signedJwt http.Open "POST", tokenUrl, False http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" http.send body If http.Status <> 200 Then MsgBox "token status:" & http.Status Exit Sub End If Dim tokenJson As String tokenJson = http.responseText
OAuth 2.0のJWTベアラーフローでアクセストークンを取得するVBAです。signedJwtには、あらかじめRS256で署名したJWTを渡します。
tokenUrlのxxxx部分は、実際にはご自身の組織のMy Domain名に置き換えます。レスポンスのJSONにはaccess_tokenとinstance_urlが含まれます。VBAには標準のJSONパーサーがないため、文字列処理か外部ライブラリで値を取り出します。
レコードを取得するVBA
アクセストークンとinstance_urlが手に入れば、あとはREST APIへのGETリクエストです。当時の記事ではAPIバージョン40.0を使っていました。Summer '26時点のAPIバージョンは67.0です。
Dim restTargetURL As String restTargetURL = instanceUrl & "/services/data/v67.0/query/?q=" & _ "SELECT+Id+FROM+Account" Dim httpObj As Object Set httpObj = CreateObject("MSXML2.XMLHTTP") httpObj.Open "GET", restTargetURL, False httpObj.setRequestHeader "Authorization", "Bearer " & accessToken httpObj.setRequestHeader "Accept", "application/json" httpObj.send MsgBox httpObj.responseText
取引先のIdをREST APIで取得するVBAです。accessTokenとinstanceUrlは、トークンエンドポイントのレスポンスから取り出した値です。
当時の記事のコードにあった、レスポンスから正規表現でサーバーのドメインを取り出す処理は不要になります。instance_urlがそのままクエリのベースURLです。
動作確認
| 呼び出し | 確認すること |
|---|---|
| トークンエンドポイントへのPOST | ステータスが200で、レスポンスJSONにaccess_tokenとinstance_urlが含まれること |
| クエリのGET | ステータスが200で、レスポンスJSONのtotalSizeとrecordsに取引先のIdが並ぶこと |
ここで間違えやすい
| 間違い | 何が起きるか |
|---|---|
| ユーザー名とパスワードをそのままログイン処理に埋め込む | SOAP APIのlogin()はAPIバージョン65.0以降で使えません。OAuthのユーザー名パスワードフローも、Summer '23以降に作成された組織では既定でブロックされ通りません |
| アクセストークンの有効期限切れに気づかない | REST API呼び出しがINVALID_SESSION_IDで失敗します。JWTベアラーフローはリフレッシュトークンを発行しないため、再度トークンエンドポイントを呼び直します |
| APIバージョンを古いまま(40.0など)で書く | 動くことはありますが、新しい機能やフィールドの挙動が反映されません。現行バージョンへ上げてください |
確認した環境
- 2026年9月/Salesforce Summer '26(APIバージョン67.0)時点の公式ドキュメントで、OAuthのフロー一覧とREST APIのクエリ形式を確認しています
- JWTの署名部分は、ご自身の環境に合わせて実装してください
まとめ
- ユーザー名とパスワードを直接渡すログインは、SOAP APIの
login()ではAPIバージョン65.0以降で使えず、OAuthのユーザー名パスワードフローもSummer '23以降に作成された組織では既定でブロックされます - 対話的なログインを伴わない自動処理には、OAuth 2.0のJWTベアラーフローが現行の選択肢です
- JWTの署名(RS256)はVBA単体では作れません。外部のツールやライブラリと組み合わせる前提で設計します
- REST APIのクエリは
/services/data/v67.0/query/?q=の形式で、認証はAuthorization: Bearerヘッダーで行います - APIバージョンは古いまま使わず、Summer '26時点の67.0へ上げてください
参考:当時の画面
記事を最初に書いた当時の画面です。いまの手順と違うところは、各画像の説明に書いています。
Salesforceの導入・運用についてご相談ください
導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。