FirebaseUI로 손쉽게 웹 앱에 로그인 추가

FirebaseUI는 Firebase 인증 SDK를 바탕으로 빌드된 라이브러리로, 앱에서 사용할 수 있는 삽입형 UI 흐름을 제공합니다. FirebaseUI의 이점은 다음과 같습니다.

  • 여러 제공업체: 이메일/비밀번호, 이메일 링크, 휴대전화 인증, Google, Facebook, Twitter, GitHub 로그인에 사용되는 로그인 흐름을 제공합니다.
  • 계정 연결: 여러 ID 공급업체에서 사용자 계정을 안전하게 연결하는 흐름을 제공합니다.
  • 맞춤설정 - 앱의 요구사항에 맞게 FirebaseUI의 CSS 스타일을 재정의합니다. 또한 FirebaseUI는 오픈소스이므로 프로젝트를 포크하여 요구사항에 정확히 맞게 맞춤설정할 수 있습니다.
  • 원탭 가입 및 자동 로그인: 빠르게 교차 기기 로그인을 할 수 있도록 원탭 가입과 자동 통합됩니다.
  • 현지화된 UI: 40개 이상 언어로 국제화됩니다.
  • 익명 사용자 업그레이드 - 로그인/가입을 통해 익명 사용자를 업그레이드할 수 있습니다. 자세한 내용은 익명 사용자 업그레이드 섹션을 참조하세요.

시작하기 전에

  1. 웹 애플리케이션에 Firebase 인증을 추가하고 v9 compat(권장) 또는 이전 SDK를 사용 중인지 확인합니다(위 사이드바 참조).

  2. 다음 방법 중 하나를 통해 FirebaseUI를 포함합니다.

    1. CDN

      Firebase Console에서 페이지의 <head> 태그의 초기화 스니펫 밑에 다음 스크립트와 CSS 파일을 포함합니다.

      <script src="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.js"></script>
      <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.css" />
      
    2. npm 모듈

      다음 명령어를 사용하여 npm을 통해 FirebaseUI와 종속 항목을 설치합니다.

      $ npm install firebaseui --save
      

      소스 파일 내에서 다음 모듈을 require 처리합니다.

      var firebase = require('firebase');
      var firebaseui = require('firebaseui');
      
    3. Bower 구성요소

      다음 명령어를 사용하여 Bower를 통해 FirebaseUI와 종속 항목을 설치합니다.

      $ bower install firebaseui --save
      

      HTTP 서버가 bower_components/ 안의 파일을 제공하는 경우 필요한 파일을 HTML에 포함합니다.

      <script src="bower_components/firebaseui/dist/firebaseui.js"></script>
      <link type="text/css" rel="stylesheet" href="bower_components/firebaseui/dist/firebaseui.css" />
      

FirebaseUI 초기화

SDK를 가져온 후 인증 UI를 초기화합니다.

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());

로그인 방법 설정

사용자 로그인에 Firebase를 사용하려면 먼저 지원하려는 로그인 방법을 사용 설정하고 구성해야 합니다.

이메일 주소 및 비밀번호

  1. Firebase Console에서 인증 섹션을 열고 이메일과 비밀번호 인증을 사용 설정합니다.

  2. FirebaseUI signInOptions 목록에 이메일 제공업체 ID를 추가합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        firebase.auth.EmailAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  3. 선택사항: 사용자가 표시 이름을 입력하도록 EmailAuthProvider를 구성할 수 있습니다(기본값: true).

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          requireDisplayName: false
        }
      ]
    });
    
  1. Firebase Console에서 인증 섹션을 엽니다. 로그인 방법 탭에서 이메일/비밀번호 제공업체를 사용 설정합니다. 이메일 링크 로그인을 사용하려면 이메일/비밀번호 로그인이 사용 설정되어야 합니다.

  2. 같은 섹션에서 이메일 링크(비밀번호가 없는 로그인) 로그인 방법을 사용 설정하고 저장을 클릭합니다.

  3. FirebaseUI signInOptions 목록에 이메일 제공업체 ID와 이메일 링크 signInMethod를 추가합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
        }
      ],
      // Other config options...
    });
    
  4. (단일 페이지 앱과 관련해) 조건부로 로그인 UI를 렌더링하는 경우 ui.isPendingRedirect()를 사용하여 이 URL이 이메일 링크를 사용하는 로그인에 해당하며 로그인을 완료하려면 UI를 렌더링해야 하는지 감지합니다.

    // Is there an email link sign-in?
    if (ui.isPendingRedirect()) {
      ui.start('#firebaseui-auth-container', uiConfig);
    }
    // This can also be done via:
    if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
      ui.start('#firebaseui-auth-container', uiConfig);
    }
    
  5. 선택사항: 이메일 링크 로그인의 EmailAuthProvider를 구성하여 사용자의 교차 기기 로그인 수행을 허용하거나 차단할 수 있습니다.

    선택사항인 emailLinkSignIn 콜백을 정의하여 링크를 전송할 때 사용할 firebase.auth.ActionCodeSettings 구성을 반환할 수 있습니다. 이를 통해 링크 처리 방식, 커스텀 동적 링크, 딥 링크의 추가 상태 등을 지정할 수 있습니다. 이러한 구성이 제공되지 않으면 현재 URL이 사용되며 웹 전용 흐름이 트리거됩니다.

    FirebaseUI-web의 이메일 링크 로그인은 FirebaseUI-AndroidFirebaseUI-iOS와 호환되어 FirebaseUI-Android에서 흐름을 시작한 사용자가 링크를 열고 FirebaseUI-web으로 로그인을 완료할 수 있습니다. 이와 역순으로 진행되는 흐름 역시 가능합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
          signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD,
          // Allow the user the ability to complete sign-in cross device,
          // including the mobile apps specified in the ActionCodeSettings
          // object below.
          forceSameDevice: false,
          // Used to define the optional firebase.auth.ActionCodeSettings if
          // additional state needs to be passed along request and whether to open
          // the link in a mobile app if it is installed.
          emailLinkSignIn: function() {
            return {
              // Additional state showPromo=1234 can be retrieved from URL on
              // sign-in completion in signInSuccess callback by checking
              // window.location.href.
              url: 'https://www.example.com/completeSignIn?showPromo=1234',
              // Custom FDL domain.
              dynamicLinkDomain: 'example.page.link',
              // Always true for email link sign-in.
              handleCodeInApp: true,
              // Whether to handle link in iOS app if installed.
              iOS: {
                bundleId: 'com.example.ios'
              },
              // Whether to handle link in Android app if opened in an Android
              // device.
              android: {
                packageName: 'com.example.android',
                installApp: true,
                minimumVersion: '12'
              }
            };
          }
        }
      ]
    });
    

