小ネタ – Amazon API Gateway Cognito オーソライザーに送信する ID トークン のフォーマットに注意

こんにちは、広野です。

Amazon API Gateway で Cognito オーソライザーを使用するときに、Amazon API Gateway の API タイプにより ID トークンを送信するフォーマットが異なります。知らないとハマることがあるため、小ネタとして仕組みも含め紹介します。ここでは、よく使用する REST API と HTTP API での違いについて触れます。

REST API、HTTP API の機能の違いについてはこちら。HTTP API は REST API の機能を削減、安価にしてリニューアルしたような感じです。

HTTP API と REST API 間で選択する - Amazon API Gateway
HTTP API と REST API の違いについて説明します。

やりたいこと

  • Amazon Cognito を使用したサーバーレスアプリケーションで、API Gateway にリクエストをかけるときに Cognito オーソライザーで認証をかけたい。
  • API Gateway の API タイプは REST API と HTTP API とする。
  • サンプルとして紹介するアプリコードの開発フレームワークは React とする。

実現方法

アーキテクチャ

  1. ユーザがアプリ経由で Amazon Cognito に認証を受けてログインする。
  2. ログインすると、アプリは Amazon Cognito からいくつかのトークンを取得する。
  3. ユーザがアプリ経由で Amazon API Gateway にリクエストをかける。その際、リクエストに ID トークンを付加する。
    本記事では、ここで付加する ID トークンのフォーマットについて主に説明する。
  4. リクエストを受けた Amazon API Gateway は、リクエストに付加された ID トークンを検証するため、Amazon Cognito に問い合わせする。
  5. ID トークン検証の結果、問題なければ後続の処理を進める。(AWS Lambda の呼び出し等)

Amazon API Gateway での Cognito オーソライザーの設定

REST API、HTTP API のいずれも簡単な設定のみです。

REST API の場合

「オーソライザー」メニューで「オーソライザー」を作成します。タイプは Cognito を選択、トークンのソースは Authorization と入力します。認証用の Amazon Cognito ユーザープールもプルダウンで選択できます。

リソースメニューから該当するメソッドを選択し、メソッドリクエストを開くと「認可」の設定があるので、そこで先ほど作成した「オーソライザー」を関連付けます。

詳細は以下の公式ドキュメントをご覧下さい。

Amazon Cognito ユーザープールをオーソライザーとして使用して REST API へのアクセスを制御する - Amazon API Gateway
API メソッドの呼び出しを許可する Amazon Cognito ユーザープールを使用する方法を説明します。

HTTP API の場合

「認可」メニューから、「オーソライザーを管理」タブを選択し、オーソライザーを作成します。

オーソライザーのタイプは JWT を選択します。ID ソースは、$request.header.Authorization と書きます。ID プロバイダーの発行者URI には、Amazon Cognito ユーザープールの URI を以下のような書式で書きます。対象者は Amazon Cognito ユーザープールのアプリケーションクライアント ID になります。

オーソライザーが作成できたら、「オーソライザーをルートにアタッチ」タブからメソッドに関連付けます。

詳細は以下の公式ドキュメントをご覧下さい。

JWT オーソライザーを使用した HTTP API へのアクセスの制御 - Amazon API Gateway
HTTP API の JWT 認証について説明します。

アプリ側の API 呼出・ID トークン送信

ここでは、React アプリで axios を使用した API 呼出、ID トークン送信のコードを紹介します。

まず、アプリから Amazon Cognito へのユーザ認証を済ませると、アプリは Amazon Cognito から「自分のユーザ情報のかたまり」のようなものを受け取ります。この中に、ID トークンが含まれています。

アプリがその「自分のユーザ情報のかたまり」を user という変数で受け取ったとすると、ID トークンは user.signInUserSession.idToken という記述で取得できます。ID トークンはエンコードされた英数字の文字列なので、console.log 等でそのまま表示させても何が何だかわかりませんが、デコードするとユーザ情報やシークレットが格納されていることがわかります。Amazon API Gateway の Cognito オーソライザーを使用するときには、この ID トークンを使用するので API 呼出をするときにデータと一緒に送信する必要があります。

トークンについてはこちら。

JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

以下は、React アプリから ID トークン付きで API を呼び出すコードのサンプルです。Amazon Cognito から取得した ID トークンは props.idToken というパラメータで親コンポーネントから引き渡され、idtoken 変数に格納するように書いています。

axios で ID トークンを Amazon API Gateway に送信するときは headers という項目名で送ることになるのですが、送信先が REST API か HTTP API かで、そのフォーマットに違いがあります。

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const Sample = (props) => {
  const idtoken = props.idToken
  const headerdata = //ここで REST API と HTTP API でフォーマットに違いがある!
  const [data, setData] = useState([]);

  const getData = async (p1, p2, p3) => {
    const res = await axios.post(
      process.env.REACT_APP_GETDATA_URL + "/xxxxxxx", //送信先API Gateway URL
      {
        param1: p1,
        param2: p2,
        param3: p3
      },
      {
        headers: headerdata
      }
    );
    setData(res.data.Items);
  };
  
  useEffect(() => {
    getData("AAA","BBB","CCC");
  }, []);

  return (
    <React.Fragment>
      {/* 中略 */}
    </React.Fragment>
  );
};

export default Sample;

ここでは、headerdata という変数に各APIに適したフォーマットで ID トークンを格納し送信するようにします。いずれも JSON フォーマットになるのは共通です。

REST API の場合

const headerdata = {
  "Authorization": idtoken
};

REST API の場合は、Authorization という項目名で単純に ID トークンを格納するだけです。

HTTP API の場合

const headerdata = {
  "Authorization": "Bearer " + idtoken
};

HTTP API の場合は、Authorization という項目名は同じなのですが、ID トークンの先頭に “Bearer ” という接頭辞を付ける必要があります。Bearerの後には半角スペースがあります。

これは知らないと、ハマります。

まとめ

いかがでしたでしょうか?

同じ API Gateway でも、REST API と HTTP API で Amazon Cognito へのオーソライザー機能実装手順は大きく異なります。やっていることは同じなんですが。

本記事がみなさまのお役に立てれば幸いです。

著者について
広野 祐司

AWSサーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリや教育コンテンツをつくっています。
ReactでSPAを書き始めたら快適すぎて、他の開発言語には戻れなくなりました。React仲間を増やしたいです。
取得資格:AWS認定は7つ、ITサービスマネージャ、ITIL v3 Expert、等
2019, 2020 AWS APN Top engineers 受賞
好きなAWSサービス:AWS Amplify / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする
クラウドに強いによるエンジニアブログです。
SCSKは専門性と豊富な実績を活かしたクラウドサービス USiZE(ユーサイズ)を提供しています。
USiZEサービスサイトでは、お客様のDX推進をワンストップで支援するサービスの詳細や導入事例を紹介しています。
AWSサーバレスアーキテクチャ
TechHarmony
タイトルとURLをコピーしました