CData Software Blog

クラウド連携のCData Software の技術ブログです。

GCP の OAuth 2.0 grant_type=refresh_token で「Token has been expired or revoked.」が発生する場合の対処方法

こんにちは。CData Software Japanリードエンジニアの杉本です。

ここ最近、GCP・BigQuery や Google Contacts などの連携利用でリフレッシュトークンが期限切れになる・使えなくなるという事象に遭遇することがあったので、その対処方法についてお伝えしたいと思います。

どんな問題?

GCP で提供されているOAuth2.0 で、Reflesh Tokenのリクエスト「grant_type=refresh_token」を行った際に発生するエラーの一種です。

developers.google.com

取得したReflesh Tokenを使って、新しいAccess Tokenを取得しようとし、以下のようなリクエストを行った場合に発生します。

developers.google.com

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

client_id=your_client_id&
client_secret=your_client_secret&
refresh_token=refresh_token&
grant_type=refresh_token

通常であれば、以下のような新しいAccess Tokenを受け取るレスポンスとなりますが、

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "token_type": "Bearer"
}

今回のケースでは「400 Bad Request」で、以下のようなレスポンスが返却されます。

{
    "error": "invalid_grant",
    "error_description": "Token has been expired or revoked."
}

「Token has been expired or revoked.」の発生条件

なかなか公式ドキュメントでうまく見つけ出せなくて苦労したのですが、以下のURLに記載がありました。

developers.google.com

・The user has revoked your app's access.

・The refresh token has not been used for six months.

・The user changed passwords and the refresh token contains Gmail scopes.

・The user account has exceeded a maximum number of granted (live) refresh tokens.

A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.

ざっくり日本語にすると以下のようになります。

このページで ユーザーが アプリのアクセスを取り消した場合。

・Refresh Token が6か月間使用されていない場合。

・ユーザーがパスワードを変更し、Refresh Token にGmailスコープが含まれている場合。

・ユーザーアカウントが、付与されたReflesh Token の最大数を超えた場合。

そして、以下が重要ですね。

OAuth同意画面が外部ユーザータイプ用に構成され、公開ステータスが「テスト中」のGoogle Cloud Platformプロジェクトの場合、7日で有効期限が切れる更新トークンが発行されます。

現在、Googleの提供するAPIに対してOAuth2.0 でアクセスしようとする場合、以下のようなOAuth 同意画面を構成する必要があります。

f:id:sugimomoto:20210128093004p:plain

この同意画面が外部向けかつ、公開ステータスが「テスト」の場合に、7日間で有効期限が切れてしまうReflesh Tokenが発行されてしまいます。

通常、Reflesh Token には上記で紹介したような特別なシチュエーションを除けば、期限切れを起こさないので、ちょっとびっくりしてしまいますね。

おそらく内部向けのバッチ利用や、テストで作っておいて検証している時に発生しやすい問題かな?と思います。

内部向けのバッチ利用の場合は、サービスアカウントを作成して、認証するほうが良いでしょう。

ClientId や ClientSecret などが間違っている場合のエラーメッセージ

ちなみに、ClientId や ClientSecret 、Reflesh Token が間違っている場合のエラーメッセージは少し文言が異なります。

{
    "error": "invalid_client",
    "error_description": "Unauthorized"
}

Reflesh Tokenが間違っている場合は以下のようなメッセージになります。

{
    "error": "invalid_grant",
    "error_description": "Bad Request"
}

ちゃんとシチュエーションに応じて、レスポンスメッセージが異なるので、問題を切り分ける時は注意しましょう。

CData Driverの挙動について

CDataで提供している、GCPのOAuth 2.0を利用した製品としては、Google BigQuery DriverやGoogle Drive Driverなどが挙げられます。

www.cdata.com

www.cdata.com

www.cdata.com

f:id:sugimomoto:20210128093011p:plain

通常、このDriverを使う場合は、CData側で取得した正式なOAuth 2.0のアプリケーション・埋め込まれているClientIdおよびClientSecretを利用するため、今回のようなエラーは明示的に以下のような手順を踏まない限り発生しません。

このページで ユーザーが アプリのアクセスを取り消した場合。

・Refresh Token が6か月間使用されていない場合。

・ユーザーがパスワードを変更し、Refresh Token にGmailスコープが含まれている場合。

・ユーザーアカウントが、付与されたReflesh Token の最大数を超えた場合。

もし自身でOAuth 2.0のアプリの取得、そしてClientId・ClientSecretを指定した場合は、前述の外部向けかつテスト中の同意画面のままだと、リフレッシュトークンの期限切れが発生する可能性があるので注意しましょう。

cdn.cdata.com

また、特に OAuth 2.0にこだわりがない場合は、サービスアカウントによる認証がオススメです。

www.cdatablog.jp