Firebase Authentication
- 쉽게 사용자 인증을 구현할 수 있도록 돕는 Firebase 서비스
- 이메일과 비밀번호 인증, 소셜 미디어 인증, 전화번호 인증
- 인증 정보 안전하게 저장(보안이 강화되어 있음)
- 인증 정보 변경시 실시간으로 앱에 업데이트
- 인증 이메일 전송, 비밀번호 재설정 이메일 전송 등의 기능
로컬 회원가입
- Firebase 프로젝트 생성, Firebase SDK 앱 추가
- Firebase 초기화
- Firebase Authentication 함수로 사용자 인증
소셜 로그인(Google OAuth)
- Google 제공업체 객체의 인스턴스를 생성
- Google 제공업체 객체를 사용해 Firebase에 인증(signInWithPopup)
Firebase Authentication 시작하기
- firebase console에 들어가 프로젝트 생성

- SDK발급을 위해 프로젝트를 선택 후 웹 선택

- 앱 이름을 입력

- SDK 발급

- firebaseApp.ts 파일에 설정
import { initializeApp, FirebaseApp, getApp } from "firebase/app";
export let app:FirebaseApp;
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_APP_ID,
};
try {
app = getApp("app");
} catch (e) {
app = initializeApp(firebaseConfig, "app");
}
const firebase = initializeApp(firebaseConfig);
export default firebase;
- 최상단 컴포넌트에서 getAuth를 이용해서 currentUser가 있는지 없는지 판별
import { getAuth } from "firebase/auth";
import { app } from "firebaseApp";
function App() {
const auth = getAuth(app);
return (
<Layout>
<Router />
</Layout>
);
}
createUserWithEmailAndPassword(회원가입)
- 공식문서
- 해당 프로젝트의 Authentication에 들어간 후 로그인 방법 탭에서 이메일/비밀번호 선택
const onSubmit = async (e: any) => {
e.preventDefault();
try {
const auth = getAuth(app);
await createUserWithEmailAndPassword(auth, email, password);
navigate("/");
toast.success("성공적으로 회원가입이 되었습니다.");
} catch (error: any) {
toast.error(error?.code);
}
};
- 이러면 회원가입은 되지만 사용자를 인식하지 못하기에 새로고침을 해줘야하는 이슈가 있다.
- 이때 사용하는 것이
onAuthStateChanged
메서드이다. 공식문서
import Router from "pages/components/Router";
import { Layout } from "pages/components/Layout";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { app } from "firebaseApp";
import { useState, useEffect } from "react";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
function App() {
const auth = getAuth(app);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(
!!auth?.currentUser
);
const [init, setInit] = useState<boolean>(false);
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
setIsAuthenticated(true);
} else {
setIsAuthenticated(false);
}
setInit(true);
});
}, [auth]);
return (
<Layout>
<ToastContainer />
{init ? (
<>
<Router isAuthenticated={isAuthenticated} />
</>
) : (
"loading"
)}
</Layout>
);
}
export default App;
signInWithEmailAndPassword(로그인)
- 회원가입과 똑같고 signInWithEmailAndPassword만 바꾸면 된다.
const onSubmit = async (e: any) => {
e.preventDefault();
try {
const auth = getAuth(app);
await signInWithEmailAndPassword(auth, email, password);
navigate("/");
toast.success("성공적으로 회원가입이 되었습니다.");
} catch (error: any) {
toast.error(error?.code);
}
};
signOut(로그아웃)
const clickLogout = async () => {
const auth = getAuth(app);
await signOut(auth);
toast.success("로그아웃 되었습니다.");
}
OAuth란?
- OAuth(Open Authorization) : 사용자가 다른 애플리케이션 혹은 서비스의 리소스에 접근할 수 있도록 허용하는 프로토콜
- OAuth1.0 : 서명된 요청을 통해 사용자 인증 처리. 하지만 복잡하고 사용이 어려움
- OAuth2.0(SNS 로그인)
- 간결한 방식으로 사용자 인증.
- 클라이언트와 리소스 소유자 사이의 권한 부여 관리.
- 토큰 기반의 접근 방식 사용.
OAuth 구성요소
- 주요 원리 : 사용자의 계정 정보를 안전하게 다른 서비스의 리소스에 접근할 수 있게 하는 것
- Resource Owner : 보호된 리소스에 대한 액세스 권한을 가진 사용자 (ex : 사용자의 Google 계정은 리소스 오너)
- Client : 리소스에 접근하려는 애플리케이션/서비스
- Authorization Server : 사용자의 인증을 처리하고 클라이언트에게 액세스 토큰 제공
- Resource Server : 실제로 보호된 리소스를 호스팅하고 있는 서버
OAuth 인증과정
- client -> resource owner (리소스 접근 권한 요청)
- resource owner -> authorization server (요청 승인 & 권한 부여)
- authorization server -> client ( Access Token 발급)
- client -> resource server (Access Token 저장)
- resource server -> client (토큰 검증 & 요청 처리)
OAuth 장단점
- 사용자가 자신의 계정 정보를 외부 애플리케이션에 노출하지 않아도 됨
- 보안성 및 사용자 경험 향상(간편한 로그인/회원가입)
- 서비스 간에 사용자 정보 공유X. 각 서비스별 독립성 유지
- 하지만, OAuth를 직접 구현하고 관리하는 것은 복잡하고, 보안 이슈가 생길수도 있음
- Firebase의 Authentication은 복잡한 OAuth를 편리하게 구현할 수 있도록 도와줌
Firebase OAuth 적용
- Authentication에 들어간 후 새 제공업체 추가

- 공식문서
const onClickSocialLogin = async (e: any) => {
const {
target: { name },
} = e;
let provider;
const auth = getAuth(app);
if (name === "google") {
provider = new GoogleAuthProvider();
}
if (name === "github") {
provider = new GithubAuthProvider();
}
await signInWithPopup(
auth,
provider as GithubAuthProvider | GoogleAuthProvider
)
.then((result) => {
console.log(result);
toast.success("로그인 되었습니다.");
})
.catch((e) => {
console.log(e);
const errorMessage = e?.message;
toast.error(errorMessage);
});
};