LoginSignup
0
1

AWS APIGateway(HTTP API)とCognitoを統合

Posted at

やりたいこと

フロントエンド(ここではReactアプリ)から、APIGateway経由でLambda関数を実行するときにCognitoで認証されたユーザーからのリクエストのみをAPIGatewayで受け付けるようにしたい
※備忘録に近い内容です

作成手順

①Lambda関数を作成

何でも良いのでLambda関数を作成
とりあえず作成したときに出来上がるHelloLambdaのままとした
(ここでやりたいことはLambdaの中身は関係ないので)

export const handler = async (event) => {
  // TODO implement
  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};
②APIGateway作成

・HTTP APIを作成
・Authorization設定
 オーソライザーのタイプ:JWT
 IDソース:$request.header.Authorization
 発行者URL:https://cognito-idp.ap-northeast-1.amazonaws.com/{userPoolId}
 対象者:CognitoユーザープールのアプリケーションクライアントIDを入力
・CORSの設定(ReactアプリからAPIGatewayを呼び出すため)
 Access-Control-Allow-Origin:* (本番環境の場合は具体的なドメイン名を指定すること)
 Access-Control-Allow-Methods:*
 Access-Control-Allow-Headers:content-type,authorization

試しに実行

ブラウザからAPIGatewayのURLをたたいてみる
-> 401 Unauthorizedが返ってくる。想定通り

ReactからAPIGateway実行

import {
  CognitoUserPool,
  AuthenticationDetails,
  CognitoUser,
} from "amazon-cognito-identity-js";

const poolData = {
  UserPoolId: "ap-northeast-1_xxxxxxxxx", // ユーザープールID
  ClientId: "6b093xxxxxxxxxxxxxxxxxxxx", // アプリクライアントID
};

const userPool = new CognitoUserPool(poolData);

// Cognitoログイン
function signIn(username, password) {
  const authenticationData = {
    Username: username,
    Password: password,
  };
  const authenticationDetails = new AuthenticationDetails(authenticationData);

  const userData = {
    Username: username,
    Pool: userPool,
  };
  const cognitoUser = new CognitoUser(userData);

  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: (result) => {
      debugger;
      const accessToken = result.getAccessToken().getJwtToken();
      const idToken = result.getIdToken().getJwtToken();
      console.log("access token: " + accessToken);
      console.log("id token: " + idToken);
      // アクセストークンを使用した処理をここに記述
      alert("ログイン完了" + accessToken);
    },
    onFailure: (err) => {
      console.error(err);
      alert(err.message || JSON.stringify(err));
    },
  });
}

// APIGateway Called
const apiGatewayCall = async (idToken) => {
  debugger;
  try {
    const response = await fetch(
      "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/endpoint",
      {
        method: "GET",
        headers: {
          Authorization: `Bearer ${idToken}`,
          "Content-Type": "application/json",
        },
      }
    );
    const result = await response.json();
    console.log("result", result);
  } catch (error) {
    console.error("api error", error);
  }
};

export default function LoginForm() {
  const handleLogin = (event) => {
    event.preventDefault();
    const username = event.target.username.value;
    const password = event.target.password.value;
    signIn(username, password);
  };

  const apiCall = (event) => {
    event.preventDefault();
    const idToken = event.target.idToken.value;
    apiGatewayCall(idToken);
  };

  return (
    <>
      <form onSubmit={handleLogin}>
        <input type="text" name="username" required />
        <input type="password" name="password" required />
        <button type="submit">ログイン</button>
      </form>
      <br />
      <form onSubmit={apiCall}>
        id_token=
        <input type="text" name="idToken" required />
        <button type="submit">ApiCall</button>
      </form>
    </>
  );
}

使い方

①一つ目のformのインプットテキストにCognitoユーザーIDとパスワードを入力してログインボタン押下
②signIn関数が実行されるので、console.logで取得しているaccess tokenまたはid tokenをメモ
③ ②でメモしたtoken(access tokenを使う場合が多い)を二つ目のformのインプットテキストに入力しApiCallボタン押下
④apiGatewayCall関数が実行される。
 正しく実行されていれば、result.messageに「Hello from Lambda!」200が返ってくる
 認証エラーの場合、result.messageに「Unauthorized」401が返ってくる

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1