brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Aug 10. 2016

Firebase #06-1

Authentication

Firebase Authentication


Most apps need to know the identity of a user. Knowing a user's identity allows an app to securely save user data in the cloud and provide the same personalized experience across all of the user's devices.

(대부분의 앱은 사용자의 신원을 알 필요가 있습니다. 사용자의 신원을 알고 있는 것은 클라우드에 사용자 데이터를 안전하게 저장하고 모든 기기에서 동일한 개인화된 경험을 제공할 수 있습니다.)


Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app.

(Firebase Authentication는 앱 사용자를 인증하는 백엔드 서비스, 사용하기 쉬운 SDK들, 이미 만들어진 UI 라이브러리를 제공합니다.)


It supports authentication using passwords, popular federated identity providers like Google, Facebook and Twitter, and more.

(비밀번호를 이용하거나, 구글, 페이스북 그리고 트위터 같은 인기 있는 통합 로그인을 지원해주는 연합을 통해 인증을 지원합니다.)


Firebase Authentication integrates tightly with other Firebase services, and it leverages industry standards like OAuth 2.0 and OpenID Connect, so it can be easily integrated with your custom backend.

(Firebase Authentication는 다른 Firebase 서비스들과 긴밀하게 통합하고, OAuth 2.0 및 OpenID  연결과 같은 업계 표준을 활용하여, 사용자 제작 백엔드와 쉽게 통합할 수 있도록 합니다.)


https://firebase.google.com/docs/auth/

https://www.youtube.com/watch?list=PLl-K7zZEsYLmOF_07IayrTntevxtbUxDL&time_continue=5&v=8sGY55yxicA




Key functions


완벽한 drop-in 인증 솔루션인 FirebaseUI를 이용하거나 Firebase Authentication SDK를 이용하여 수동으로 하나 또는 여러 개의 로그인 함수를 결합하여 Firebase app에 사용자가 로그인할 수 있습니다.


FirebaseUI (beta)
손쉽게 완벽한 로그인 시스템을 앱에 추가할 수 있습니다. Firebase UI는 사용자의 이메일 주소와 비밀번호, 구글 로그인, 그리고 페이스북 로그인을 이용하는 로그인 UI 흐름을 다룰 수 있는 drop-in 인증 솔루션을 제공합니다.
FirebaseUI 인증 구성요소는 로그인을 극대화하고 가입을 할 수 있는 모바일 기기나 웹사이트에서 모범 사례를 구현합니다. 또한 보안에 민감하고 오류가 발생하기 쉬운 계정 복구와 계정 연결 같은 edge 케이스도 처리합니다.
FirebaseUI는 앱의 시각적 스타일의 남은 부분에 맞게 손쉽게 사용자 정의할 수 있어, 당신이 원하는 UX 실현에 제한되지 않습니다.

Email and password based authentication
이메일 주소와 비밀번호로 사용자를 인증합니다. Firebase Authentication SDK는 이메일 주소와 비밀번호를 이용해 로그인하는 사용자를 관리하고 생성하는 함수를 제공합니다.  또한 Firebase 인증은 비밀번호 재설정 이메일을 보내는 작업도 처리합니다.

Federated identity provider integration
통합 로그인을 지원해주는 연합과 통합하여 사용자를 인증합니다. Firebase Authentication SDK는 구글, 페이스북, 트위터 그리고 깃허브 계정을 통한 로그인을 지원합니다.

Custom auth system integration
앱의 기존 로그인 시스템을 Firebase Authentication SDK와 연결하고 Firebase Realtime Database와 다른 Firebase 서비스들과 연동할 수 있습니다.

Anonymous auth
임시 익명 계정을 생성하여 처음 사용자의 로그인을 요구하지 않고 Firebase 기능을 이용할 수 있습니다. 사용자가 나중에 가입을 하면, 익명 계정을 정식 계정으로 업그레이드하여, 사용자는 계속해서 유지할 수 있습니다. 


Implementation paths - Using FirebaseUI Auth (beta)


1. Set up sign-in methods

