Salesforceの認証に「OAuth 2.0 ユーザ名パスワードフロー」を使って下記のエラーが返ってきた場合、どこを確認し、どう対応すべきか?について書く。
{"error":"invalid_grant","error_description":"authentication failure"}
問題
ステップ 1: 認証を設定する | REST API 開発者ガイド | Salesforce Developers
上記ページにcurlコマンドで認証するサンプルがあったので、これを例に説明する。
curl https://MyDomainName.my.salesforce.com/services/oauth2/token \
-d 'grant_type=password' \
-d 'client_id=consumer-key' \
-d 'client_secret=consumer-secret' \
-d 'username=my-login@domain.com' \
-d 'password=my-password'
このコマンドを叩いた時に冒頭に書いたエラーが返ってくる場合がある。
(ちなみに、レスポンスのステータスコードは「400 Bad Request」)
OAuth 2.0 認証エラー
上記ページにエラーの原因がいくつか挙げられているが、単に「認証エラー(authentication failure)」で理由が明確でない。少なくとも「無効なユーザ」や「IP 制限または無効なログイン時間帯」ではないのか?となると、あと考えられるのはパスワードが間違っているくらいか?と考えてしまいがちである。
調査
しかし、Salesforceにログイン(この時点でパスワードは間違ってなかったことが確定)し、設定 > ID > ログイン履歴 を確認すると、「失敗:APIセキュリティトークンが必要です」というログが残っていた。
この場合curlコマンドでログインできなかった原因は、「コマンドを叩いたPCのIPが信頼済みIPアドレス(設定 > セキュリティ > ネットワークアクセス で確認可能)でなかったから」となる。
対応
仮にセキュリティートークンが"12345"だった場合、-d 'password=my-password'
ではなく-d 'password=my-password12345'
としてリクエストする。
公式ドキュメントによる解説は以下の通り。
特別なシナリオの OAuth 2.0 ユーザ名パスワードフロー
セキュリティトークンは、信頼されないネットワークから Salesforce にログインするためにパスワードの末尾に追加する必要のある鍵で、自動生成されます。認証要求を渡すときに、パスワードとトークンを連結します。
まあ、これも「パスワードが間違っていた」と言えなくもないのか...
セキュリティ的な都合上、あまり明確な理由を返せないからこのような表現になっているのかもしれません。
以上