AWS Amplify를 사용하여 Cognito로 Facebook 로그인 구현하기
Facebook 로그인을 AWS Amplify와 Cognito로 구현하기
지금까지의 가이드에서는 Cognito 사용자 풀을 사용하여 데모 노트 앱에 사용자를 등록했습니다. 이는 사용자가 이메일과 비밀번호로 계정을 등록해야 함을 의미합니다. 하지만 여러분은 사용자가 Facebook이나 Google 계정으로 앱에 가입할 수 있기를 원할 수 있습니다. 이렇게 하면 사용자가 사이트마다 다른 이메일과 비밀번호 조합을 기억할 필요가 없어집니다. 이번 장에서는 데모 앱에 “Facebook으로 로그인” 옵션을 추가하는 방법을 살펴보겠습니다.
이번 장에서 사용된 노트 앱 버전은 다음에서 확인할 수 있습니다:
- 별도의 GitHub 저장소: https://github.com/AnomalyInnovations/serverless-stack-demo-fb-login-client
- 접속 가능한 URL: https://demo-fb-login.sst.dev
이번 장의 주요 아이디어와 코드는 오랜 독자이자 기여자인 Peter Eman Paver Abastillas가 제공했습니다.
시작하기 전에 사용자가 로그인할 Facebook 앱을 만들어 보겠습니다.
Facebook 앱 만들기
http://developers.facebook.com/로 이동하여 My Apps > Add New App을 클릭해 새 앱을 만드세요.
Facebook Login 아래에서 Set Up을 선택하세요.
그리고 Web을 선택하세요.
Quickstart의 첫 번째 단계에서 앱의 URL을 http://localhost:3000
으로 설정하세요. 또는 Create React App에서 HTTPS 옵션을 사용한다면 https://localhost:3000
으로 설정하세요. Save를 클릭하세요.
Continue를 클릭해 Quickstart의 나머지 단계를 진행할 수 있습니다.
마지막으로 Settings > Basic으로 이동해 App ID를 메모해 두세요.
이 App ID는 AWS와 React 부분을 설정할 때 필요합니다.
다음으로 Cognito Identity Pool을 사용해 아이덴티티를 연동할 것입니다. 이는 사용자가 Facebook 계정으로 가입하면 Identity Pool에 추가되고, 서버리스 백엔드 API에서 사용할 수 있는 ID를 얻게 된다는 의미입니다. 이 ID는 사용자가 나중에 다시 로그인해도 동일하게 유지됩니다. Identity Pool과 User Pool의 차이점이 헷갈린다면 Cognito user pool vs identity pool 챕터를 참고하세요.
Facebook를 인증 프로바이더로 추가하기
AWS 콘솔로 이동한 후, Cognito로 가서 Manage Identity Pools를 클릭하세요.
앱에서 사용 중인 Identity Pool을 선택하세요.
상단에서 Edit identity pool을 클릭하세요.
아래로 스크롤하여 Authentication providers를 확장하세요.
기본 옵션으로 Cognito가 설정되어 있는 것을 확인할 수 있습니다. Facebook 탭을 선택하고 Unlock을 클릭한 후, 위에서 복사한 Facebook App ID를 붙여넣으세요.
아래로 스크롤하여 Save Changes를 클릭하세요.
이제 AWS 설정이 완료되었으니, React 앱으로 이동해 보겠습니다.
AWS Amplify로 Facebook 로그인 설정하기
React 앱에서 Facebook JS SDK와 AWS Amplify를 사용해 Facebook 로그인을 설정할 것입니다. 작업 중인 앱 버전은 GitHub 저장소에서 확인할 수 있습니다.
주요 변경 사항을 간단히 살펴보겠습니다.
먼저 Facebook App ID를 src/config.js
에 추가합니다. 파일은 다음과 같이 보일 것입니다.
export default {
s3: {
REGION: "YOUR_S3_UPLOADS_BUCKET_REGION",
BUCKET: "YOUR_S3_UPLOADS_BUCKET_NAME"
},
apiGateway: {
REGION: "YOUR_API_GATEWAY_REGION",
URL: "YOUR_API_GATEWAY_URL"
},
cognito: {
REGION: "YOUR_COGNITO_REGION",
USER_POOL_ID: "YOUR_COGNITO_USER_POOL_ID",
APP_CLIENT_ID: "YOUR_COGNITO_APP_CLIENT_ID",
IDENTITY_POOL_ID: "YOUR_IDENTITY_POOL_ID"
},
social: {
FB: "YOUR_FACEBOOK_APP_ID"
}
};
YOUR_FACEBOOK_APP_ID
를 위에서 얻은 ID로 바꿔주세요.
다음으로 src/App.js
의 componentDidMount
메서드에서 Facebook JS SDK를 로드합니다.
async componentDidMount() {
this.loadFacebookSDK();
try {
await Auth.currentAuthenticatedUser();
this.userHasAuthenticated(true);
} catch (e) {
if (e !== "not authenticated") {
alert(e);
}
}
this.setState({ isAuthenticating: false });
}
loadFacebookSDK() {
window.fbAsyncInit = function() {
window.FB.init({
appId : config.social.FB,
autoLogAppEvents : true,
xfbml : true,
version : 'v3.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
}
또한 Auth.currentAuthenticatedUser
메서드를 사용해 현재 인증된 사용자를 로드합니다. 여기서 Auth
는 AWS Amplify 패키지의 일부입니다.
src/App.js
상단에서 config를 임포트하는 것을 잊지 마세요.
import config from "./config";
이제 src/components/FacebookButton.js
에 Facebook 로그인 버튼 컴포넌트를 만듭니다.
import React, { Component } from "react";
import { Auth } from "aws-amplify";
import LoaderButton from "./LoaderButton";
function waitForInit() {
return new Promise((res, rej) => {
const hasFbLoaded = () => {
if (window.FB) {
res();
} else {
setTimeout(hasFbLoaded, 300);
}
};
hasFbLoaded();
});
}
export default class FacebookButton extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
}
async componentDidMount() {
await waitForInit();
this.setState({ isLoading: false });
}
statusChangeCallback = response => {
if (response.status === "connected") {
this.handleResponse(response.authResponse);
} else {
this.handleError(response);
}
};
checkLoginState = () => {
window.FB.getLoginStatus(this.statusChangeCallback);
};
handleClick = () => {
window.FB.login(this.checkLoginState, {scope: "public_profile,email"});
};
handleError(error) {
alert(error);
}
async handleResponse(data) {
const { email, accessToken: token, expiresIn } = data;
const expires_at = expiresIn * 1000 + new Date().getTime();
const user = { email };
this.setState({ isLoading: true });
try {
const response = await Auth.federatedSignIn(
"facebook",
{ token, expires_at },
user
);
this.setState({ isLoading: false });
this.props.onLogin(response);
} catch (e) {
this.setState({ isLoading: false });
this.handleError(e);
}
}
render() {
return (
<LoaderButton
block
bsSize="large"
bsStyle="primary"
className="FacebookButton"
text="Login with Facebook"
onClick={this.handleClick}
disabled={this.state.isLoading}
/>
);
}
}
여기서 어떤 작업을 하는지 간단히 살펴보겠습니다.
-
먼저
waitForInit
메서드에서 Facebook JS SDK가 로드될 때까지 기다립니다. 로드가 완료되면 Login with Facebook 버튼을 활성화합니다. -
사용자가 버튼을 클릭하면
FB.login
을 사용해 로그인 프로세스를 시작하고,statusChangeCallback
에서 로그인 상태 변경을 감지합니다. 이 메서드를 호출할 때{scope: "public_profile,email"}
을 설정해 사용자의 공개 프로필과 이메일 주소를 요청합니다. -
사용자가 앱에 권한을 부여하면 Facebook에서 받은 정보(사용자의 이메일)를 사용해 AWS Amplify의
Auth.federatedSignIn
메서드를 호출합니다. 이렇게 하면 사용자가 로그인됩니다.
마지막으로 FacebookButton.js
를 src/containers/Login.js
와 src/containers/Signup.js
에서 사용할 수 있습니다.
<FacebookButton
onLogin={this.handleFbLogin}
/>
<hr />
로그인 및 회원가입 폼 위에 버튼을 추가합니다. 그리고 import FacebookButton from "../components/FacebookButton";
를 사용해 임포트하는 것을 잊지 마세요.
또한 핸들러 메서드도 추가합니다.
handleFbLogin = () => {
this.props.userHasAuthenticated(true);
};
위 코드는 Facebook 회원가입 프로세스가 완료되면 사용자를 React 앱에 로그인시킵니다. src/containers/Signup.js
에도 동일하게 추가하세요.
이제 앱으로 이동하면 Facebook으로 로그인 옵션이 보일 것입니다.
클릭하면 앱으로 로그인하라는 Facebook 다이얼로그가 나타납니다.
로그인 후에는 이전과 동일하게 앱과 상호작용할 수 있습니다.
앱 배포에 대한 마지막 참고사항입니다. 위에서 Facebook이 https://localhost:3000
URL을 사용하도록 설정했던 것을 기억할 것입니다. React 앱을 배포할 때는 이 URL을 실제 URL로 변경해야 합니다. 좋은 방법은 실제 사용자를 위한 Facebook 앱과 로컬 테스트를 위한 Facebook 앱을 각각 만드는 것입니다. 이렇게 하면 URL을 변경할 필요 없이 변경 사항을 테스트할 수 있는 환경을 갖출 수 있습니다.
For help and discussion
Comments on this chapter