筆記:網站整合LINE登入機制
原本只是想弄LINE通知,不過看到要oauth就覺得煩,乾脆直接了解LINE登入機制。這篇會講登入的作法,和需要存取的LINE API,以CURL指令舉例說明。建議可以先了解LINE BOT機制再來整合。
基本概念
讓網站可以接受LINE Login的方式,就是透過自訂的帳號榜定機制,常見的榜定是
1. 登入網站現有的帳號,再榜定LINE
2. 網站沒有帳號直接創建新帳號,將兩者帳號做榜定
因為做第二種表示你的網站是開放註冊新帳號的,就目前的應用因為是不開放帳號註冊,所以如果找不到榜定的LINE帳號資料就要顯示擋板網頁。
LINE登入流程
你的網站 -> 使用者按下LINE登入按鈕 -> LINE登入頁面 -> callback的URL
LINE會給callback網頁授權碼,剩餘交給我們自己處理。
- Q1. 登入失敗呢?
在callback時就會讓你知道它失敗/錯誤了。 - Q2. 使用者名稱呢?
取得LINE登入授權碼之後跟LINE的oauth2伺服器取得更多資料。 - Q3. E-mail呢?
你需要在LINE開發者中心裡面,在LINE登入中啟用E-mail權限,並且上傳一張圖寫明白為何需要E-mail。
事前準備
- 在LINE開發者網站中建立一個LINE Login的設定
- 開設你個人網站,網站需要具備HTTPS的憑證
- 登入頁面,最簡單就是放個LINE登入按鈕連結
- 接受callback的網頁 get
- 儲存帳號和LINE登入對應的資料庫
以我手邊的side-project來說,會用Heroku+MongoDB或Google AppScript+Sheet完成這件事情,這樣都不用申請自己的HTTPS憑證。
LINE登入按鈕
官方有提供標準登入按鈕的圖示可以直接使用,我自己測試的所以只在網頁中寫一個登入連結下:
<a href="https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=${CHANNEL_ID}&redirect_uri=${CALLBACK_URL}&state=${STATE}&scope=profile%20openid&nonce=${NONCE}">LINE login
</a>
- client_id就是你的LINE登入的Channel ID。
- redirect_uri 就是你的callback的URL。
這裡因為是html的URL記得要用percentage encoding
以Herorku的APP舉例,原本的URL若是https://my-line-bot.herokuapp.com/callback,編碼後要改成https%3A%2F%2Fmy-line-bot.herokuapp.com%2Fcallback`。 - state 是你自己決定的內容,因為會被傳送到callback URL中,可以做確認來源或資料確認。
- nonce 是你自己決定的隨機碼,會被放 id_token 中。
你的Callback網頁
網頁要接受query參數
- 固定參數: state 是我們在Login API自己決定的隨機碼。
- 動態參數:
- 成功時:
1. code 即LINE授權碼。
2. friendship_status_changed 是當官方LINE@好友狀態有改變時會傳遞。 - 失敗時:
1. error 錯誤類型。
2. error_description 錯誤描述。
用LINE授權碼取得使用者名稱
從LINE授權碼取得使用者名稱,有兩個步驟:
- 存取token API
- 抓取使用者資訊, 有兩個方法:
- 使用access_token存取user profile API,取用displayName欄位
- 針對id_token的第二部份進行BASE64解碼,取用name欄位
存取token API
取得LINE授權碼的在10分鐘內都可以用來存取token API。
curl -v -X POST 'https://api.line.me/oauth2/v2.1/token' \-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d "redirect_uri=${CALLBACK_URL}" \
-d "code=${LINE_AUTH_CODE}" \
-d "client_id=${CHANNEL_ID}" \
-d "client_secret=${CHANNEL_SECRET}"
- redirect_uri 就是放你登錄在LINE開發者中心的callback url,必須完全相同。因為curl會幫忙轉換所以不用放precentage encoding的結果。
- code 就是給LINE callback的授權碼。
- client_id 就是你的LINE登入的Channel ID。
- client_secret 就是你的LINE登入的Channel secret。
伺服器會回傳
{access_token: 'eyJhbG...Fdk',
token_type: 'Bearer',
refresh_token: 'VNd...c1c',
expires_in: 2592000,
scope: 'profile openid',
id_token: 'eyJ0eX...kKc'
}
- access_token 是用來取得使者資訊,驗證及撤銷時使用。
- refresh_token 是用來刷新access_token用的。
- id_token 是一種JWT格式,由兩個點(.)分隔的三段資訊,各段分別以BASE64編碼。
解碼id_token
使用JWT.io可以視覺化的看出JWT格式的三段資訊: header, payload, signature。我們取出第二段payload以BASE64解碼如下:
{"iss": "https://access.line.me",
"sub": "U1fc...945",
"aud": "16...18",
"exp": 1633414357,
"iat": 1633410757,
"nonce": "09876xyz",
"amr": [
"linesso"
],
"name": "Yung-Hsiang",
"picture": "https://profile.line-scdn.net/0hLh8h...SH4t"
}
包含使用者名稱,token發出時間,到期時間
取得使用者資訊
curl -v -X GET https://api.line.me/v2/profile \-H "Authorization: Bearer ${ACCESS_TOKEN}"
Bearer跟access_token之間有空格
伺服器回傳
{"userId":"U1fc...45",
"displayName":"Yung-Hsiang",
"statusMessage":"(Moon hehe)(Moon hehe)(Moon hehe)",
"pictureUrl":"https://profile.line-scdn.net/0hL...H4t"
}
驗證access_token
這裡主要是用來確認是否還可用這個access_token跟剩餘時間。
curl -v -X GET \"https://api.line.me/oauth2/v2.1/verify?access_token=${ACCESS_TOKEN}"
伺服器驗證成功回傳 http code 200
{"client_id":"16...18",
"expires_in":2585320,
"scope":"profile openid"
}
伺服器驗證失敗回傳 http code 400
{"error":"invalid_request",
"error_description":"The access token revoked"
}
刷新access_token
curl -v -X POST 'https://api.line.me/oauth2/v2.1/token' \-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token' \
-d "refresh_token=${REFRESH_TOKEN}" \
-d "client_id=${CHANNEL_ID}" \
-d "client_secret=${CHANNEL_SECRET}"
"access_token":"eyJhbG...Gv4",
"token_type":"Bearer",
"refresh_token":"VNdD...c1c",
"expires_in":2592000,
"scope":"profile openid"
}
-H 'Content-Type: application/x-www-form-urlencoded' \
-d "client_id=${CHANNEL_ID}" \
-d "client_secret=${CHANNEL_SECRET}" \
-d "access_token=${ACCESS_TOKEN}"
- refresh_token 是用授權碼從token API取得,或是之前刷新時給的refresh_token。
- client_id 就是你的LINE登入的Channel ID。
- client_secret 就是你的LINE登入的Channel secret。
伺服器驗證回傳,相較於用登入授權時少了id_token欄位
{"access_token":"eyJhbG...Gv4",
"token_type":"Bearer",
"refresh_token":"VNdD...c1c",
"expires_in":2592000,
"scope":"profile openid"
}
撤銷access_token
這個方法相當於登出LINE,讓access_token不能再使用。
curl -v -X POST 'https://api.line.me/oauth2/v2.1/revoke' \-H 'Content-Type: application/x-www-form-urlencoded' \
-d "client_id=${CHANNEL_ID}" \
-d "client_secret=${CHANNEL_SECRET}" \
-d "access_token=${ACCESS_TOKEN}"
- client_id 就是你的LINE登入的Channel ID
- client_secret 就是你的LINE登入的Channel secret
- access_token 是放使用者登入的access_token
沒有回傳內容
留言