이메일 주소와 비밀번호 로그인 및 지원하려는 통합 로그인을 지원해주는 연합의 경우, Firebase 콘솔을 활성화하고,  OAuth를 리디렉션 URL을 설정하는 등, 아이디 공급자에 필요한 구성을 완료합니다.

2. Customize the sign-in UI

FirebaseUI 옵션을 설정하거나, GitHub의 코드를 fork 해 로그인 UI를 커스터마이즈 할 수 있습니다.

3. Use FirebaseUI to perform the sign-in flow

FirebaseUI 라이브러리를 import 하여, 지원하고자 하는 로그인 방법을 지정하고 FirebaseUI 로그인 흐름을 시작할 수 있습니다.


Implementation paths - Using the Firebase Authentication SDK Usㄴㄴㄴing the Firebase Authentication SDK

1. Set up sign-in methods

이메일 주소와 비밀번호 로그인 및 지원하려는 통합 로그인을 지원해주는 연합의 경우, Firebase 콘솔을 활성화하고,  OAuth를 리디렉션 URL을 설정하는 등, 아이디 공급자에 필요한 구성을 완료합니다.

2. Implement UI flows for your sign-in methods

이메일 주소와 비밀번호 로그인에서, 사용자가 자신의 이메일 주소와 비밀번호를 입력하라는 메시지 흐름을 구현합니다. 통합 가입에서, 각 제공자에 의해 요구되는 흐름을 구현합니다.

3. Pass the user's credentials to the Firebase Authentication SDK

사용자의 이메일을 주소와 비밀번호 또는 통합 로그인을 지원해주는 연합으로부터 OAuth 토큰을 Firebase Authentication SDK에 전달합니다.





User in Firebase Projects


Firebase User 객체는 Firebase 프로젝트 앱에 가입한 계정을 표현한다. 앱들은 보통 수많은 등록된 사용자를 보유하고, Firebase 프로젝트의 모든 앱은 사용자 데이터베이스를 공유합니다.

Firebase User 인스턴스는 Firebase Auth 인스턴스로부터 독립적입니다. 이는 같은 context로 서로 다른 수많은 참조들을 가질 수 있고, 여전히 그들의 함수중 하나를 호출할 수 있다는 것을 의미합니다.


User properties


Firebase User는 사용자(iOS, Android, web)에 의해 수정이 가능한 프로젝트의 사용자 데이터베이스에 저장된 고정된 기본 속성 - 고유 ID, 기본 이메일 주소, 이름, 사진 URL - 세트를 가지고 있습니다.

Firebase User 객체에 다른 속성들을 바로 추가할 수 없습니다; 대신, 부가적인 속성들을 Firebase Realtime Database에 저장할 수 있습니다.

처음 사용자가 앱에 가입하면, 사용자의 프로필 데이터는 유효한 정보를 이용하여 채워집니다.

사용자가 이메일 주소와 비밀번호로 가입하면, 오직 기본 이메일 주소 속성이 채워집니다.

사용자가 통합 로그인을 지원해주는 구글 또는 페이스북 같은 연합으로 가입하면, Firebase User의 프로필은 채우는데 이들을 이용합니다.

사용자 정의 인증 시스템을 통해 가입하면, Firebase User의 프로필에 원하는 정보를 명시적으로 추가해야 합니다.

사용자 계정이 한번 생성되면, 사용자가 다른 장치에서 만들 수 있는 변경 사항을 적용하기 위해 사용자의 정보를 다시 로드할 수 있습니다.


Sign-in providers


다양한 방법들을 이용해 사용자들은 Firebase 앱들에 로그인할 수 있습니다: 이메일 주소와 비밀번호, 통합 로그인을 지원하는 연합, 그리고 사용자 정의 인증 시스템. 하나 이상의 로그인 방법과 사용자를 연결할 수 있습니다: 예를 들어, 사용자는 이메일 주소와 비밀번호, 또는 Google 로그인을 이용하여 동일한 계정에 로그인할 수 있습니다.

Firebase User 인스턴스는 사용자와 관련된 모든 공급자의 track을 가지고 있습니다. 이것은 당신이 공급자에 의해 주어진 정보를 이용하여 빈 프로필 속성을 업데이트할 수 있습니다.


