Flutter: MacデスクトップアプリからのGoogle SignInが突如エラーになる

結論:「google_sign_in_dartio」パッケージを利用する、もしくはセキュリティソフトを無効化する

2022/7/17 Flutter エラー・バグ日記

 

以前、こちらの日記にも記載したが、Flutter2.10にアップグレードしたタイミングから、「エラー400: invalid_request」が出て、突然、MacからのGoogleサインインができなくなった(サインインの目的はGoogle Driveへのアクセス)。

 

しばらく対応を塩漬けしていたが、、、今回調査していくつかの解決方法が分かったのでメモ(後述のとおり、Flutterのアップグレード自体は関係なかった。。)。

 

本記事はライトな日記思考で書いているので、詳細説明はしておらず、基本、テキストのみで画像とかは載せておりません。。m(_ _)m

解説記事ではないため、解決していない内容や、その時々の間違った解釈を述べてしまっている可能性が大いにありますので、何卒、ご了承ください。

 

Flutterで一般的に使用されるGoogleサインイン用のパッケージ「google_sign_in」は、iOS、Android、Webのみの対応のため、デスクトップアプリにGoogleサインインを実装するためは、他の方法を模索する必要がある。

 

当初、対応方法を調べて「googleapis_auth」パッケージを用いれば、ブラウザを経由してGoogleサインインできると分かったので、下記方法(要点のみ掲載)で実装していた。

 

// クラス名、メソッド名、プロパティ名(変数名)について、
// パッケージ等で規定済の名称と区別するため、筆者が作成したもの(名前変更可のもの)
// の名前の末尾には、大文字のオー「O」を付記

import "package:googleapis_auth/auth_io.dart";
import 'package:url_launcher/url_launcher.dart';
import 'package:googleapis/drive/v3.dart'

// ・・・(略)・・・

// ここではGoogle Driveを使用する例として、scopeを設定
scopeO = [DriveApi.driveAppdataScope,];

// Googleサインイン・ユーザー同意の画面をブラウザで表示するためのメソッドを設定
void promptO(String urlO) async {
        if (await canLaunch(urlO)) {
          await launch(urlO);
        } else {
          throw 'Could not launch $urlO';
        }
      }

// "・・・・"には、Google Cloudで取得したClientIDを入れる
var clientIdO = ClientId("・・・・", "");

// ここでブラウザを起動させてサインイン画面を表示
httpClientO = await clientViaUserConsent(clientIdO, scopeO, promptO);

// Google Drive APIのインスタンスを作成
// 以降、このインスタンスを用いてGoogle Driveへのアクセス処理を記述する
googleDriveApiO = DriveApi(httpClientO);

// ・・・(略)・・・

 

(以下、参考情報)

↓Dart向けのGoogle API公式説明

 

↓Google カレンダーへのアクセス実装例

 

しかし、この方法が使えなくなってしまい、調べても解決策を見いだせなかったので、仕方なく他の方法を探すことにした。

 

他のMacデスクトップからのGoogleサインイン方法

結論としては、以下2つのパッケージを使う方法が見つかった。

 

① 「desktop_webview_auth」 を使う方法

 

 

以下のイシューで、本パッケージの具体的な実装例が紹介されている。

 

 

② 「google_sign_in_dartio」 を使う方法

 

 

こちらは、「pub.dev」内で関連しそうなパッケージが無いか探したところ、見つかった。

 

①「desktop_webview_auth」については、パッケージのExampleや、上記イシューの実装例を元に試したところ、確かにGoogleサインインの画面を起動でき、ユーザー同意を取得の上、サインインさせることができた。

 

しかし、恥ずかしながら、自分の理解が及ばず、「サインアウト」させる方法が分からなかった。。

 

※ソースコード内をひたすら探したが、サインアウトさせるメソッドが見つからなかった(無い訳はないと思うのだが、、、)。

 

そこで、②「google_sign_in_dartio」の方も試してみた。

 

ネット上に実装例が見当たらないので、パッケージのExampleを元に実装したところ、こちらもGoogleサインインの画面を起動でき、ユーザー同意を取得の上、サインインさせることができた。

 

しかも、実装方法が非常に簡単で、通常のiOS、Android用に「google_signin」パッケージを実装するコードの前に、以下のコードを入れるだけだった。

 

await GoogleSignInDart.register(clientId: “・・・・”);

 

※”・・・・”の部分には、パッケージの説明ページのとおり、Google Cloudで、デスクトップ用に取得したClient ID(「アプリケーションの種類」で「デスクトップアプリ」を選択して作成)を記載する。

 

