如何使用 Firebase - 使用 Google Login(kotlin)

如何使用 Firebase - 使用 Google Login(kotlin)

情境

Google sign-in 是一種廣泛使用的 OAuth 認證,只需要透過 SDK 串接就可以輕易做好簡單認證,在 Android 可以透過 Firebase 更輕易完成 Google Sign-In 處理。

完整程式碼

如果你需要完整程式碼,可以到 GitHub 上觀看或下載。

說明

首先,透過以下流程操作。

  • Android Studio 的 Tool -> Firebase -> Authentication -> Connect your app to Firebase & Add Firebase Authentication to your app

連結好了你的 app project 就會出現一個檔案叫做 google-service.json。

你也可以在 Firebase Console 看到相關資訊。

對以上流程想要知道更細節的描述,可以參考如何使用 Firebase - 用 Android Studio 建立帳戶篇 或者 官方教學

連結好了以後,我們一開始就可以在 XML 上建立一個 Google Sign-In Button。

<com.google.android.gms.common.SignInButton
	android:id="@+id/sign_in_button"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content" />

這個神奇按鈕就幫我們包好了所有認證功能,只要你按下去,就會看到這樣的畫面。


讓使用者自己選擇要登入的帳號,只要這次登入以後,之後登入就不會再確認了。

接著我們來看一下怎麼使用這個按鈕,首先,先對這個按鈕設定事件。

sign_in_button.setOnClickListener {  
  signIn()  
}

接著我們來看 signIn 這個方法內寫些什麼?
這邊我們可以要求多個東西,例如名字、email 或者 token,這邊我們故意設定兩個點,一個是 IdToken,另外一個是 Email,IdToken 相當於你的權限,如果你有自己的後台的話,就可以透過這個 IdToken 去跟 Google 要使用者的相關資料,因此,會牽扯到一些資安的問題,但是在我們這個範例內,只是單純示範拿一下 Token。

private fun signIn() {
	val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
		.requestIdToken("google-service.json 內的 client_id")
		.requestEmail()
		.build()
	//...
}

一開始透過 Builder 建立了一個 Option 的物件,透過這個物件就可以宣告以下的變數。

private fun signIn() {  
	//...
	val mGoogleSignInClient = GoogleSignIn.getClient(this, gso)  
	val signInIntent = mGoogleSignInClient.signInIntent  
	startActivityForResult(signInIntent, RC_SIGN_IN)  
}

是否有注意到?這邊有用到 startActivityForResult,這就代表著我們等下會透過 onActivityResult 來接東西,這邊就很單純的成功或失敗的判斷。

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {  
    super.onActivityResult(requestCode, resultCode, data)  
    if (requestCode == RC_SIGN_IN) {  
        val task = GoogleSignIn.getSignedInAccountFromIntent(data)  
        try {  
            val account = task.getResult(ApiException::class.java)  
            val email  = account?.email  
  val token = account?.idToken  
  Log.i("givemepass", "email:$email, token:$token")  
            Toast.makeText(this, getString(R.string.login_success), Toast.LENGTH_SHORT).show()  
        } catch (e: ApiException) {  
            Log.i("givemepass", "signInResult:failed code=" + e.statusCode)  
            Toast.makeText(this, getString(R.string.login_fail), Toast.LENGTH_SHORT).show()  
        }  
    } else{  
        Log.i("givemepass", "login fail")  
        Toast.makeText(this, getString(R.string.login_fail), Toast.LENGTH_SHORT).show()  
    }  
}

這樣就大致上完成了登入的作業。
效果如下圖。


回到前面的 IdToken 能夠做什麼呢?
透過下面網址,再把 Id-Token 塞進去,就可以拿到個人資料。

https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=拿到的token

把透過 Google Sign-In 拿到的 id_token 塞到上面網址列的 id_token 值,你就會發現可以拿到一堆相關資訊。

{
	"iss": "https://accounts.google.com",
	"azp": "878489384959-igk261ic4ut8u8fu8eu8f34dsjdjdjiw.apps.googleusercontent.com",
	"aud": "878489384959-dgjcuehguhug434fji4jfijw4ifji494.apps.googleusercontent.com",
	"sub": "859384953495934995943",
	"email": "givemepassxd999@gmail.com",
	"email_verified": "true",
	"name": "givemepass",
	"picture": "https://lh3.googleusercontent.com/a-/AAuE7mAS2z4RwoNTQlhtfjwet6ISdQ=s96-c",
	"given_name": "givemepass",
	"family_name": "givemepass",
	"locale": "zh-TW",
	"iat": "4990439504",
	"exp": "49949690904",
	"alg": "RS256",
	"kid": "47456b8069e4365e517ca5e29434a9efa567ba",
	"typ": "JWT"
}

是不是感到很危險呢?所以我們要很小心地保護好 Token,
這樣就是一個簡單的 Google Sign-In 的範例了。