質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

解決済

GASでLINEログイン後にOauthエラー(invalid_grant, authorization code expired or incompatible)

HirokazuYokota
HirokazuYokota

総合スコア1

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

1回答

0評価

0クリップ

1789閲覧

投稿2020/10/20 04:04

編集2020/10/20 13:26

前提・実現したいこと

GASでLINEログインを用いたWebアプリを作成しています。
Oauth認証を用いてLINE認証した後のコールバック処理で、下記のエラーが発生しています。
何が問題で本事象が発生しているか、また、解決方法についてご存知の方がいらっしゃいましたらご教示頂けないでしょうか。

発生している問題・エラーメッセージ

Error: Error retrieving token: invalid_grant, authorization code expired or incompatible at Service_.getTokenFromResponse_(Service:541:11) at Service_.fetchToken_(Service:516:15) at Service_.handleCallback(Service:399:20)

該当のソースコード

test.gs

gs

function doGet() { 'use strict'; var service = getService(); if (service.hasAccess()) { createAndSendDocument(service.getAccessToken()); return HtmlService.createHtmlOutput('Success'); } // 承認されていない場合、承認リンクをHTMLページに表示 var authorizationUrl = service.getAuthorizationUrl(); var template = '<a href="' + authorizationUrl + '" target="_blank">Authorize</a>'; return HtmlService.createHtmlOutput(template); } /** * OAuth 2.0 serviceのセットアップ */ function getService() { 'use strict'; // OAuth 2.0承認サービスの生成 return OAuth2.createService('line') .setAuthorizationBaseUrl('https://access.line.me/dialog/oauth/weblogin')// 認可エンドポイント .setTokenUrl('https://api.line.me/oauth2/v2.1/token')// トークンエンドポイント // LINEログインのクライアントIDおよびクライアントシークレットを設定 .setClientId('xxxxxxxxxx') // OAuthクライアントID .setClientSecret('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') // OAuthクライアントシークレット // OAuth2.0 承認後のコールバック関数名の設定 .setCallbackFunction('authCallback') // 承認トークンを維持するプロパティーストアの設定 .setPropertyStore(PropertiesService.getUserProperties()) // LINEログインリクエストのスコープ設定 .setScope('profile'); // LINEログインのスコープ } /** * 最初のOAuth2承認の際のコールバック処理 */ function authCallback(request) { 'use strict'; var service = getService(); var authorized = service.handleCallback(request); if (authorized) { createAndSendDocument(service.getAccessToken()); return HtmlService.createHtmlOutput('Success!'); } return HtmlService.createHtmlOutput('Denied.'); }

Oauthライブラリのソース抜粋
ソースコード全文

js

Service_.prototype.handleCallback = function(callbackRequest) { var code = callbackRequest.parameter.code; var error = callbackRequest.parameter.error; if (error) { if (error == 'access_denied') { return false; } else { throw new Error('Error authorizing token: ' + error); } } validate_({ 'Client ID': this.clientId_, 'Client Secret': this.clientSecret_, 'Token URL': this.tokenUrl_ }); var payload = { code: code, client_id: this.clientId_, client_secret: this.clientSecret_, redirect_uri: this.getRedirectUri(), grant_type: 'authorization_code' }; var token = this.fetchToken_(payload); this.saveToken_(token); return true; }; /** * Fetches a new token from the OAuth server. * @param {Object} payload The token request payload. * @param {string} [optUrl] The URL of the token endpoint. * @return {Object} The parsed token. */ Service_.prototype.fetchToken_ = function(payload, optUrl) { // Use the configured token URL unless one is specified. var url = optUrl || this.tokenUrl_; var headers = { 'Accept': this.tokenFormat_ }; if (this.tokenHeaders_) { headers = extend_(headers, this.tokenHeaders_); } if (this.tokenPayloadHandler_) { payload = this.tokenPayloadHandler_(payload); } var response = UrlFetchApp.fetch(url, { method: 'post', headers: headers, payload: payload, muteHttpExceptions: true }); return this.getTokenFromResponse_(response); }; /** * Gets the token from a UrlFetchApp response. * @param {UrlFetchApp.HTTPResponse} response The response object. * @return {!Object} The parsed token. * @throws If the token cannot be parsed or the response contained an error. * @private */ Service_.prototype.getTokenFromResponse_ = function(response) { var token = this.parseToken_(response.getContentText()); var resCode = response.getResponseCode(); if ( resCode < 200 || resCode >= 300 || token.error) { var reason = [ token.error, token.message, token.error_description, token.error_uri ].filter(Boolean).map(function(part) { return typeof(part) == 'string' ? part : JSON.stringify(part); }).join(', '); if (!reason) { reason = resCode + ': ' + JSON.stringify(token); } throw new Error('Error retrieving token: ' + reason); } return token; };

試したこと

コールバック処理(authCallback)のINPUTパラメータ(request)の中身をログに出力したものの何が問題かが十分に分かりません。

log

{ parameters={ code=[uLuj9s4Asa1qujrtAGm0] , serviceName=line , state=[ADEpC8zLJCo5fkyokPfDcyVfYbFS-2fdPU0DUBfrJOmN9E5-OWKdZW012RW3JViXtPw9EXtztv2FkxNqpeJ_3gkyhHb0xm-KDobrNbMz2NB_lV9scjSXFfdlnkD_FvCXNKR30oDMM1qOIBgxpwEFDLxq9mTVh0_sr2ZGNApQKsUpAa1y5PVrW70] } , parameter={ serviceName=line , code=uLuj9s4Asa1qujrtAGm0 , state=ADEpC8zLJCo5fkyokPfDcyVfYbFS-2fdPU0DUBfrJOmN9E5-OWKdZW012RW3JViXtPw9EXtztv2FkxNqpeJ_3gkyhHb0xm-KDobrNbMz2NB_lV9scjSXFfdlnkD_FvCXNKR30oDMM1qOIBgxpwEFDLxq9mTVh0_sr2ZGNApQKsUpAa1y5PVrW70 } , queryString=code=uLuj9s4Asa1qujrtAGm0 &state=ADEpC8zLJCo5fkyokPfDcyVfYbFS-2fdPU0DUBfrJOmN9E5-OWKdZW012RW3JViXtPw9EXtztv2FkxNqpeJ_3gkyhHb0xm-KDobrNbMz2NB_lV9scjSXFfdlnkD_FvCXNKR30oDMM1qOIBgxpwEFDLxq9mTVh0_sr2ZGNApQKsUpAa1y5PVrW70 , contextPath= , contentLength=-1.0 }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。