🍡

Firebase認証を付けたAWS AppSyncからAzureのAPIを実行する

2023/05/08に公開

やったこと

GWだったので3大クラウドを組み合わせたバックエンドを作ってみました。

  • AWS AppSync から Azure の OCR(Read API) を実行する
  • AWS AppSync に Firebase Authenticationで認証をつける

クロスクラウドってやつですね(?)

もう少し抽象的に書くとこうなります。

  • AWS AppSync から外部の Rest API を実行する
  • AWS AppSync に OIDC で外部の認証をつける

これらを可能とする AWS AppSync を CDK(Typescript) を使って構築します。

構築する

コード類一式は、 GitHub に置いておきます。
https://github.com/k-ibaraki/sample-firebase-appsync/tree/2023-05-06

Azure 上に Cognitive Service を作る

ChatGPTに聞いたら教えてくれました。

Azure で Cognitive Service を使う方法を教えて下さい

Azure Cognitive Servicesは、Microsoft Azureの一部であり、機械学習、自然言語処理、音声認識などのテクノロジーを提供しています。Azure Cognitive Servicesを使用するには、以下の手順に従ってください。

  1. Azureポータルにログインし、左側のナビゲーションメニューから「Cognitive Services」を選択します。
  2. 「Cognitive Services」ページで、「+ Add」ボタンをクリックします。
  3. 「Create Cognitive Services」ページで、必要な情報を入力します。これには、サービスの名前、場所、価格プランなどが含まれます。
  4. 必要な情報を入力したら、「Review + create」ボタンをクリックします。
  5. 作成の概要が表示されるので、確認して「Create」をクリックします。

サービスが作成されたら、Cognitive Servicesにアクセスするために必要なエンドポイントとキーが表示されます。これらの情報を使用して、アプリケーションでCognitive Servicesを呼び出すことができます。詳細については、Azure Cognitive Servicesの公式ドキュメントを参照してください。

Firebase Authentication を作る

ChatGPTに聞いたら教えてくれました。

Firebase Authentication を使う方法を教えて下さい

Firebase Authenticationを使うには、以下の手順に従ってください。

  1. Firebaseプロジェクトを作成する。Firebaseコンソールにログインして、プロジェクトを作成します。
  2. Firebase Authenticationを有効にする。Firebaseコンソールで、左側のメニューから「Authentication」を選択し、必要な設定を行います。
  3. 認証方法を選択する。Firebase Authenticationでは、メールアドレスとパスワード、ソーシャルメディアアカウント、電話番号など、さまざまな認証方法をサポートしています。必要な認証方法を選択して、必要な設定を行います。
  4. 認証を実装する。Firebase SDKを使用して、アプリケーションに認証機能を実装します。具体的な実装方法については、Firebase Authenticationの公式ドキュメントを参照してください。

Firebase Authenticationを使用することで、アプリケーションのユーザー認証機能を簡単に追加することができます。また、Firebase Authenticationは、認証情報のセキュリティにも配慮しており、安全に利用することができます。

CDK で AppSync を作る

全体像は GitHub に置いたソースを参考にしてください。

https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/cdk-appsync-stack.ts

以下は、ポイントとなる部分を説明します。

AppSync に Firebase Authentication による認証をつける

Appsync は直接は Firebase での認証をサポートしていませんが、 OIDC を通して認証をすることが出来ます。具体的な設定は、AppSyncで認証にOIDCを指定して、oidcProvider に https://securetoken.google.com/${FIREBASE_PROJECT_ID} [1] [2] を指定すればOKです。

CDKだとこの部分です。
https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/cdk-appsync-stack.ts#L19-L30

AWSのコンソールで設定する場合はこんな感じです。

この設定で、Firebase で認証されたユーザーだけが AppSync の API を実行できるようになります。

AppSync から Azure Cognitive Service の Read API (OCR) を呼ぶ

続いて AppSync から Azure の Read API (OCR) を呼び出します。ですが、2点ほど妥協した点があるのであるので最初に書いておきます。

  1. Read API の API Key を Secret Manager か SSM に格納して動的に取得するようにしたかったのですが、ドキュメント見てもやり方が載ってなかったので諦めて AppSync のリゾルバーに Key を埋め込みました。
  2. Read API は OCR なので input は画像ですが、渡し方が画像の URL を指定する方法と画像データをバイナリで渡す方法の2通りがあります。しかし、後者は AppSync経由での呼び出しがエラーとなり上手くいかなかった[3]ので URL 指定だけ作りました。

他にはエラー処理サボっていたりテスト書いてなかったりしますが、妥協したわけでなく最初からやる気がないだけです。

schema を定義する

schema を定義します。
https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/schema.graphql#L1-L20

