{
    "componentChunkName": "component---src-templates-blog-post-js",
    "path": "/21-08-29-firebase-auth-sign-in-with-google/",
    "result": {"data":{"site":{"siteMetadata":{"title":"irrationnelle","author":"irrationnelle","siteUrl":"https://dev.rase.blog","comment":{"disqusShortName":"","utterances":"irrationnelle/devlog"},"sponsor":{"buyMeACoffeeId":""}}},"markdownRemark":{"id":"59aadbd8-0590-574d-aaf1-9042f2e6d64c","excerpt":"firebase 서버리스하면 다들 aws lambda 를 떠올리는 것 같지만, 나는 firebase 를 먼저 손에 꼽는다. 일단 나는 공식 문서의 불친절함과 직관성이 전혀 없는 대시보드 등으로 aws 서비스를 우호적으로 생각하지 않는다. 그래서 개인 프로젝트는 gcp 나 azure 를 시도해보려고 하는데, firebase 는 이중에서도 가장 접근성이 좋다. back-end 의 스펙에 대해 어느 정도 익숙하고 sdk…","html":"<h1 id=\"firebase\" style=\"position:relative;\"><a href=\"#firebase\" aria-label=\"firebase permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>firebase</h1>\n<p>서버리스하면 다들 aws lambda 를 떠올리는 것 같지만, 나는 firebase 를 먼저 손에 꼽는다.</p>\n<p>일단 나는 공식 문서의 불친절함과 직관성이 전혀 없는 대시보드 등으로 aws 서비스를 우호적으로 생각하지 않는다.</p>\n<p>그래서 개인 프로젝트는 gcp 나 azure 를 시도해보려고 하는데, firebase 는 이중에서도 가장 접근성이 좋다.</p>\n<p>back-end 의 스펙에 대해 어느 정도 익숙하고 sdk 라는 걸 다뤄본 적이 있다면 소규모 프로젝트나 프로젝트의 와이어 프레임 구현으로는 아주 적격이다.</p>\n<p>난 웹앱 환경에서만 사용했지만, android 와 ios 환경도 지원하기 때문에 정말 이만한 서비스가 없다.</p>\n<h1 id=\"firebase-auth\" style=\"position:relative;\"><a href=\"#firebase-auth\" aria-label=\"firebase auth permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>firebase auth</h1>\n<p>firebase 를 이용해서 로그인 구현 및 인증처리하는 방법은 간단한데, 이메일 주소와 비밀번호를 사용하는 경우 다음처럼 처리한다.</p>\n<p>예제는 <a href=\"https://github.com/firebase/snippets-web/blob/eee411f0580eb061e4c6eeabf9b4fd8aac9b49ab/auth/email.js#L28-L38\">여기</a>에서 가져왔다.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">import</span> firebase <span class=\"token keyword\">from</span> <span class=\"token string\">\"firebase/app\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">\"firebase/auth\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">signUpWithEmailPassword</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> email <span class=\"token operator\">=</span> <span class=\"token string\">\"test@example.com\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> password <span class=\"token operator\">=</span> <span class=\"token string\">\"hunter2\"</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> userCredential <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> firebase<span class=\"token punctuation\">.</span><span class=\"token function\">auth</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">createUserWithEmailAndPassword</span><span class=\"token punctuation\">(</span>email<span class=\"token punctuation\">,</span> password<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> errorCode <span class=\"token operator\">=</span> error<span class=\"token punctuation\">.</span>code<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> errorMessage <span class=\"token operator\">=</span> error<span class=\"token punctuation\">.</span>message<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>예제에서 반환한 userCredential 에서는 이메일 인증을 완료했는지 확인하는 property 까지 가지고 있다.</p>\n<p>단점이 있다면, 사용자에 custom property 같은 걸 추가하고 싶다면 별도로 realtime database 나 firestore database 에서 사용자를 다루는 테이블을 만들어야 한다.</p>\n<p>하지만 단순히 클라이언트 사용자의 유효성을 판단하기 위해서라면 이걸로 끝이다. 토큰도 알아서 firebase sdk 가 관리한다.</p>\n<h1 id=\"google-로그인\" style=\"position:relative;\"><a href=\"#google-%EB%A1%9C%EA%B7%B8%EC%9D%B8\" aria-label=\"google 로그인 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Google 로그인</h1>\n<p>firebase 는 구글에서 제공하는 서비스이니, 구글 로그인도 쉽다.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">import</span> firebase <span class=\"token keyword\">from</span> <span class=\"token string\">\"firebase/app\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">\"firebase/auth\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">signInWithGoogle</span><span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> provider <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">firebase</span><span class=\"token punctuation\">.</span>auth<span class=\"token punctuation\">.</span><span class=\"token function\">GoogleAuthProvider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  provider<span class=\"token punctuation\">.</span><span class=\"token function\">addScope</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://www.googleapis.com/auth/contacts.readonly'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// ref: https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters</span>\n  provider<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomParameters</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">'prompt'</span><span class=\"token operator\">:</span> <span class=\"token string\">'select_account'</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> firebase<span class=\"token punctuation\">.</span><span class=\"token function\">auth</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">signInWithPopup</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> credential <span class=\"token operator\">=</span> result<span class=\"token punctuation\">.</span>credential<span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// This gives you a Google Access Token. You can use it to access the Google API.</span>\n    <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> credential<span class=\"token punctuation\">.</span>accessToken<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> user <span class=\"token operator\">=</span> result<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> errorCode <span class=\"token operator\">=</span> error<span class=\"token punctuation\">.</span>code<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> errorMessage <span class=\"token operator\">=</span> error<span class=\"token punctuation\">.</span>message<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><code class=\"language-text\">provider.setCustomParameters</code> 의 인자로 전달하는 옵션값은 주석의 링크를 참고하자.</p>\n<h1 id=\"그런데-google-로그인이-안된다\" style=\"position:relative;\"><a href=\"#%EA%B7%B8%EB%9F%B0%EB%8D%B0-google-%EB%A1%9C%EA%B7%B8%EC%9D%B8%EC%9D%B4-%EC%95%88%EB%90%9C%EB%8B%A4\" aria-label=\"그런데 google 로그인이 안된다 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>그런데 Google 로그인이 안된다.</h1>\n<p>여러가지를 고려할 수 있다.</p>\n<ul>\n<li>gcp 의 <code class=\"language-text\">API 및 서비스</code> 메뉴의 <code class=\"language-text\">사용자 인증 정보</code> 에서 api 키의 권한을 조정하고 api 를 요청하는 도메인 권한을 설정해주어야 할 수 있다.</li>\n<li>firebase 의 authentication 메뉴를 선택하고, Sign-in method 탭에서 승인된 도메인을 설정해야 할 수 있다.</li>\n</ul>\n<p>그런데 내 경우, 둘 다 아니었고 이것저것 많이 시도해보다 아주 근본적이고 기초적인 부분의 문제였다는 것을 알 수 있었다.</p>\n<h1 id=\"firebaseinitializeapp-을-신중히\" style=\"position:relative;\"><a href=\"#firebaseinitializeapp-%EC%9D%84-%EC%8B%A0%EC%A4%91%ED%9E%88\" aria-label=\"firebaseinitializeapp 을 신중히 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>firebase.initializeApp() 을 신중히</h1>\n<p>firebase 앱을 사용하기 위해선, 모든 sdk 가 그렇듯 초기화 과정이 필요하다.</p>\n<p>이때 정말 많은 옵션들을 인자로 전달하는데, 그 옵션 중에 <code class=\"language-text\">authDomain</code> 라는 것이 있다.</p>\n<p>보통<code class=\"language-text\">PROJECT_ID.firebaseapp.com</code> 같은 형태인데, 나는 로컬호스트에서 테스트한다고 여기에 <code class=\"language-text\">localhost</code> 라는 값을 넣은 것이 문제였다.</p>\n<p>그럼 인증을 하기 위해서 <code class=\"language-text\">localhost/something-auth-url</code> 같은 곳에다 요청을 하는데 당연히 뭐가 될리가 없다.</p>\n<p>그래서 <code class=\"language-text\">localhost:3000</code> 으로 변경했더니, firebase sdk 가 예외를 던진다.</p>\n<p>혼란스러운 와중 스택 트레이스를 차분히 따라가보니 port number 같은 게 authDomain 에 존재하면 던지는 예외였다.</p>\n<p>결국 기존의<code class=\"language-text\">PROJECT_ID.firebaseapp.com</code> 로 <code class=\"language-text\">authDomain</code> 을 바꿔주니 모든 것이 정상적으로 작동했다.</p>\n<p>생각해보니 당연한 것이, 구글 인증 과정을 내 로컬에서 처리하려고 했다는 것인데 내가 firebase sdk 를 완전히 뜯어고쳐서 로컬에서 가능하게 한 것이 아닌 이상,</p>\n<p>구글이 제공하는 authDomain 을 사용하는 것이 맞는 거였다. 내가 localhost 에서 테스트를 하든 staging 서버에서 테스트를 하든, prod 단계까지 가든 authDomain 은 구글이 제공한 곳에서 이루어지는 게 당연한 것 아닌가.</p>\n<h1 id=\"결론\" style=\"position:relative;\"><a href=\"#%EA%B2%B0%EB%A1%A0\" aria-label=\"결론 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>결론</h1>\n<p>local 환경이라고 안일하게 설정하면 안 된다는 사실을 깨달았고, sdk 를 사용하는 것이 무엇을 의미하는지 새삼스레 깨달을 수 있는 계기였다.</p>","frontmatter":{"title":"firebase auth 이용하여 google 로그인 구현","date":"August 29, 2021"}}},"pageContext":{"slug":"/21-08-29-firebase-auth-sign-in-with-google/","previous":{"fields":{"slug":"/21-03-20-magic-number/"},"frontmatter":{"title":"매직 넘버를 지양해야 하는 이유","category":"Dev","draft":false}},"next":{"fields":{"slug":"/21-10-07-test-and-spec-again/"},"frontmatter":{"title":"다시, 테스트 코드는 왜 스펙인가","category":"dev","draft":false}}}},
    "staticQueryHashes": ["3128451518","3474900066"]}