標籤

LINE Login

Day22 - 最常用的搭配 - 使用 Login + Message API 讓使用者在掃描加入好友時就綁定帳號

前言

在第 Day 13 Python SDK 試玩的時候使用過 get_profile,當時使用時就是在每次訊息來的時候才去 SQL 儲存使用者資訊,若只是單純想要使用者資訊的話這樣用好像有點多餘 😓,以下就帶各位簡單的實作。

實作

我們要將上篇的前端頁面(line_login_auth.html)改造一下

<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>LINE Login</title>
  </head>
  <body></body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
  <script>
    $.ajax({
      url: "https://YOUR_SLS_DOMAIN.us-east-1.amazonaws.com/dev/line/auth",
      method: "POST",
      success: function(data) {
        window.location.replace(data.result);
      }
    });
  </script>
</html>

這邊我將 button 的 onclick 事件以及 button 本身移除掉,目的是要讓使用者一到這個頁面之後就直接透過 AJAX call api

到了這裡應該有感應到什麼了吧!接著就是把這個 html 檔的 S3 路徑網址使用 QR code 包起來,讓他看起來像是 LINE bot 的 QR code

到了這邊基本上已經快完成了,參考 LINE 的好友說明或下圖

接著到機器人的開發者頁面,並且往下滑會看到自己機器人的 QR code 以及 Bot 的 ID,把他複製下來並製作機器人的加好友網址

像是這樣子

https://line.me/R/@1234

接著到 controller/line_login_controller.pydef get(self)最後一行,原本我們這邊做的是回傳 JSON

if dt:
			return {'result': dt}, 200

改用

from flask import redirect
if dt:
 		return redirect("https://line.me/R/ti/p//@127ojvgz", code=302)

如此一來在登入驗證完之後就會把使用者導向到加好友的頁面,在手機上若已經加過好友則會直接導到機器人對話窗上,如此一來就可以讓使用者在加入好友的同時也綁定完帳號,在未來使用的時候 api 這邊也比較好控管使用者的權限問題。

結論

像是我自己做的健身記錄機器人,就是以這個方法下去實作,有聽過一些朋友跟我反應這樣的方法多此一舉,但我認為若是有網頁的話也是套用 LINE SSO 來實作,就可以讓兩個入口去統一,在狀態流上就能比較好控制了。

繼續閱讀

Day21 - LINE Login 實作

前言

現在有規模的平台提供商基本上都會提供 Single Sign On (SSO)的登入機制,藉由他們的平台讓一般小網站可以讓使用者免密碼登入,雖然有很多種 Oauth2 的套件,不過我還是喜歡自己打 🤣,下面就開始嚕!

實作

views/建立一個line_login_auth.html,填入以下內容,主要是實作一個按鈕並透過 javascript 來互叫 api 並導向到 LINE 頁面

<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>LINE Login</title>
  </head>
  <body>
    <button class="auth" onclick="auth()">LINE LOGIN</button>
  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
  <script>
    function auth() {
      $.ajax({
        url: 'https://YOUR_SERVERLESS_DOMAIN.amazonaws.com/dev/line/auth',
        method: 'POST',
        success: function(data) {
          window.location.replace(data.result);
        },
      });
    }
  </script>
</html>

接著我們在.env加入 LINE Login 的環境變數並輸入對應的參數

LINE_LOGIN_CLIENT_ID=
LINE_LOGIN_SECRET=
LINE_LOGIN_URI=https://YOUR_SERVERLESS_DOMAIN.amazonaws.com/dev/line/auth

最後就是我們最重要的部分了,實作 GET a& POST 的 api,這邊我先從 POST 講起,這邊主要是把環境變數組在網址中回傳給前端,這邊需要注意的是state他是在回傳回來的 JWT 需要解碼時所使用的,這邊我簡單打個字串,然而實際上會隨機產個變數,確保解碼的安全。

GET 則是負責處理從 LINE 回來的參數們,這邊我只用回傳回來的stateid_token解開,拿到裡面的使用者的參數,後續可以參照應用把資訊存下來,放入 session 並告知前端已登入。

from flask import request
from flask_restful import Resource
import requests
import webbrowser
import os
import jwt
import json