The current user


사용자가 가입하거나 로그인하면, Auth 인스턴스의 현재 사용자가 된다. Firebase Auth 인스턴스는 사용자의 상태를 유지하여, 페이지를 갱신(in a browser)하거나 앱을 재시작할 때 사용자들의 정보를 잃지 않습니다.


사용자가 로그아웃하면, Auth 인스턴스는 User 객체에 대한 참조와 상태를 더 이상 유지하지 않습니다; 현재 사용자가 아닙니다. 그러나, 사용자 인스턴스는 기능적으로 계속해서 완벽하게 유지합니다; 이에 대한 참조를 유지하면, 사용자의 데이터에 계속 접근하고 업데이트할 수 있습니다.


The user lifecycle


Firebase Auth 인스턴스의 현재 상태를 추적하는 좋은 방법은 리스너(JavaScript에서는 "observers"라 부릅니다.)를 이용하는 것입니다. Auth 리스너는 Auth 객체에 발생하는 모든 것을 언제든지 감지해냅니다.


인증 리스너는 다음과 같은 경우에 통지됩니다 :

Auth 객체는 초기화를 종료하고 사용자는 이전 세션에서 이미 signed 되었거나, ID 공급자의 로그인 흐름에서 redirected 되었을 경우.

사용자가 로그인 (현재 유저가 설정)

사용자가 로그아웃 (현재 유저가 null이 되었을 때)

다음과 같은 환경에서 현재 사용자의 접근 토큰이 새로 고쳐지는 경우가 나타날 수 있습니다.
- 접근 토큰이 만료 : 흔한 경우입니다. refresh 토큰은 새로운 유효한 세트를 가져오는 데 사용됩니다.
- 비밀번호 변경 : Firebase가 새로운 접근을 발행하고 토큰들을 새로 고치고 만료된 오래된 토큰들을 렌
더링하면 보안적인 이유로 인해 자동적으로 모든 기기의 사용자는 로그 아웃됩니다.
- 사용자 재인증 : 일부 작업은 계정 삭제, 주요 이메일 주소 설정, 그리고 비밀번호 변경 같은 사용자의 credential을 발행할 것을 요구합니다. 사용자 로그 아웃과 재로그인 대신, 사용자로부터 새로 credential들을 얻고, User 객체의 재인증 함수를 통해 새로운 credential을 전달합니다.


Auth tokens


Firebase로 인증을 수행할 때, 3가지 종류의 인증 토큰이 발생할 수 있다.

Firebase ID tokens
Firebase 앱에 로그인할 때 Firebase에 의해 생성된다. 이 토큰들은 Firebase 프로젝트에서 안전하게 사용자들을 식별 가능한 JWTs에 의해 서명된다. 이 토큰들은 사용자 기본 프로필 정보, Firebase 프로젝트 사용자 고유 ID string을 포함하고 있습니다. ID 토큰의 무결성을 검증할 수 있기 때문에, 현재 로그인 한 사용자를 식별하는 백엔드 서버로 보낼 수 있습니다.

Identity provider tokens
구글과 페이스북 같은 연합 공급자에 의해 만들어진다. 이 토큰들은 서로 다른 포맷을 가질 수 있지만, 대부분 OAuth 2.0 access 토큰들입니다. Firebase 앱들은 사용자가 성공적으로 이 공급자로 인증했는지 확인하려고 이 토큰들을 이용하여, Firebase 서비스에서 이용 가능한 credential로 변환합니다.

Firebase custom tokens
Firebase 앱에 사용자가 로그인할 수 있도록 하는 사용자 정의 인증 시스템에 의해 생성된다. 사용자 정의 토큰들은 서비스 계정의 개인 키를 이용하여 JWTs로 서명됩니다. Firebase 앱들은 연합 공급자에서 반환된 토큰과 다른 이 토큰들을 이용합니다.




Password Authentication



https://firebase.google.com/docs/auth/android/password-auth

https://firebase.google.com/docs/reference/android/com/google/firebase/auth/EmailAuthCredential

