從Google第三方登入看OAuth2.0
剛開始直接硬嗑Google 官方文件,根本搞不清楚是怎運作授權這件事,直接在文件裡面大迷路,於是覺得還是要了解原理,才會搞得懂授權是怎麼運作的,讀了幾篇文章後跟實際操作後才整個恍然大悟整個過程,那就開始吧。
OAuth2.0
用文謅謅的說法就是
👤使用者授權給💻某程式/服務去跟🔑 另一網站/服務 換取授權去資源中心🏢拿回使用者同意給你的資料💾
白話文的實例
小明是老闆👤,要請他的員工A💻去服務中心🔑索取資料,所以小明👤寫了一份授權書給員工A💻,員工A💻去了服務中心🔑跟櫃台出示授權書,換得一張代理權證明,並前往存放資料中心🏢的所在地,向資料料中心🏢的櫃台出示代理權的證明,換得一份密碼,最後前往資料所在地,用密碼解開鎖拿回資料💾交差。
那麼來看看老方法怎麼用,並用白話的方式
小明是老闆👤,要請他的員工A💻去資料中心🏢索取資料,所以小明👤直接給了員工A💻帳號密碼,員工A💻單刀直入前往存放資料中心🏢的所在地,用密碼解開鎖拿回資料💾交差,途中忽然心生歹念,把小明的另 一個放貴重物品的箱子也抄了,想想小明平時很機八,想搞他一下,於是利用拿到的資料,假冒身分亂搞他,超爽der~
是不是很可怕(x,這種方式等同你要非常相信要幫你取資料的人,於是乎才有現在OAuth2.0 的方式,該授權單位本身的防衛機制良好,加上換取授權換取資料的方式,再加上只限定給你使用者願意給你的資料,這使得個人敏感資料的防護更加的有保障。
接下來提及整個流程的重要的角色吧
角色介紹
👤資料所有者Resource Owner
就是使用者本人,當client向你要求使用某些資料(ex:email、姓名去建立帳戶,必須要先經過本人同意。
💻 Client
意即使用者使用的APP、網站等等,以Leetcode為例,可以用github來授權登入,Leetcode就是client。
client端必須事先向授權中心註冊拿到client_ID、client_Secret,並指定你要索取的資料,透過scope來標示,並指定redirect_url(很重要很重要很重要!!),使用者同意後會把授權轉到redirect_url來
🔑授權中心Authorization Server
顧名思義掌管授權的單位,給使用者本人進行確認動作,確認完成後發放Grant(授權狀)給client端,會回到你指定的redirect_url(很重要很重要很重要!!再說一次),client拿到Grant(授權狀)才能去要token
🏢資料中心Resource Server
管理資料的單位就好比web server API,當client透過授權中心拿到token,就能夠向資料中心索取資料。
OAuth2.0 共分4種授權類型流程
- Authorization Code Grant Flow
- Implicit Grant Flow
- Resource Owner Password Credentials Grant Flow
- Client Credentials Grant Flow
以下會實際串接google來看看第一種Authorization Code Grant Flow長怎樣,所以僅介紹Authorization Code Grant Flow
Authorization Code Grant Flow流程
廢話不多說先上流程圖
A)💻 client會預先設置授權連結並用query的方式夾帶在url中。
B) 👤使用者點擊授權連結後,轉到🔑授權中心並詢問你要不要授權這 些資料給💻client,按下同意後。
C) 🔑授權中心就會回傳Grant(授權狀)(是以query的形式夾帶),送到💻client指定的 redirect_url。
D)💻client收到後會以用Grant(授權狀),去🔑授權中心索取token
E)🔑授權中心確認無虞後就會發放token給client使用
後續💻client就可以token去向🏢資料中心索取資料啦
詳細的細節,就交給實際串一次再來講,GOGOOGO
實作
- 先去https://console.cloud.google.com/apis/credentials,新增OAuth2.0的憑證跟設定redirect_url
- 建立簡易前端頁面
3. 建立使用者點擊下去,轉到🔑授權中心的url
A)💻 client會預先設置授權連結並用query的方式夾帶在url中。
B) 👤使用者點擊授權連結後,轉到🔑授權中心並詢問你要不要授權這 些資料給💻client,按下同意後。
query夾帶需要的選項
- redirect_uri ,送出去請求後🔑Google會去確認你設定的redirect_uri有沒有相同,不相同就會失敗
- client_id,🔑Google會去確認你的client_id是否存在
- response_type,一定要標"code"才會知道要走"Authorization Code Grant Flow",不然🔑Google沒辦法分辨到底要走哪一個流程
- scope,client端開出想要的資料,🔑Google會去確認你的格式、內容是否正確
4. 將Grant(授權狀)回傳到先前設定的redirect_uri
C) 🔑授權中心就會回傳Grant(授權狀)(是以query的形式夾帶),送到💻client指定的 redirect_url。
(這邊要注意的是,這個由🔑Google回傳的url透過query給你grant,瀏覽器是看得到這個response的,query是明碼相對來說是不安全的,是能被人利用的,所以才會有下一步,後端收到後,由後端去請求token,而這段過程是瀏覽器是看不到的。)
那我們來看看回傳的東西長什麼樣
/auth/google/callback?code=4/0AXWgctXynOPlUNJUOsg&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=consent
有點亂?沒關係可以看到回傳的/auth/google/callback ,是預先設定的redirect_uri。
query 部分看下面,另外用object呈現
{ code:
'4/0AXWgctXynOPlUNJUOsg',
scope:
'email profile https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email openid',
authuser: '0',
prompt: 'consent' }
可以看到我們拿到了關鍵的Grant(授權狀)也就是code裡面的內容。
=====以下動作皆在 app.get(auth/google/callback)內執行=======
5. 以這組code去向🔑Google換取token
D)💻client收到後會以用Grant(授權狀),去🔑授權中心索取token
要索取token必須要POST夾帶以下資料才能夠成功換取
- code、clientId、clientSecret、redirectUri、grant_type
🔑Google會去確認clientId、clientSecret、是否正確redirectUri是否與client設定的相同,若無問題就會回傳token
其中grant_type這個用意一樣,是告知🔑Google要用什麼樣的流程索取,"Authorization Code Grant"要設"authorizaion_code"
那回傳的data會以json檔回傳,並包含以下
- access_token,用來索取資料
- refresh_token,當access_token過期時,可以透過POST refresh token 去做更新access_token,其過期時限也會設定的比access_token久
- scope,client要請求的資料選項
- expires_in,access_token的過期時間
- id_token:這部分是google自己的設定,請求資料需要放在header內使用Bearer 夾帶進去
{
access_token:'yUPj01aw4Eh0TWscGAu8CQUW4fr9DKp',
expires_in: 3599,
refresh_token:'1//0egm404TGA4SNwF',
scope:'https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/userinfo.email openid',
token_type: 'Bearer',
id_token:
'eyJhbGciOiJSUzI1NiIsImtp'
}
6.使用token向google的資料中心索取使用者同意給的資料
回傳後的資料為以下
{ id: '10451',
email: 'example@gmail.com',
verified_email: true,
name: 'ZHIH',
given_name: 'ZHIH',
picture:
'https://lh3.googleusercontent.com/a/123tyr4',
locale: 'zh-TW' }
接下來就看要怎麼運用這筆資料啦~~如果是建立帳戶,就把相關資訊存到資料庫裡。
總結
實際跑過一次對於整個運作真的清晰許多,對於以後串接大公司的API (google、facebook)閱讀上難度應該會降低不少,就這樣啦~~~
886