class LineLoginController(Resource):
	def get(self):
		r = requests.post(
			"https://api.line.me/oauth2/v2.1/token",
			data={
				"grant_type": "authorization_code",
				"code": request.args.get('CODE'),
				"redirect_uri": os.environ.get('LINE_LOGIN_URI'),
				"client_id": os.environ.get('LINE_LOGIN_CLIENT_ID'),
				"client_secret": os.environ.get('LINE_LOGIN_SECRET'),
			}, headers={"Content-Type": "application/x-www-form-urlencoded"})
		payload = json.loads(r.text)
		print(payload)
		token = payload.get("id_token")
		if token is None:
			return {'result': payload['error_description']}, 400

		state = request.args.get('state')
		token = token.encode()
		dt = jwt.decode(token, state, None, algorithms=['HS256'])
		if dt:
			return {'result': dt}, 200

	def post(self):
		r_uri = os.environ.get("LINE_LOGIN_URI")
		client = os.environ.get("LINE_LOGIN_CLIENT_ID")
		state = "nostate" # it will be random value
		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}"
		return {'result': uri}

JWT 解開的參數如下,sub就是 LINE 的唯一值 ID,一般拿到這個就可以知道是來自 LINE 的使用者了。

{
  "result": {
    "iss": "https://access.line.me",
    "sub": "Ud6ab866a67xxxxxxxxb12b0baffb8ac",
    "aud": "1622939248",
    "exp": 1569925548,
    "iat": 1569921948,
    "amr": ["linesso"],
    "name": "NiJia Lin",
    "picture": "https://profile.line-scdn.net/0hKvTocMuLFFlpFj9HpKdrDlVTGjxxxxxxxxx1YHACMOPRtEHmkWJVIKUyUJNkQWGT0X",
    "email": "loxxxxx09@gmail.com"
  }
}

最後別忘了要在api.py加入路由才會被導出去ㄛ

from controller.line_login_controller import LineLoginController
api.add_resource(LineLoginController, '/line/auth')

結論

在實作的時候不知道為什麼一直不能讓 python 去幫我把用戶導去 LINE 認證的頁面,我記得之前寫 Ruby 可以啊(?),最後只好讓前端去幫我把使用者導出去,這邊就帶大家做到這嚕!

繼續閱讀

Day20 - LINE Login 申請與基本頁面

前言

上篇介紹了好多了,這邊就不廢話了,直接就帶大家申請一個 LINE Login 的服務。

實作

首先到自己的開發者頁面按+,並選擇最左邊的選項 接著輸入App name(服務名稱)、App description(服務簡介),因為我們是實作 API ,所以選擇Use WEB的選項,接著再輸入email 把該填的填完之後按下送出就會看到有一個新的服務嚕! 點進去後往下滑,可以看到有個 link to this channel 的選項,這邊選擇一開始建立的那隻機器人,綁定之後就變它的形狀啦(?) 接著再往下會看到 Email 的狀態是 Unapplied,然後按下右邊的Submit 會看到這樣子的一個框框,把兩個框框打勾並選擇一張圖片上傳,這部分就算是申請帳號下面的同意服務條款一樣,圖片就上傳自己希望當使用者到你頁面的時候想看到的圖片 🤣,送出之後就會看到狀態改成 Applied

結論

很多時候實作對我們來說已經不是什麼問題了,重點是在找不到服務要怎麼去申請 😓,這篇也算是記錄一下申請的步驟細節,接下來會實作個簡單的認證頁面以及 API,打完收工嚕!

繼續閱讀

Day19 - LINE LOGIN 介紹

前言

LINE 中文版也上線啦 URL 去某些網站登入你可能會有像下面這樣 或者是你有玩過 LINE Rangers (怎麼感覺我好老),就會看到他們登入畫面有個登入鈕,按下去按確認後就登入,使用者不用輸入帳號密碼。 這個機制被稱為 SSO (single sign-on),它是透過 OAuth2 的機制來做認證,因為不儲存密碼除了可以降低儲存第三方網站的風險,以及使用者不需要記憶各種不同的密碼所帶來困擾,像是 Facebook、Google、LINE...都有相關的機制可以串連 SSO 的服務。

以下會介紹 LINE Login 的流程。

流程

這裡我使用 LINE Login

  1. 服務要引導使用者到 LINE 認證頁面並帶著必填的欄位。
  2. LINE 會在瀏覽器上打開認證頁面,使用者必須按下同意才會進行認證。
  3. LINE 會透過設定過的 redirect_uri 還給你一個 authorization code 以及 state 在 Query string 上。
  4. 你的服務需要將 authorization code 打到https://api.line.me/oauth2/v2.1/token
  5. LINE 確認完之後就會送你一個 access token 嚕!

    可以拿透過 social API 去拿到相關資訊

結論

下一篇再帶著大家申請一個 LINE Login 的服務並建立一個簡單的註冊頁面~

參考

OAuth wiki LINE overview LINE 中文文件

繼續閱讀