본문 바로가기
✍️ 글쓰기/💻 배우고

Amazon Cognito와 Amplify로 리액트 앱에서 Authentication 구현하기

by ddubimoon 2022. 5. 14.

■ Amazon Cognito란?

Amazon Cognito는 웹 및 모바일 앱에 대한 인증, 권한 부여 및 사용자 관리를 제공한다. 사용자는 사용자 이름과 암호를 이용하여 직접 로그인하거나 Facebook, Amazon, Google 또는 Apple 같은 타사를 통해 로그인할 수 있다.

 

사용자 인증 이후 AWS 서비스에 대한 사용자 액세스 권한을 부여하는 과정이다. 

1. 첫 번째 단계에서 앱 사용자는 사용자 풀(User pool)을 통해 로그인하여 인증 성공 이후 사용자 풀 토큰을 부여 받는다.
2. 앱은 자격 증명 풀(Identity Pool)을 통해 사용자 풀 토큰을 AWS 자격 증명으로 교환한다. 
3. 앱 사용자는 AWS 자격 증명을 사용하여 Amazon S3, Dynamo DB 등 다른 AWS 서비스에 엑세스 할 수 있다.

https://docs.aws.amazon.com/ko_kr/cognito/latest/developerguide/what-is-amazon-cognito.html

■ Amazon Cognito 시작하기

사전 확인사항 | Precondition

AWS 루트 계정 및 IAM 계정 생성이 필요하다. 자세한 사항은 공식문서를 참고하면 된다.

 

사용자 풀 시작하기

1. Amazon Cognito > User pools > Create user pool

 

2. 로그인 환경 구성 (Configure sign-in experience)에서 사용자 풀에 사용할 페더레이션 공급자 선택 
- Facebook, Google, Amazon 등 서드 파티를 통해 사용자 로그인을 구현할 경우 Federated Identity providers

- 앱 사용자는 사용자 풀을 통해 직접 로그인하거나 타사 자격 증명 공급자(IdP)를 통해서 연동 로그인할 수 있다. 
이때 Amazon Cognito의 사용자 풀에서 Facebook, Google, Apple, Amazon 등 소셜 로그인에서 반환된 토큰을 처리하는 작업을 관리해준다. 

https://docs.aws.amazon.com/ko_kr/cognito/latest/developerguide/cognito-user-pools-identity-federation.html

- 그리고 이어서 사용자가 로그인 하는 옵션을 설정할 수 있다. (이메일, username, 핸드폰 번호).
Allow users to sign in with a preferred user name: 사용자가 원하는 username으로 로그인할 수 있다.
Make user name case sensitive: 대소문자 구분이 있는 username을 사용한다.

- 어떤 서드 파티를 통해 로그인할지 고를 수 있다: Facebook, Google, Amazon, Apple ...

 

3. 보안 요구사항 구성 (Configure security requirements)에서 암호 정책, 멀티 팩터 인증(MFA) 요구 사항, 사용자 계정 복구 옵션을 선택한다.  
- 비밀번호 정책을 설정할 수 있다. Cognito에서 제공하는 기본 정책 템플렛을 선택하거나, 커스텀 정책을 선택할 수 있다.

- 멀티 팩터 인증 옵션을 선택한다. 사용자가 무조건 멀티 팩터 인증을 하도록 하거나, 옵션으로 선택할 수 있다.
- MFA 방법으로는 authenticator 앱을 이용하거나 SMS 문자 메시지를 이용할 수 있다.

4. 가입 환경 구성 (Configure sign-up experience)에서 새 사용자가 가입할 때 자격 증명을 확인하는 방법과 사용자 가입 흐름 중 필수 또는 선택 사항이어야 한느 속성을 결정할 수 있다. 
- 나는 회사 내부에서만 쓰는 앱 프로젝트였기 때문에 아무나 sign-up 할 수 있는 것이 아닌, 인증된 사용자만 가입하고 이용할 수 있도록 self-registration 옵션을 선택하지 않았다.

5. 메시지 전달 구성 (Configure message delivery)에서 가입, 계정 확인, MFA, 계정 복구를 위해 사용자에게 이메일과 SMS 메시지를 전송하도록 설정할 수 있다. 
- 마찬가지로, 팀 내부에서 쓰는 앱이기 때문에 큰 볼륨의 이메일을 처리할 일이 없어 Sent email with Cognito 옵션 선택

사용자 풀에 App Client 생성하기

1. Amazon Cognito > User Pool > App integration > App client list > Create app client

2. 어플리케이션 유형 (Application type)을 선택한다. 호스트된 UI를 사용하는 앱은 Public client이다.
- App Client 이름을 설정한다. 
- Public Client를 선택하면 클라이언트 암호가 필요하지 않다. 그래서 Don't generate a client secret을 선택하기. 

 

- 나는 기본값 설정에서 따로 바꾼 것 없이 app client를 생성했다. 

React 앱 - AWS Cognito 연결

1. 리액트 앱에 연결하기 위해서 필요한 App client ID 와 Pool ID
- 각각 App client 와 Pool 기본 정보란에서 ID를 찾으면 된다

2. 리액트 앱에서 로그인 페이지를 구현하기 위해 Amplify UI를 쓰려고 한다. 
- Amplify UI란?
Amazon Web Service에서 지원하는 오픈 소스 디자인 시스템이다. 클라우드로 연결되는 컴포넌트(component)와 프리미티브(primitive)들로 리액트, 앵귤러, 뷰, 플러터(Flutter) 등으로 감각적이고 세련된 앱들을 만들 수 있도록 해준다. 
- Amplify UI 디펜던시 설치

npm i @aws-amplify/ui-react aws-amplify

src 디렉토리 아래에 awsconfig.js 파일을 만들어 위에서 가져온 인증 정보들을 적어준다. 

// aws-config.js

export default {
    Auth: {
        region: "us-east-1",
        userPoolId: "us-east-1-----6",
        userPoolWebClientId: "5--------------------g",
        madatorySignIn: false,
    }
}

- 나는 로그인 한 유저에 한해 앱에 접근할 수 있도록 하기 위해 App.jsApp() 함수의 리턴값 자체를 <Authenticator> 태그로 감싸주었다. 
modal 모드로, 로그인 창이 화면에 떠있을 수 있도록 했고, 관리자 페이지였기 때문에 aws 콘솔에서 직접 등록한 유저가 아니면 따로 회원가입을 할 수 없도록 SignUp 기능을 숨겨두었다. 

// App.js

import './App.css';
import Amplify from 'aws-amplify';
import awsConfig from './aws-config';
import {Authenticator} from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

Amplify.configure(awsConfig);

function App() {
	return (
    	<Authenticator variation='modal' hideSignUp={true}>
        	<div>
            	Private Component ...
            </div>
        </Authenticator>
    )
}

export default App;

modal 모드이기 때문에 전체 화면을 차지하는 것이 아닌 팝업창처럼 로그인 페이지를 만들 수 있다.

3. Sign out 버튼 만들기
- 로그인 한 후 보여지는 페이지에서 원하는 곳에 Sign Out 버튼을 만든 다음 아래와 같은 함수를 넣어주면 된다.

// SignOutButtonComponent.js

import React from 'react';
import Button from '@mui/material/Button';
import {Auth} from 'aws-amplify';

async function signOut() {
	try {
    	await Auth.signOut();
    } catch (err) {
    	console.log('error signing out: ', err);
    }
}

const SignOutButton = () => {
	return (
		<Button variant='contained' size='small' onClick={signOut}>
        	Sign Out
        </Button>
    );
};

export default SignOutButton;

 

Reference

댓글