Read API は非同期なので、リクエストと結果の取得で呼び出しを分ける必要があります。
リクエスト(readRequestUrl)は Post なので、Mutation にしています。
結果の取得(readResult)は Get なので、Query にしています。
最終的なレスポンスは型が複雑でしたが Azure のドキュメントを見ながら頑張って定義しました。面倒くさかったです。

HTTPデータソースを定義する

Rest API のように HTTP や HTTPS 経由でデータを取得したい場合は、HTTPデータソースを作ります。
https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/cdk-appsync-stack.ts#L33-L35
HTTPデータソースは URL を指定するくらいしか設定項目がなく、詳細は HTTPリゾルバーで設定します。

HTTPリゾルバーを書く

HTTPリゾルバーを使ってデータソースと schema を繋ぎます。コードが長くなったので CDK テンプレートから別ファイルに分離して書きました。前述の通り、リクエストと結果の取得で API 呼び出しが2回種類必要なので HTTPリゾルバーも2個必要です。

https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/resolvers/getUrlReadHttpResolver.ts
https://github.com/k-ibaraki/sample-firebase-appsync/blob/2023-05-06/cdk-appsync/lib/resolvers/getReadResultHttpResolver.ts

ポイントは MappingTemplate の部分でしょうか。 AppSync リクエストを Read API のリクエストに、 Read API のレスポンスを AppSync のレスポンスに変換します。MappingTemplate は VTL [4] で書きました。
最近は Javascript リゾルバが実装されたので本当はそちらを使いたかったのですが、 ChatGPT 先生が VTL しか知らないというので今回は AI に従いました。

deploy

全部書き終わったらビルドしてデプロイしましょう。

npm run build
cdk deploy

動作確認

動作確認として、いらすとやさんの GW に相応しい画像を OCR してみます。

  • Firebase で認証して IDトークンを取得してください。それ用のコードも書きました。
    https://github.com/k-ibaraki/sample-firebase-appsync/tree/2023-05-06/getFirebaseIdtoken

  • ブラウザで AWSコンソールを開き、該当の AppSync のクエリのページを開きましょう。

  • IDトークンをクエリのページ右上の認証トークンのところに入力してください。

  • 画像のURLを指定して、 readRequestUrl を実行すると、 requestId が返ってきます

  • requestId を指定して readResult を実行します。このとき、 lines 配下の text を取得するように指定してください。

無事結果が返ってきました! OCR も正しい結果が取得出来ています!

最後に

この構成になった理由

複数のクラウドを使っていて無駄なことをしているように見えるかもしれませんが、以下のような考えにより作成しています。

  1. Azure の Cognitive Service は使えるけど、 Azure 自体が使いにくい[5]ので活用が困難
  2. AWS 上のバックエンドを通して呼び出せれば使い勝手が良くなるはず
  3. AWS を使うなら素直に考えると認証が Cognito になるけど、構築や管理が面倒くさい[6]
  4. 堅い業務アプリならともかく雑な便利ツールなら Firebase が使いやすい

加えて、

  1. API Gateway + Lambda とかを使えば連携が出来るのは分かりきっている。面白くないので使わない。もちろんアンマネージドなサービスも使わない
  2. Azure を使うなら AWS には存在しないサービスを使いたい(日本語 OCR は AWS では無理)
  3. 各サービス間の連携構築に使う労力は考えないものとする

ということで、今回の構成になりました。

感想

  • AWS Appsync に Firebase で認証を付けるのは意外と簡単だった。実プロジェクトに応用できそう。ただし認可の制御とか考え出すと Lambda が必要になると思うし、Cognito を通したほうが細かい権限管理はしやすいと思う。
  • マッピングテンプレート周りがよく分からなくて苦戦しました。また、 Secret Manager 等の他AWSサービスを参照出来るようにして欲しいです。と思いましたが、 Lambda を挟めばいいだけのような気もします。
    • それとも JavaScript リゾルバを使いこなせれば全て解決するのかな?
      • (2023/05/11追記) 解決しませんでした。JavaScript リゾルバは、特定のライブラリ以外を import できないのでたいしたことが出来ません。慣れた文法で書けるメリットはありますが出来ることは増えません。
  • 本番でこんな構成作ったら、インフラの請求が3会社に散ることを経理の人に怒られそう。
脚注
  1. ${FIREBASE_PROJECT_ID} の部分は自分のプロジェクトIDに置き換えてください ↩︎

  2. プロジェクト番号ではなくプロジェクトIDなので注意しましょう ↩︎

  3. バイナリの場合はapplication/octet-streamを指定する必要があるのですが、AppSyncのHTTPリゾルバーがこの指定に対応してないのでエラーになります ↩︎

  4. Apache Velocity Template Language ↩︎

  5. 個人の感想です ↩︎

  6. 個人の感想です ↩︎

Discussion