自作ログイン画面でCognito認証をかける方法

# やり方
Amplifyを使わずに、一からログイン画面を作って、Cognito認証することをチャレンジしました！

amazon-cognito-identity-jsを使えば、なんとかできるのですが、最初はCognito認証の流れに苦戦したので、ブログとして残したいと思います！

# 早速ソースコード
まずamazon-cognito-identity-jsをインポートし、CognitoユーザプールのIDなど必要な環境変数を設定しておきます。（前提：AWSにCognitoを構築済み）

Cognitoのほうで、ログイン後のセッション管理や新規アカウント作成時のメール二段階認証をやっていくので、画面側はライブラリを使えば、ログイン ログアウト処理が簡単にできます～


```
import {
    CognitoUserPool,
    CognitoUser,
    AuthenticationDetails,
    CognitoUserAttribute,
    ICognitoUserPoolData,
} from 'amazon-cognito-identity-js';

import { jwtDecode } from "jwt-decode";

const UserPoolId = process.env.EXPO_PUBLIC_USERPOOL_ID || '';
const ClientId = process.env.EXPO_PUBLIC_CLIENT_ID || '';

const poolData: ICognitoUserPoolData = {
    UserPoolId,
    ClientId,
};

const userPool = new CognitoUserPool(poolData);

// ログイン状態（セッション）を取得する
export const getCurrentUserSession = (): Promise<CognitoUser | null> => {
    return new Promise((resolve, reject) => {
        const user = userPool.getCurrentUser();

        if (!user) {
            return reject(null);
        }

        user.getSession((err: any, session: any) => {
            if (err || !session?.isValid()) {
                return reject(null);
            }

            resolve(user);
        });
    });
}

// ログアウト
export const signOut = (): Promise<void> => {
    return new Promise((resolve) => {
        const user = userPool.getCurrentUser();

        if (user) {
            user.globalSignOut(
                {
                    onSuccess: () => resolve(),
                    onFailure: () => resolve(),
                }
            );
        } else {
            resolve();
        }

        resolve();
    });
}

// ログイン
export const signIn = (email: string, password: string): Promise<{ user: CognitoUser; session: any, groups: string[] }> => {
    return new Promise((resolve, reject) => {
        const user = new CognitoUser({ Username: email, Pool: userPool });
        const authDetails = new AuthenticationDetails({ Username: email, Password: password });

        user.authenticateUser(authDetails, {
            onSuccess: (session) => {
                const accessToken = session.getAccessToken().getJwtToken();
                const idToken = session.getIdToken().getJwtToken();

                const decodedToken: any = jwtDecode(idToken);
                const groups: string[] = decodedToken["cognito:groups"] || [];

                console.log('Access Token:', accessToken);
                console.log('ID Token:', idToken);
                console.log('Groups:', groups);

                resolve({ user, session, groups })
            },
            onFailure: (err) => reject(err),
        });
    });
}

// 新規アカウント作成
export const signUp = (email: string, password: string): Promise<any> => {
    return new Promise((resolve, reject) => {
        const emailAttribute = new CognitoUserAttribute({
            Name: 'email',
            Value: email,
        });

        const attributeList = [emailAttribute];

        userPool.signUp(email, password, attributeList, [], (err, result) => {
            if (err) {
                console.log(err.message || JSON.stringify(err))
                reject(err);
            }
            console.log(result);
            resolve(result);
        });
    });
}

// アカウント作成時の二段階認証
export const confirmSignUp = (email: string, confirmationCode: string): Promise<CognitoUser> => {
    return new Promise((resolve, reject) => {
        const user = new CognitoUser({
            Username: email,
            Pool: userPool,
        });

        user.confirmRegistration(confirmationCode, true, (err, result) => {
            if (err) {
                console.log(err);
                reject();
            }

            console.log(result);
            resolve(user);
        });
    });
}
```