針對查詢「oauth」依關聯性排序顯示文章。依日期排序 顯示所有文章
針對查詢「oauth」依關聯性排序顯示文章。依日期排序 顯示所有文章

2015年7月24日 星期五

什麼是開放認證OAuth ? (一)



很多的網站提供OAuth 的認證服務, 包含Facebook,Google, Yahoo 等. 那到底什麼是OAuth 認證?


OAuth( Open Authorization)是一個開放標準,允許使用者讓第三方應用存取該使用者在某一網站上儲存的私密的資源(如相片,影片,聯絡人清單),而無需將使用者名稱和密碼提供給第三方應用。
  1. OAuth允許使用者只提供一個 Access Token,而不是使用者名稱和密碼來存取他們存放在特定服務提供者(Service Provider)的資料, 如Goolge Picasa 網路相簿 。
  2.  用戶端應用程式(Client Application)利用取得的Access Token (有token 表示已獲得使用者授權), 存取某一個使用者私有且受保護資源。
  3. 用戶端應用程式只要利用 HTTP 協定即可使用 OAuth 服務
  4. Token 會在應用程式每次向服務要求資源時,由用戶端應用程式提交以驗證權限,即每一次送出的在HTTP Request Header Authorization 標頭資料中都必須帶有Access Token。
  5. When using OAuth 2, all requests must be made over HTTPS.
  6. Access Token 是有時效性, 過期後要再重新取得Access Token。
  7. Access Token 除了時效性外,也可以定義Scope , 也就是存取範圍或權限。

Google  APIs 使用OAuth 2.0 協定來作為認證與使用者識別, 針對Web Server (PHP, Java, Python,Ruby, ASP.NET), Android APP程式或Web 劉覽器網路程式 (如Javscrip應用程式)。用戶端應用程式要獲得Client Credentials (用戶程式識別), 然後向
Authorization Server 請求以獲得token, 然後用你用的每一個google API 都要帶有這個token 

使用Google's OAuth 2.0 Authorization 程序:

  1. 先去Google Developers Console 註冊你的程式專案, 獲得用戶程式識別, 即取得2個重要資訊, Client id,Client Secret 該Google 知道你這隻程式。還有其他值,如redirect_URI , 這些會依據申請不同種類的Client 會有所差異。

    去Google Developers Console 建立新的用戶端ID 

  2. 在你的應用程式裡,將使用者Redirect 到Google 登入頁面 (Redirect 含client_id, redirect_uri等資訊)
  3. 你的應用程式獲得使用者認證後, Goolge Authorization Server傳回authorization code
    按下 "接受後"就代表使用者充許你的存取

  4. 你的應用程式再用authorization code向Google Authorization Server 去換取一個Access Token, 此請求也會包含scope 欄位, 因為不同的scope 將決定了所得到的Access Token的使用權限與範圍。(scope用來區分,這個Access Token 可以存取 Google+,Google Docs,Google Fusion Table, Google Map等 )
  5. Google Authorization Server 回傳Access Token 及Refresh Token以及Access Token Lifetime
  6. 之後每次存取Google的資料, Google API都要代入Access Token (放在HTTP Header中)
  7. Access Token過期後,用Refresh Token 重新取得新的Access Token
Your application sends a token request to the Google Authorization Server, receives an authorization code, exchanges the code for a token, and uses the token to call a Google API endpoint.


以上流程你可以試著使用 Google OAuth 2.0 Playground 了解整個流程.


Google OAuth 2.0 Playground



文件參考

  1. https://developers.google.com/identity/protocols/OAuth2InstalledApp
  2. 使用 Google fusion tables 




2015年10月18日 星期日

使用 Google fusion tables

存取google 的服務,都會用到OAuth 的認證機制,所以使用 Google fusion tables當然也不例外,底下說明的使用的是OAuth 2.0 for Devices過程,一旦取得Access Token,就可以對Google fusion tables 執行新增資料、查詢資料、刪除資料等操作。


OAuth 2.0 for Devices的認證流程
The user logs in on a separate device that has a browser.

使用 OAuth 2.0 , 必須先到Google Developers Console 建立一個專案以取得client ID及client secret. 註: 須於建立用戶端ID頁面, [已安裝的應用程式類型]請選擇"其他"

注意:curl 必須支援HTTPS (安裝說明)

取得Authorization Code


root@raspberrypi:~# curl -d "client_id=530304002742-55mhfghci5o59tur1tgt183p38ceh08t.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/fusiontables" https://accounts.google.com/o/oauth2/device/code
{
  "device_code" : "ZMUM-BZYM4/b1grhomQLBtifJxKrATFJ-m8AoYV7tr3RfN1BLvOTlo",
  "user_code" : "ZMUM-BZYM",
  "verification_url" : "https://www.google.com/device",
  "expires_in" : 1800,
  "interval" : 5
  
} 
  
The user_code and verification_url from the JSON object should be shown to your user. The idea is to ask the user to go to a browser, navigate to the verification_url URL, and enter the user_code. The user_code is case sensitive, so the user will need to enter the code exactly as it appears in the response.



  
=======================================

