Cognito から発行された認可コードからユーザー情報を取得してみた

2023.12.11

この記事は アノテーション株式会社 AWS Technical Support Advent Calendar 2023 | Advent Calendar 2023 - Qiita 11日目の記事です。

こんにちは! アノテーションの吉本です。

先日以下の記事で作成した Cognito Hosted UI で発行される認可コードからユーザー情報を取得してみたためご紹介します。

本記事のゴール

認可コードからユーザー情報を取得する

認可コードとは

OAuth 2.0 の Authorization code grant フローで利用するコードになります。 今回の記事では OAuth 2.0 についての説明は省略いたしますが、以下のブログが非常に参考になるため詳細に知りたい方は是非ご覧ください。

今回構築する構成

今回は以下のような構成を作成します。

動きのイメージは以下のようになります。

それでは早速構築していきます!

構築してみた

1. Amplify の構築

まずは、ユーザー情報を表示するための Amplify を構築していきます。

今回は Gatsby.js にて Web ページを構築します。

以下のコマンドを CLI 上で実行しプロジェクトを作成します。

% npm init gatsby

今回は index.js を以下のように編集してみました。

index.js

import React, { useEffect, useState } from "react"
import axios from "axios"

const IndexPage = ({ location }) => {
  const [data, setData] = useState([])

  useEffect(() => {
    const params = new URLSearchParams(location.search);
    const code = params.get("code")
    axios({
      method: "GET",
      url:'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/xxxxxxxxx/xxxxxxxxxx?code=' + code,
    }).then(resp => {
      setData(resp.data)
      setData(data => ({...data, code: code}));
    })
  }, [])

  return (
    <main>
      <div>
        <h1>ユーザー情報</h1>
        <h2>ユーザーID: {data.sub}</h2>
        <h2>名前: {data.name}</h2>
        <h2>メールアドレス: {data.email}</h2>
        <h2>認可コード: {data.code}</h2>
      </div>
    </main>
  )
}

export default IndexPage

export const Head = () => <title>Home Page</title>

動作確認後、以下の記事を参考に Amplify にデプロイしていきます。

設定は全てデフォルトのままで大丈夫・・・と思ったのですが以下のエラーが発生しました。

2023-12-07T05:39:23.538Z [WARNING]: error Gatsby requires Node.js 18.0.0 or higher (you have v16.19.0).
                                    Upgrade Node to the latest stable release: https://gatsby.dev/upgrading-node-js

Amplify のビルドで使用するデフォルトイメージが Gatsby でサポートする Node.js 18 に対応していないことが原因のようです。 今回は仕方がないので、以下の node 公式イメージを使用します。

アプリの設定 > ビルドの設定 > Build image settings > Edit を選択し、以下のように設定します。

再デプロイは無事成功しました。

続いては、Cognito を構築していきます。

2. Cognito User Pool の構築

前回の以下記事の内容と構築内容はほぼ同じですが、今回は「許可されているコールバック URL」に先ほどデプロイした Amplify のドメインを登録します。

作成が完了したら早速 Hosted UI にアクセスしてみましょう。アクセス方法は前回記事を参照

味気ないですが無事アクセスできました。サインアップし、ログインしてみます。

画面上に認可コードを取得することができました!
続いて、この認可コードを用いてユーザー情報を取得する API を作っていきます。

3. Lambda 関数の構築

今回は Node.js 18.x ランタイムで Lambda 関数を構築します。

まず、Lambda 関数内で必要となる Cognito のエンドポイントの URL を取得します。

Cognito のエンドポイントの URL は アプリケーションの統合 > ドメイン > Cognito ドメイン から取得できます。

Lambda 関数のコードは以下のように編集してみました。

index.js

import axios from 'axios'

export const handler = async (event) => {

  // cognito のドメイン
  const cognitoDomain = "https://xxxxx.auth.ap-northeast-1.amazoncognito.com"
  // クエリパラメータより認可コードの取得
  const code = event.queryStringParameters.code
  // トークンエンドポイントへのリクエスト
  const tokenRes = await axios.post(cognitoDomain + "/oauth2/token", {
      grant_type  : 'authorization_code',
      client_id: 'xxxxxxxxxxxxxxx',
      code: code,
      redirect_uri: "https://xxxxx.xxxxxxxxxx.amplifyapp.com/"
    }, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
  })

  // アクセストークン
  const accessToken = tokenRes.data.access_token
  // UserInfo エンドポイントへのリクエスト
  const infoRes = await axios.get(cognitoDomain + "/oauth2/userInfo", {
      headers: {
        'Authorization': 'Bearer ' + accessToken
      }
  })
  // レスポンス作成
  const response = {
    statusCode: 200,
    headers: {
        "Access-Control-Allow-Headers" : "Content-Type",
        "Access-Control-Allow-Origin": "https://xxxxx.xxxxxxxxxx.amplifyapp.com",
        "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
    },
    body: JSON.stringify(infoRes.data),
  };
  return response;
};

Cognito におけるトークンエンドポイント、userInfo エンドポイントの仕様については以下のドキュメントを参考にしています。

それでは最後に、API Gateway を用いて Lambda を API 化します!

3. API Gateway の構築

Lambda のコンソール画面からサクッと作成していきます。

Lambda > トリガーの追加から以下のように設定します。

上記で必要なものは構築完了しました。実際にログインし画面を確認してみます。

無事ユーザー情報が取得できました!(名前は今回ユーザ登録時に必要項目としていなかったため取得できていません・・・すみません)

まとめ

今回は、Cognito User Pool のトークンエンドポイント、UserInfo エンドポイントを用いてユーザーデータを取得するアプリケーションを構築してみました。 サービスを組み合わせることによって意外と簡単にアプリケーションを構築できますね。

実際に本番環境等で利用する場合、上記設定ではセキュリティ面などに不安があるため注意してください!

参考資料

Developers.IO 2017セッション「基礎からの OAuth 2.0」でお話してきました #cmdevio2017 | DevelopersIO

Gatsby.js と AWS Amplify を使って爆速でブログサイトをデプロイする | DevelopersIO

トークンエンドポイント - Amazon Cognito

UserInfo エンドポイント - Amazon Cognito

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。