想密碼太麻煩?那用account kit解決你的困擾吧

我覺得取密碼已經是現在網路時代很讓人困擾的事情之一,特別是現在各種不同網站對密碼的要求不一樣(其實我很希望各網站不只是設新密碼的時候會顯示要符合的密碼規則,登入的時候可以也顯示一下嗎QQ)或者是要求使用者要定期換密碼最後常常造成防堵了密碼被盜也防堵了使用者登入自己的帳戶。

為了好記而取簡單的密碼讓人不放心( ex.# ji32k7au4a83 ) ,但是就算我取了強度夠的密碼如果網站的安全性不夠密碼根本沒幫我加密好像也只是增加我輸入密碼的時間,比方說曾經收過某知名英文學習網站直接把密碼明碼寄給我。

那如果乾脆不要用密碼的話呢?

Facebook Account Kit

就像很多網站第一次註冊的時候為了確認身份會要求要email認證或是手機認證一樣,同樣的收法也可以用在登入的時候,你可以找外面提供傳送手機簡訊發送服務的api來自己做(ex. twilio / Amazon SNS / nexmo,或者也可以使用今天要介紹的Account Kit來達到這個目的。

優點:

  1. 支援用email / 手機簡訊
  2. 一個月發送數量沒超過10萬的話不收費(但其實也沒寫超過十萬會怎麼收費)

缺點:

  1. 認證畫面的樣式和說明文能自訂的部分有限,要在他的後台設定。 enter image description here

個人認為沒超過十萬件就不用收費是很大的吸引力。

網頁上也有提供PHP和Node.js的範例

也有提供android / ios用的SDK,不過這邊只說明網頁版的部分。

大略下的流程如下: 1. 使用者在網站內輸入電話號碼 / email 2. 將收到的認證碼輸入到網站裡 3. FB確認認證碼無誤之後會發送授權碼到你的server 4. 在使用授權碼去取得用戶存取權仗 (以下只解釋3,4的步驟) enter image description here

雖然分成SMS和email兩種,但並不需要寫兩種code。

實作

取得存取權杖

前端的部分由於完全照FB給的範例就可以了,這邊直接從已經可以拿到Account Kit的授權碼開始。

寫這篇文的時候Facebook AccountKit Graph API的網址是 https://graph.accountkit.com/v1.3/access_token

圖形API說明連結

使用授權碼交換用戶存取權杖是透過 Account Kit API 呼叫進行。

GET https://graph.accountkit.com/v1.3/access_token?grant_type=authorization_code&code=<authorization_code>&access_token=AA|<facebook_app_id>|<app_secret>

用ruby來執行的話可以像以下這樣

# 應用程式id, 程式密鑰可以從後台查到
  def access_token_info
    uri = URI("https://graph.accountkit.com/api版本/access_token")
    uri.query = URI.encode_www_form(access_token_params(授權碼))
    response = get_response(uri)
  end

  def access_token_params(code)
  #這些是指定要回傳的params
    { grant_type: 'authorization_code',
      code: code,
      access_token: ['AA', 應用程式id, 程式密鑰].join('|') }
  end

如果授權碼有效且尚未過期,Account Kit API 就會回應用戶存取權杖如下。

{  "id"  :  <account_kit_user_id>,  "access_token"  :  <user_access_token>,  "token_refresh_interval_sec"  :  <refresh_interval>  }

順利拿到以上回應的話就可以使用上面的access_token來取得使用者資料。

授權碼只能使用一次,第二次會跳error。

取得使用者資料

這一次需要呼叫以下的endpoint

GET https://graph.accountkit.com/v1.3/me/?access_token=<access_token>

如果你沒有在後台啟用需要應用程式密鑰設定,那邊上面的就只需要access_token: access_token

但如果有啟用需要應用程式密鑰, 則接受帳號存取權杖做為參數的大部分呼叫將會需要額外的 appsecret_proof 參數{ access_token: access_token, appsecret_proof: appsecret_proof },用以驗證這些呼叫是否來自自己的伺服器。

appsecret_proof是存取權杖的 sha256 雜湊值,使用應用程式密鑰當作產生雜湊值的密鑰。

用ruby來加密的話會如下

    OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new,
                            密鑰, 存取權杖)

成功的話就可以得到以下的使用者資料了

{ id:  "1234512345123451", phone:  { number:  "+15551234567" country_prefix:  "1", national_number:  "5551234567"  }, application:  { id:  "5432154321543210"  }  }

上面的id是account kit自己的id和fb id並不一樣,網頁上也說明

Account Kit 帳號編號保證不會與 Facebook 用戶編號相衝突。

而由於每一個使用者都會有自己的固定的id,對於不想儲存使用者個人資訊的網站來說,可以光靠儲存account kit來辨識不同的使用者而不需要一起儲存電話號碼或email。

另外account kit曾經發生被人使用不同應用程式所發行的token成功登入到另一個應用程式(現已解掉),所以為了保險起見,也可以使用上面回傳的應用程式id來比對是否來自於自己的網站。

總結

整體來說使用上很簡單,特別是對於用過GraphAPI來說應該更容易上手,但是當初在我負責的案子上曾經發生過不知為何staging環境上測試都很成功,但是一推到production上認證總是不成功,當初試了各種方法之後最後是server換了ip以後就一切都好了。雖然至今還不知道為什麼會發生這種事,如果有人確定程式沒有問題卻不知為何失敗的話,或許可以參考看看。