實做Google、Facebook、Line OAuth登入
OAuth基本流程
- 前端前往第三方登入、授權頁
- 登入成功後取得AccessToken或是Code
- 將AccessToken或是Code發API交給後端
- 後端拿AccessToken或是Code跟Auth Server(Google/FB/Line)確認是否可用,並且取得基本資料(一般為Email)
- 依照專案需求自行決定這些基本資料如何使用
共同規範
- client_id:前端發起OAuth登入時在URL要帶入的憑證
- response_type:OAuth登入成功後要回應的類型,可使用token或code(Line登入只能使用code flow)
- redirect_uri:前端登入成功後導向頁面,一般都需要在第三方的服務後台做設定
- scope:權限請求
- state:額外要多傳的資料,可以拿來做一些驗證資料傳遞,避免前端被不明來源執行OAuth登入
Google OAuth設定
前往Goolge API Console的憑證設定頁面
建立一個新的憑證
類型選擇OAuth用戶端ID
並且設定授權的JavaScript來源(就是網站的網域)
接著設定已授權的重新導向URI(就是redirectUri)
其餘設定例如同意畫面的條款、隱私權、審核等資料請自行依照專案設定
Facebook OAuth設定
開啟Facebook developer帳號
前往應用程式頁面
建立一個登入類型的應用程式
接著在設定>基本資料頁設定應用程式網域
然後到商品設定頁面設定有效的OAuth重新導向URI(redirectUri)
其餘設定例如同意畫面的條款、隱私權、審核等資料請自行依照專案設定
Line OAuth設定
開啟Providers頁面建立一個Provider
接著開啟建立好的Provider建立一個新的Channel
並選擇LINE Login類型
大部分設定都依照專案設定即可
主要要設定App types為Web App即可
建立完成後要另外請求取得Email權限
如果你的網站OAuth登入是打算透過Email來當帳號依據的話
這點一定要做
最後開啟LINE Login tab
設定Callback URL(redirectUri)
其餘設定例如同意畫面的條款、隱私權、審核等資料請自行依照專案設定
各家差異整理
服務設定的限制
例如Google會限制網域
Facebook也會限制網域但不限制開發機(localhost)
Line則是完全不擋
名詞差異
redirectUri
- Google:已授權的重新導向URI
- Facebook:有效的OAuth重新導向URI
- Line:Callback URL
流程簡介(Google/Facebook)
流程簡介(Line)
關於State設定
前面有提到
從前端到授權頁然後再透過redirectUri回到網站上的OAuth處理中繼頁面
可以透過state傳參數在這個中繼頁取得state的資料
通常是以object格式做JSON.stringify即可(至少Google/Facebook是這樣做沒問題)
但是在Line的OAuth登入上
直接用JSON.stringify導向Line授權頁面
Line會直接回Bad Request錯誤
後來只好把JSON.stringify的前後{跟}字元拿掉
在redirectUri的中繼頁如果偵測是Line登入再接回{跟}這兩個字元
然後才能做JSON.parse取得state物件資料
簡單來說Line就是看URL的{跟}這個字元不爽
就是想辦法把這兩個符號去掉不要帶在URL就是了
用什麼格式都可以
導向授權頁面的query(Page Mode)
以下為導向各家授權頁面的Base URL
Google:https://accounts.google.com/o/oauth2/v2/auth
Facebook:https://www.facebook.com/v7.0/dialog/oauth
Line:https://access.line.me/oauth2/v2.1/authorize
接著是各家的URL query
以下先用JSON格式紀錄
最後再轉成QueryString帶在Base URL後即可
以下示範使用一個叫qs的js套件
很簡單就能將object轉成QueryString
const baseUrl = 'https://accounts.google.com/o/oauth2/v2/auth'
let query = {
client_id: clientKey,
response_type: 'token',
scope: 'openid email https://www.googleapis.com/auth/userinfo.profile',
state: JSON.stringify({ foo: 'bar' }),
redirect_uri: this.redirectUri,
}
const queryString = qs.stringify(query, { encode: false })
return `${baseUrl}?${queryString}`
const baseUrl = 'https://www.facebook.com/v7.0/dialog/oauth'
let query = {
client_id: clientKey,
response_type: 'token',
scope: 'public_profile email',
state: JSON.stringify({ foo: 'bar' }),
redirect_uri: this.redirectUri,
}
const queryString = qs.stringify(query, { encode: false })
return `${baseUrl}?${queryString}`
Line
const baseUrl = 'https://access.line.me/oauth2/v2.1/authorize'
// line登入頁如果url帶 { } 符號會400, 所以要先去掉頭尾的 { }
let stateString = JSON.stringify({ foo: 'bar' })
stateString = stateString.slice(0, -1)
stateString = stateString.substring(1)
let query = {
client_id: clientKey,
response_type: 'code', // line的oauth response type只接受code flow
scope: 'profile openid email',
state: stateString,
redirect_uri: this.redirectUri,
}
const queryString = qs.stringify(query, {
encode: false,
})
return `${baseUrl}?${queryString}`
總結
本篇介紹這三家的Oauth主流程就是那樣
其餘就是看各個專案取得AccessToken或是使用者資料之後怎麼使用
通篇看下來
就是Line最麻煩要跟別人不一樣
但有些專案如果要使用Line登入就沒辦法了
畢竟Line在台灣的市占率使用率真的是滿高的
Icon Credit
User: Icons made by Freepik from www.flaticon.com
Verify: Icons made by Pixel perfect from www.flaticon.com
Server: Icons made by Adib Sulthon from www.flaticon.com
Google: Icons made by Freepik from www.flaticon.com
Facebook: Icons made by Pixel perfect from www.flaticon.com
Line: Icons made by Freepik from www.flaticon.com
Profile: Icons made by Pixelmeetup from www.flaticon.com