前言
碰巧最近有個日文五十音消除遊戲的 Side Project 正在實作中,參考之前鐵人賽文章,實作上發現有些內容可能是年久失修,導致實作上不太順利,碰巧近期 LINE Login 的官方文件也有更新,並且搭配之前實作的範例是使用 (Screen-LINE-Bullets),來延伸 Side Project,以下就為各位介紹一下其中使用 LINE Login 的一些過程。
TL;DR
- LINE Login 範例從 Flask 轉到 Vue+FastAPI
- 前後端分離
- 前端用兩個頁面清楚展示 LINE Login SSO 步驟
- 後端兩個 API
- 取得認證導向網址
- 認證 JWT 中的使用者參數
- 環境變數都放後端(較安全)
介紹
LINE Login 綁定步驟
- 進入 LINE Developer Console
- 建立 Provider
- 建立 LINE Login channel
- 點選最右面選項把 LINE Login channel 設定為
published
- 啟動
Web App
選項並設定 Callback URL 為http://localhost:8080/line/auth
- LINE Login 開發時不用 SSL+Domain,但上線後記得改成自家 Domain + SSL
- 把 client_id、client_secret、Callback URL 複製到後端 FastAPI 的環境變數中
- 開始以下文章內容
用戶看見的頁面
首先先參考前端的路由(後續實作上可能有差)
1 | { |
將用戶導向 Login 頁面 - 前端路由 /line
- 【前端】用戶透過訪問
/line
按下登入鈕 (Setting.vue)- 取得後端需要導向至 LINE Login 的網址
- 透過 window.location 把用戶轉去 Login 頁面
1 | setup() { |
- 【後端】 FastAPI API 路由位置
- r_uri = os.environ.get(“LINE_LOGIN_URI”)
- client = os.environ.get(“LINE_LOGIN_CLIENT_ID”)
- 取得兩個環境變數並放入 OAuth2 網址中回傳給前端導向
uri = f"https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id={client}&redirect_uri={r_uri}&scope=profile%20openid%20email&state={state}&initial_amr_display=lineqr"
參數 r_uri 以及網址中的 redirect_uri 為 LINE Login 用戶輸入正確登入後會導向的網址,網址就存放在後端 FastAPI 的環境變數中,數值則填上前端頁面的路由,也就是 line/auth
上
網址組成方式請參考文件
LINE 認證用戶後回到 redirect_uri 的頁面中 - 前端路由 /line/auth
當用戶輸入完帳密(QR Code)後 LINE 會重新導向 /line/auth
,導回來的網址會有兩個 Query parameter,範例如下(官方文件說明):
1 | http://localhost:8000/?code=xxx&state=ooo |
參考官方文件,拿到 code 之後要再拿著 redirect_uri
、client_id
、client_secret
去換用戶資訊,但三個參數安全性問題因此需要放後端,因此由後端 call LINE API 來取得用戶的 JWT 資訊,Query parameter 放置的方式參考 FastAPI 文件,Python code 如下:
1 |
|
離奇事蹟:JWT 解不開
我參考 18 年寫的鐵人賽文章中的 LINE Login 範例程式碼,當我到了 token = token.encode()
步驟時一直顯示 algorithms 有問題
1 | TypeError: encode() got multiple values for argument 'algorithm' |
當初寫的文章中要透過這步驟會把 token 換成 binary 的形式 -> b’xxxxx’,再丟到 decode()
去解密,但即便把 encode 移除後把 id_token 丟進去也是出錯。
在百思不得起解的狀態下,決定先不用 JWT 相關的函示庫,參考官方文件最下方的驗證程式來將 ID Token 解碼並進行驗證,如此一來就成功可以解出 JWT 並把使用者的資訊存到 DB 中並回傳給前端頁面使用了。
解開範例:
1 | { |
結論
有些日子沒回來寫 LINE Login 的相關操作步驟,伴隨著 LINE Login 文件有更改後,過往一些自己寫的文章程式碼可能有點年久失修,導致再回來看文章寫程式時出了些錯誤。
過程中除了修程式碼外還有個收穫,就是可以透過 使用 LINE Login API 的 Endpoint 來取得用戶的資訊,只要透過 Client_id + id_token 即可取得,甚至不用透過 JWT 解密就可以拿到上述的用戶資訊,實在是很方便(嘗試過很讚),只是我個人還是比較信任透過 channel_secret 換到的用戶資訊,因此大家在選擇上時可以依照自己的需求去選用喔!