獲得access tokens

code為上一個請求所傳回的device code

root@raspberrypi:~# curl -d "client_id=530304002742-55mhfghci5o59tur1tgt183p38ceh08t.apps.googleusercontent.com&client_secret=xtogS1gi_MSl_7apvzfrsvmK&code=ZMUM-BZYM4/b1grhomQLBtifJxKrATFJ-m8AoYV7tr3RfN1BLvOTlo&grant_type=http://oauth.net/grant_type/device/1.0" https://www.googleapis.com/oauth2/v3/token




{
 "access_token": "ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "1/97_rdY40n2PusItQPVPENp5ECTZYqFvUobJZB09nOxlIgOrJDtdun6zK6XiATCKT"
}

==================================

#Access Token 過期時, 出現 401 "Invalid Credentials" 錯誤

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL" -d "sql=SELECT * FROM 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE number=43" "https://www.googleapis.com/fusiontables/v2/query" { "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } } =======================================

# Refresh Token

root@raspberrypi:~# curl -d "client_id=530304002742-55mhfghci5o59tur1tgt183p38ceh08t.apps.googleusercontent.com&client_secret=xtogS1gi_MSl_7apvzfrsvmK&refresh_token=1/97_rdY40n2PusItQPVPENp5ECTZYqFvUobJZB09nOxlIgOrJDtdun6zK6XiATCKT&grant_type=refresh_token" https://www.googleapis.com/oauth2/v3/token
{
 "access_token": "ya29.tAHsfamfZ4CUSiMwXG0TztY9DYkcj3Zs988p9Wr_GrZz5vRbxkGHFoQiHxDMNsuEZf8-",
 "token_type": "Bearer",
 "expires_in": 3600
}


一旦取得Access Token並知道過期後如何更新Access Token, 接下接下來就是對Google fusion tables 執行新增資料、查詢資料、刪除資料對表格的操作。使用的方式使用HTTP POST,但必須在每一次的HTTPS請求,在Header中加入Access Token

#新增 "sql=INSERT INTO {table} (number,Address)VALUES(43,'IT robotics lab')"

root@raspberrypi:~# curl  -H "Authorization: Bearer ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL" -d "sql=INSERT INTO 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU (number,Address)VALUES(43,'IT robotics lab')" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "rowid"
 ],
 "rows": [
  [
   "5002"
  ]
 ]
}
==================================

#查詢 "sql=SELECT * FROM {table} WHERE number=43"

root@raspberrypi:~# curl  -H "Authorization: Bearer ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL" -d "sql=SELECT * FROM 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE number=43" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "Date",
  "Time",
  "number",
  "Location",
  "Address"
 ],
 "rows": [
  [
   "",
   "",
   "43",
   "",
   "IT robotics lab"
  ]
 ]
}
==================================

#查詢ROWID SELECT ROWID FROM {table} WHERE number=43

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAHsfamfZ4CUSiMwXG0TztY9DYkcj3Zs988p9Wr_GrZz5vRbxkGHFoQiHxDMNsuEZf8-" -d "sql=SELECT ROWID FROM 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE number=43" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "rowid"
 ],
 "rows": [
  [
   "5002"
  ]
 ]
}
==================================

#更新 sql=Update {table} Set Address='ittraining' WHERE ROWID='5002'

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL" -d "sql=Update 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU Set Address='ittraining' WHERE ROWID='5002'" "https://www.googleapis.com/fusiontables/v2/query"


{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "affected_rows"
 ],
 "rows": [
  [
   "1"
  ]
 ]
}
==================================

#再查詢一次

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAH13KudNYGAmG9rtdXLJjO_QNPjbJcvEkJEeG_C3MxqWh5T9sFbbrguWh77llT6JbVL" -d "sql=SELECT * FROM 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE number=43" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "Date",
  "Time",
  "number",
  "Location",
  "Address"
 ],
 "rows": [
  [
   "",
   "",
   "43",
   "",
   "ittraining"
  ]
 ]
}

#刪除 sql=Delete {table} WHERE ROWID='5002'

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAHsfamfZ4CUSiMwXG0TztY9DYkcj3Zs988p9Wr_GrZz5vRbxkGHFoQiHxDMNsuEZf8-" -d "sql=Delete from 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE ROWID='5002'" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "affected_rows"
 ],
 "rows": [
  [
   "1"
  ]
 ]
}

#確認該筆資料(number=43)已刪除

root@raspberrypi:~# curl -H "Authorization: Bearer ya29.tAHsfamfZ4CUSiMwXG0TztY9DYkcj3Zs988p9Wr_GrZz5vRbxkGHFoQiHxDMNsuEZf8-" -d "sql=SELECT ROWID FROM 1fV5mXuKgG5cCck1cAVQX0G7HVTjfdm1SqeYSdmXU WHERE number=43" "https://www.googleapis.com/fusiontables/v2/query"
{
 "kind": "fusiontables#sqlresponse",
 "columns": [
  "rowid"
 ]
}