OAuth 제공업체(Google, Facebook, Twitter, GitHub)

  1. Firebase Console에서 인증 섹션을 열고 지정된 OAuth 제공업체 로그인을 사용 설정합니다. 해당 OAuth 클라이언트 ID와 보안 비밀도 지정해야 합니다.

  2. 인증 섹션에서 로그인 페이지를 렌더링할 도메인이 승인된 도메인 목록에 추가되었는지도 확인합니다.

  3. FirebaseUI signInOptions 목록에 OAuth 제공업체 ID를 추가합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        // List of OAuth providers supported.
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        firebase.auth.GithubAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 선택사항: 커스텀 범위 또는 제공업체별 커스텀 OAuth 매개변수를 지정하려면 제공업체 값만 전달하지 말고 객체를 전달합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID,
          scopes: [
            'https://www.googleapis.com/auth/contacts.readonly'
          ],
          customParameters: {
            // Forces account selection even when one account
            // is available.
            prompt: 'select_account'
          }
        },
        {
          provider: firebase.auth.FacebookAuthProvider.PROVIDER_ID,
          scopes: [
            'public_profile',
            'email',
            'user_likes',
            'user_friends'
          ],
          customParameters: {
            // Forces password re-entry.
            auth_type: 'reauthenticate'
          }
        },
        firebase.auth.TwitterAuthProvider.PROVIDER_ID, // Twitter does not support scopes.
        firebase.auth.EmailAuthProvider.PROVIDER_ID // Other providers don't need to be given as object.
      ]
    });
    

전화번호

  1. Firebase Console에서 인증 섹션을 열고 전화번호 로그인을 사용 설정합니다.

  2. 로그인 페이지를 렌더링할 도메인이 승인된 도메인 목록에 추가되었는지도 확인합니다.

  3. FirebaseUI signInOptions 목록에 전화번호 제공업체 ID를 추가합니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        firebase.auth.PhoneAuthProvider.PROVIDER_ID
      ],
      // Other config options...
    });
    
  4. 선택사항: PhoneAuthProvider를 커스텀 reCAPTCHA 매개변수와 함께 구성하여 reCAPTCHA 표시 여부를 지정할 수 있습니다(기본값: normal). 자세한 내용은 reCAPTCHA API 문서를 참조하세요.

    전화번호 입력 시 기본적으로 선택되는 국가도 설정할 수 있습니다. 전체 코드 목록은 지원되는 국가 코드 목록을 참조하세요. 지정하지 않으면 전화번호 입력 시 기본적으로 미국(+1)이 지정됩니다.

    현재 지원되는 옵션은 다음과 같습니다.

    ui.start('#firebaseui-auth-container', {
      signInOptions: [
        {
          provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
          recaptchaParameters: {
            type: 'image', // 'audio'
            size: 'normal', // 'invisible' or 'compact'
            badge: 'bottomleft' //' bottomright' or 'inline' applies to invisible.
          },
          defaultCountry: 'GB', // Set default country to the United Kingdom (+44).
          // For prefilling the national number, set defaultNationNumber.
          // This will only be observed if only phone Auth provider is used since
          // for multiple providers, the NASCAR screen will always render first
          // with a 'sign in with phone number' button.
          defaultNationalNumber: '1234567890',
          // You can also pass the full phone number string instead of the
          // 'defaultCountry' and 'defaultNationalNumber'. However, in this case,
          // the first country ID that matches the country code will be used to
          // populate the country selector. So for countries that share the same
          // country code, the selected country may not be the expected one.
          // In that case, pass the 'defaultCountry' instead to ensure the exact
          // country is selected. The 'defaultCountry' and 'defaultNationaNumber'
          // will always have higher priority than 'loginHint' which will be ignored
          // in their favor. In this case, the default country will be 'GB' even
          // though 'loginHint' specified the country code as '+1'.
          loginHint: '+11234567890'
        }
      ]
    });
    