若干の注意点としては、「scopes:」の設定時に、「’email’」と「’profile’」も入れておく必要がある点。

 

当初、これらを入れずにscopesを設定したところ、サインイン画面は起動するものの、「Null check operator used on a null value」のエラーが出て、サインインできなかった。

 

具体的な実装例(一部のみ)は以下のとおり。

 

import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';
import 'package:google_sign_in/google_sign_in.dart'
import 'package:googleapis/drive/v3.dart'
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';

// ・・・(略)・・・

// ↓この1文を追加するのみ
await GoogleSignInDart.register(clientId: "・・・・");

// 以降はiOS、Android用に記述するコードと同じ

googleSignInO = GoogleSignIn(
        scopes: [
          // この2つがないと、nullエラーになるため必要
          'email',
          'profile',

          DriveApi.driveAppdataScope,
        ]);

await googleSignInO.signIn();

httpClientO = (await googleSignInO.authenticatedClient())!;
googleDriveApiO = driveO.DriveApi(httpClientO);

// ・・・(略)・・・

 

「googleapis_auth」を使うときに必要だったurl_launcher」パッケージを用いてブラウザを起動するコードなどが不要なので楽

 

ただ、1つ難点があるのは、この方法だとアクセストークンがリフレッシュされないため、1時間経つとトークンが失効し、再度サインインが必要になってしまう点。

 

この問題を解消するには、下記説明ページを参考に、エンドポイント(endpoint)のURIを用意して、「register」メソッドの「exchangeEndpoint:」プロパティに設定する必要があるようだが、方法が難解で理解が及ばず。。。

 

 

自分のアプリでは、Google Driveとの間でのデータのバックアップ・リストアが目的だったので、サインインの維持は必要ないと判断し、エンドポイントの設定は割愛することとした。

 

「googleapis_auth」を用いたサインインも復活(セキュリティソフトの問題)

なぜ従前の「googleapis_auth」を用いる方法が使えなくなったのか、再度調べてみた。

 

すると、こちらのDart公式説明ページにおいて、「http://localhost:8080」を使用する、と書かれている事に気づく。

 

そこで、ローカルホスト関連のエラーについて調べたところ、以下の情報が見つかった。

 

 

 

いずれも「ESET(セキュリティソフト)のファイアウォールを無効化したらつながった」とのこと。

 

そこで、自分のMacに入れているのセキュリティソフトを無効化したところ、なんとアクセスできるようになった。。

 

ちょうどエラーが出るようになったタイミングで、当該セキュリティソフトの再インストール・アップデートをしており、それが影響したのかもしれない。。

 

まさかセキュリティソフトが原因とは。。

 

ただ、「google_sign_in_dartio」を用いる方法は、「googleapis_auth」を使う方法に比べ、実装の手間が少ないので、引き続き前者を採用しようと思う。

 

 

\一般的なエラー対処法をまとめた記事はこちら/

 

リリースしたアプリ(全てFlutterで開発)

暗記用マーカー – シンプル穴埋め問題作成

Google Play で手に入れよう
Download on the App Store

 

超即ToDo –最短2タップで通知登録できるタスク管理アプリ

Google Play で手に入れよう
Download on the App Store

 

かんたんプリント管理:アラート・OCR文字認識・検索機能を搭載

Google Play で手に入れよう
Download on the App Store

 

シンプルメモ帳「BasicMemo」 – 文字カウント、ワンタッチ入力、タグ管理等の機能を搭載

Macのデスクトップ版もリリースしました。

Google Play で手に入れよう
Download on the App Store

 

個人アプリ開発で役立ったもの

おすすめの学習教材

超初心者向けでオススメな元Udemyの講座/

 

\Gitの基礎について無料で学べる/

 

おすすめの学習書籍

実用的image_pickerに関してかなり助けられた/

 

Dartの基礎文法を素早くインプットできる/


Dart入門 – Dartの要点をつかむためのクイックツアー

 

おすすめのソフトウェア

安くて高機能。アプリの独自ドメイン・紹介サイト構築に最適/

 

\アイコン作成・画面設計・クラウド保存…何でもできて超必須

 

おすすめのハードウェア

\リーズナブルな価格で検証端末を確保できる/

 

\目線の高さを調節しやすく、疲れにくい

 

\キータッチが超静音で心地よい/

 

おすすめのサポートアイテム

\部屋の中を仕切って、集中できる開発環境を作れる/

 

\部屋の中でも大き過ぎず、長時間座っても疲れない

 

\バグと格闘した後の肩こりを解消してくれる/

タイトルとURLをコピーしました