Quantcast
Viewing all articles
Browse latest Browse all 577

Google 帳號資訊如何辨別真偽﹍後端驗證用戶資料與 token 的技巧

Image may be NSFW.
Clik here to view.
過去曾使用「Google 試算表」來打造及存放會員系統,而會員註冊的部分可利用「FB API 製作登入按鈕」取得帳號資訊。但 FB API 限制較多也不好操作,後來使用「Google API 製作登入按鈕」取得基本資訊,並搭配「People API」取得更多個人資訊。 有第三方 API 處理會員註冊問題真的方便又安心,不用經手棘手的帳號密碼問題,可參考「FB API 製作登入按鈕」的詳細說明。不過久了可能會面臨一種狀況:「被大量惡意註冊怎麼辦?」當提供的服務如果出名、爆紅了,就會有各種原因出現大量註冊,例如用來鑽漏洞、或是被公關公司盯上成為目標。 前端經第三方 API 取得的使用者資訊不會有什麼問題,但傳送到後端的資料就無法保證了,一方面所有中繼傳輸設備都可能被攔截,一方面有心人說不定已寫好了執行腳本,跳過前端直接發送大量的假帳號註冊請求給後端,一次註冊了幾百個帳號也說不定。 依照這樣的攻擊手法,我們有可能在後端辨識出,這幾百個註冊的 Google 帳號是真是假嗎? (圖片出處: pixabay.com)

一、Google API 使用者資訊

首先複習一下「Google API 登入按鈕」,Google 登入後可以取得這些公開資訊:ID暱稱頭像Email。接著儲存到資料庫後,要拿 ID 或 Email 做為單一不重複的帳號依據都可。 然而前端傳送到後端的註冊請求,資訊想造假並不困難,"暱稱"、"頭像"、"Email"就不用說了,如果 "ID"資訊是假的,後端有辦法判斷嗎?畢竟 ID 是第三方 API 產生的,我們不會知道運算邏輯,所以哪知道這字串是真是假~ 好消息是,實際上別說 "ID",我們連 "暱稱"、"頭像"、"Email"全部的資訊都有辦法辨別真偽!趕快來看看是怎麼回事。

二、後端進行身份驗證

根據 Google 官網文件「使用後端服務器進行身份驗證」,官方明確告知我們要如何對使用者進行身份驗證:
如果您將Google登錄用於與後端服務器通信的應用或網站,則可能需要識別服務器上當前登錄的用戶。為了安全地執行此操作,請在用戶成功登錄後,使用HTTPS將用戶的ID令牌發送到您的服務器。然後,在服務器上,驗證ID令牌的完整性,並使用令牌中包含的用戶信息建立會話或創建新帳戶
意思就是說,使用者在前端登入 Google 帳號後取得的資訊,其中包含了 "ID令牌",也就是 ID token,必須傳到後端伺服器進行驗證。驗證無誤後,再將 ID token 中包含的使用者資訊(這才是不會被竄改的資訊)進行註冊之用。 根據官網說明,驗證 ID token 的網址如下: https://oauth2.googleapis.com/tokeninfo?id_token=這裡是 ID token 字串如果 id_token 驗證無誤,就會傳回使用者資訊,此時可以跟前端接收到的使用者資訊一一比對,就能驗證 Google 帳號的註冊資料真假了。官網也提供該網址回傳的資料範例,大概長這樣: { "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en"}主要看看 name、email、picture(頭像網址) 這幾項是否吻合就可以了。

三、取得 id token 範例程式碼

修改一下「Google API 登入按鈕」的範例程式碼,就可取得 id_token、access_token 等資訊: <script src="https://apis.google.com/js/platform.js" async="async"></script> <meta name="google-signin-client_id" content="5432xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com"/> <div class="g-signin2" data-onsuccess="onSignIn"></div> 目前狀態: <span id="GOOGLE_STATUS_1"></span> <script> // 登入之後 function onSignIn(googleUser) { var profile = googleUser.getBasicProfile(), target = document.getElementById("GOOGLE_STATUS_1"), html = ""; html += "ID: " + profile.getId() + "<br/>"; html += "會員暱稱: " + profile.getName() + "<br/>"; html += "會員頭像:" + profile.getImageUrl() + "<br/>"; html += "會員 email:" + profile.getEmail() + "<br/>"; html += "id token:" + googleUser.getAuthResponse().id_token + "<br/>"; html += "access token:" + googleUser.getAuthResponse(true).access_token + "<br/>"; target.innerHTML = html; } </script>
  • 紅色字串改為自己的「用戶端 ID」,請參考前一篇所有流程注意事項

四、驗證 id token

下面是以上範例程式碼「官方 Google 登入按鈕」的效果,執行登入可取得各項資料:
目前狀態: 如前面「二、後端進行身份驗證」的說明,以下紅字改為自己的 id token 字串即可取得驗證結果: https://oauth2.googleapis.com/tokeninfo?id_token=這裡是 ID token 字串

五、驗證 access token

前面的範例程式碼附帶提供了 access token 資訊,取得的方式請參考討論串「How to properly get Access Token from logged in Google Sign In」。 這裡額外說明如何驗證 access token 真偽。此討論串「How can I verify a Google authentication API access token?」提到 Google 兩個版本的驗證網址: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=這裡是 access token 字串https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=這裡是 access token 字串任選一個將紅字改為自己的 access token 字串即可取得驗證結果。
更多「資訊安全」相關文章:

Viewing all articles
Browse latest Browse all 577

Trending Articles