로그인

FirebaseUI 로그인 흐름을 시작하려면 기본 Auth 인스턴스를 전달하여 FirebaseUI 인스턴스를 초기화합니다.

// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());

FirebaseUI 로그인 위젯을 렌더링할 HTML 요소를 정의합니다.

<!-- The surrounding HTML is left untouched by FirebaseUI.
     Your app may use that space for branding, controls and other customizations.-->
<h1>Welcome to My Awesome App</h1>
<div id="firebaseui-auth-container"></div>
<div id="loader">Loading...</div>

지원되는 제공업체, UI 맞춤설정, 성공 콜백 등의 FirebaseUI 구성을 지정합니다.

var uiConfig = {
  callbacks: {
    signInSuccessWithAuthResult: function(authResult, redirectUrl) {
      // User successfully signed in.
      // Return type determines whether we continue the redirect automatically
      // or whether we leave that to developer to handle.
      return true;
    },
    uiShown: function() {
      // The widget is rendered.
      // Hide the loader.
      document.getElementById('loader').style.display = 'none';
    }
  },
  // Will use popup for IDP Providers sign-in flow instead of the default, redirect.
  signInFlow: 'popup',
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    // Leave the lines as is for the providers you want to offer your users.
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.TwitterAuthProvider.PROVIDER_ID,
    firebase.auth.GithubAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  // Terms of service url.
  tosUrl: '<your-tos-url>',
  // Privacy policy url.
  privacyPolicyUrl: '<your-privacy-policy-url>'
};

마지막으로 FirebaseUI 인증 인터페이스를 렌더링합니다.

// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);

익명 사용자 업그레이드

익명 사용자 업그레이드 사용 설정

익명 사용자가 영구 계정을 사용하여 로그인하거나 가입하는 경우 이 사용자가 가입 전에 수행했던 작업을 계속 수행할 수 있게 하려 합니다. 이렇게 하려면 로그인 UI를 구성할 때 autoUpgradeAnonymousUserstrue로 설정하면 됩니다. 이 옵션은 기본적으로 중지되어 있습니다.

익명 사용자 업그레이드 병합 충돌 처리

처음에 익명으로 로그인한 사용자가 기존 Firebase 사용자로 업그레이드하려는 경우가 있습니다. 기존 사용자는 다른 기존 사용자에 연결될 수 없으므로 위와 같은 경우 FirebaseUI가 firebaseui/anonymous-upgrade-merge-conflict 오류 코드와 함께 signInFailure 콜백을 트리거합니다. 이 오류 객체는 영구 사용자 인증 정보도 포함합니다. 로그인을 완료하려면 영구 사용자 인증 정보를 사용한 로그인이 콜백에서 트리거되어야 합니다. auth.signInWithCredential(error.credential)을 통해 로그인을 완료하려면 먼저 익명 사용자의 데이터를 저장하고 익명 사용자를 삭제해야 합니다. 그런 다음 로그인이 완료되면 익명이 아닌 사용자에게 데이터를 다시 복사합니다. 아래 예는 이러한 흐름의 작동 방식을 보여줍니다.

// Temp variable to hold the anonymous user data if needed.
var data = null;
// Hold a reference to the anonymous current user.
var anonymousUser = firebase.auth().currentUser;
ui.start('#firebaseui-auth-container', {
  // Whether to upgrade anonymous users should be explicitly provided.
  // The user must already be signed in anonymously before FirebaseUI is
  // rendered.
  autoUpgradeAnonymousUsers: true,
  signInSuccessUrl: '<url-to-redirect-to-on-success>',
  signInOptions: [
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
    firebase.auth.FacebookAuthProvider.PROVIDER_ID,
    firebase.auth.EmailAuthProvider.PROVIDER_ID,
    firebase.auth.PhoneAuthProvider.PROVIDER_ID
  ],
  callbacks: {
    // signInFailure callback must be provided to handle merge conflicts which
    // occur when an existing credential is linked to an anonymous user.
    signInFailure: function(error) {
      // For merge conflicts, the error.code will be
      // 'firebaseui/anonymous-upgrade-merge-conflict'.
      if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
        return Promise.resolve();
      }
      // The credential the user tried to sign in with.
      var cred = error.credential;
      // Copy data from anonymous user to permanent user and delete anonymous
      // user.
      // ...
      // Finish sign-in after data is copied.
      return firebase.auth().signInWithCredential(cred);
    }
  }
});

다음 단계

  • FirebaseUI 사용 및 맞춤설정 방법에 대한 자세한 내용은 리드미를 참조하세요.
  • FirebaseUI에서 발견한 문제를 신고하려면 GitHub Issue Tracker를 사용하세요.