FlutterでIAPの突破を試みた話

この記事は「MIXI DEVELOPERS Advent Calendar 2023」19日目の記事です。

https://qiita.com/advent-calendar/2023/mixi

「Flutterで開発したAndroid/iOSのアプリから、GoogleCloudのIdentity-Aware Proxy（IAP）で保護されたリソースに対してAPI通信する」ということをやったので、その際にやったことや困ったことなどをまとめたいと思います。
この記事では「IAPで保護されたリソースに対してAPI通信する」ことを「IAPを突破する」と表現することにします。

# 詳細
「Flutterで開発したAndroid/iOSのアプリ」ではFirebaseを利用していて、既にGoogleCloudのプロジェクトが1つ紐づいている状態です。今回そのプロジェクトとは別のプロジェクトに存在しているIAPの突破を試みました。
モバイルアプリからIAPを突破するための具体的な手順については、ドキュメントが用意されていますが、実装するに当たって困ったことが大きく2つありました。

https://cloud.google.com/iap/docs/authentication-howto?hl=ja

1. ドキュメントに具体的な実装方法についての記載が少なく、Flutterについては言及がない
Android/iOSともに「GoogleSignを利用して〜」と書かれているのですが、それしか書かれていません。GoogleSignInについてはGoogleSignInのドキュメントを読むしかなく（リンクが貼られているだけ）、GoogleSignInを利用してどのように認可を得るのか、コードベースでの具体的な説明がありません。
FlutterのGoogleSignInのパッケージのドキュメントを読みますが、こちらにもIAP関連の記載はないので手探りで進めるしかありませんでした。

https://pub.dev/packages/google_sign_in

2. 「モバイルアプリからIAPを突破する」というコンテキストでの事例がインターネット検索であまりヒットしない
前述のドキュメント以上の情報を得るのが難しかったです。今回は「モバイルアプリから、アプリが紐づいているGoogleCloudのプロジェクトとは別のプロジェクトに存在するIAPを突破する」というさらに一歩踏み込んだ要件であったため、さらに情報収集が難しかったように感じました。
Flutter（Android、iOS） × Firebase × IAP × 「今回の要件」で条件や状況を一つ一つ場合分けして解決する必要があり、ハードルが高いように感じました。

# 今回やったこと
## iOS
1. OAuthクライアントIDを作成する
IAPと同じプロジェクト内に作成します。「名前（任意の識別子）/BundleId」が必須項目です。特に困ることなく作成できました。
2. アプリにGoogleSignInパッケージを追加し、認可の取得とリクエストの送信部分を実装する
FlutterのGoogleSignInのパッケージを追加します。
認可の取得については以下のような実装になりました。
```dart
import 'dart:io';

import 'package:google_sign_in/google_sign_in.dart';
import 'package:http/http.dart' as http;

Future<void> request() async {
  final googleSignIn = GoogleSignIn(
    clientId: '1で作成したOAuthクライアントID',
    serverClientId: 'アクセスしたいリソースを保護しているIAPのOAuthクライアントID',
  );
  final account = await googleSignIn.signIn();
  final authResult = await account?.authentication;

  final response = await http.Client().get(
    'アクセスするリソースURL',
    headers: { HttpHeaders.authorizationHeader: 'Bearer ${authResult.idToken}' }
  );
}
``````

`GoogleSignInのオプションにあるserverClientIdに「IAPのOAuthクライアントID」をセットする`
この事実に気づくのにかなり時間がかかりました。。
ドキュメントを読み、ネット検索で複数の記事を読むも有益な情報が得られず、それっぽいなと思って試したら上手くアクセスできました。

## Android
先に結論を書いてしまうのですが、Androidは現在も上手くアクセスすることができていません。方法をご存知の方がいらっしゃったらコメントで教えていただきいです。。
試したことを記載したいと思います。
1. OAuthクライアントを作成する
Androidの場合アプリのパッケージ名とSHA-1証明書のフィンガープリントを登録する必要があるのですが、パッケージ名とSHA-1証明書はGoogleCloudのプロジェクトをまたいで一意の組み合わせである必要があります。例えば、プロジェクトAに既に登録していた場合、別のプロジェクトBには登録できないということです。
我々の場合、FirebaseAuthenticationを利用しているため、FirebaseコンソールからSHA-1証明書を登録していたのですが、この登録によって自動的にOAuthクライアントが作成されており、IAPと同じプロジェクトでOAuthクライアントを作成することができない、という状況でした。
[こちら](https://support.google.com/firebase/answer/6401008?hl=ja#zippy=%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE-google-cloud-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%84%E3%81%A6firebase-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%82%E3%81%8B%E3%81%BE%E3%82%8F%E3%81%AA%E3%81%84%E3%81%BE%E3%81%9F%E3%81%AF-invites-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%2C%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AF%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%8Finvites-%E3%81%AF%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84)のヘルプを参考にしつつ、FirebaseのプロジェクトからOAuthクライアントを削除できないか試行してみたのですが上手くできませんでした。

https://support.google.com/firebase/answer/6401008?hl=ja#zippy=%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%2C%E7%AB%B6%E5%90%88%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B-oauth-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88-id-%E3%81%8C%E3%81%A9%E3%81%AE-google-cloud-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%8F%E3%81%8B%E3%81%A3%E3%81%A6%E3%81%84%E3%81%A6firebase-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%82%82%E3%81%8B%E3%81%BE%E3%82%8F%E3%81%AA%E3%81%84%E3%81%BE%E3%81%9F%E3%81%AF-invites-%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%2C%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AF%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%8Finvites-%E3%81%AF%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84

2. アプリにGoogleSignInパッケージを追加し、認可の取得とリクエストの送信部分を実装する
FirebaseAuthenticationが動かないという件は一旦考えず、既存のOAuthクライアントは削除してIAPと同じプロジェクトにOAuthクライアントを新規に作成しました。そのうえでiOSと同じように実装をしてみたのですが、上手くアクセスすることができませんでした。

# まとめ
Androidでは上手く突破できなかったというとてももやもやする結論で恐縮なのですが、やったことをまとめてみました。iOSでは上手く動くのでOAuthクライアントの設定やSHA-1証明書の登録が間違っているような気がしているのですが、上手く解決できていません。時間が空いたときに条件をシンプルにするためFlutterの文脈は一度捨ててAndroidの文脈で探ってみようと思っています。
日に日に事例や利用者も増えてきたFlutterではありますが、他の色々な要素との組み合わせになるとまだまだ情報量が少ないのかもしれないと思った経験についてでした。