https://firebase.google.com/docs/reference/android/com/google/firebase/auth/EmailAuthProvider


1. google-service.json 추가


#01 구성 파일 복사


2. plugin 추가

#02 Project build.gradle에 추가
buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.gms:google-services:3.0.0'
    }
}
#03 app build.gradle에 추가
apply plugin: 'com.android.application'

...

dependencies {
    ...
    compile 'com.google.firebase:firebase-auth:9.4.0'
}

apply plugin: 'com.google.gms.google-services'


3. Enable Email/Password sign-in in Firebase console


'Firebase Auth - 로그인 방법'에서 '이메일/비밀번호'를 활성화합니다. 

#04 이메일/비밀번호 사용 설정


4. Create FirebaseAuth object


private FirebaseAuth mFirebaseAuth;

// ...

mFirebaseAuth= FirebaseAuth.getInstance();


5. Create AuthStateListener object



private FirebaseAuth.AuthStateListener mAuthStateListener;

// ...

private void initFBAuthState() {
    mAuthStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
            String message;
            if (firebaseUser != null) {
                // User is signed in
            } else {
                // User is signed out
            }
        }
    };
}

@Override
public void onStart() {
    super.onStart();
    mFirebaseAuth.addAuthStateListener(mAuthStateListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthStateListener != null) {
        mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
    }
}


6. Sign up


이메일은 이메일 포맷에 맞춰야 합니다. 만약 포맷에 맞지 않으면 아래와 같은 exception이 발생합니다.

aNs = "ERROR_INVALID_EMAIL"
cause = "com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The email address is badly formatted."
detailMessage = "The email address is badly formatted."

패스워드는 최소 6개의 문자로 이루어져야 합니다.

aNs = "ERROR_WEAK_PASSWORD"
cause = "com.google.firebase.auth.FirebaseAuthWeakPasswordException: The given password is invalid. [  Password should be at least 6 characters ]"
detailMessage = "The given password is invalid. [  Password should be at least 6 characters ]"

이 외에도 이미 등록된 계정 여부를 판단도 해줍니다.

aNs = "ERROR_EMAIL_ALREADY_IN_USE"
cause = "com.google.firebase.auth.FirebaseAuthUserCollisionException: The email address is already in use by another account.
detailMessage = "The email address is already in use by another account."



private void createUserWithEmailAndPassword() {
    String email = "oemilk@naver.com"; // email address format
    String password = "123456"; // at least 6 characters
    mFirebaseAuth.createUserWithEmailAndPassword(email, password)
        .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    String message;
                    if (task.isSuccessful()) {
                        // success
                    } else {
                        // fail
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            // exception
        }
    });
}


위 코드로 사용자를 생성하면 아래와 같이 'Auth-사용자'에 새로 추가됩니다.

Console창에서 바로 사용자를 추가할 수 있습니다.

비밀번호 재설정, 계정 사용 중지, 계정 삭제를 할 수 있습니다.


#05 생성된 사용자
#06 사용자 추가
#07 사용자 설정


7. Sign in


사용자와 비밀번호가 올바른지 판단해줍니다.

aNs = "ERROR_USER_NOT_FOUND"
cause = "com.google.firebase.auth.FirebaseAuthInvalidUserException: There is no user record corresponding to this identifier. The user may have been deleted."
detailMessage = "There is no user record corresponding to this identifier. The user may have been deleted."
aNs = "ERROR_WRONG_PASSWORD"
cause = "com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The password is invalid or the user does not have a password.
detailMessage = "The password is invalid or the user does not have a password."
private void signInWithEmailAndPassword() {
    String email = "test@test.com";
    String password = "123456";
    mFirebaseAuth.signInWithEmailAndPassword(email, password)
        .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    String message;
                    if (task.isSuccessful()) {
                        // success
                    } else {
                        // fail
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            // exception
        }
    });
}


5. Sign out

private void signOut() {
    if (mFirebaseAuth != null) {
        mFirebaseAuth.signOut();
    }
}




Sample


https://github.com/oemilk/firebase




작가의 이전글 Firebase #05
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari