สร้างระบบ Firebase Custom Authentication ด้วย LINE Login v2.1

Jirawatee
LINE Developers Thailand
6 min readMar 15, 2018

--

ตลอด 1 ปีที่ผ่านมา ผมได้รับคำถามจากสมาชิกในเพจ Firebase Thailand เรื่องการทำ Custom Authentication จำนวนไม่น้อย เนื่องจากพวกเขามีระบบสมาชิกอยู่แล้ว และต้องการใช้ระบบสมาชิกเดิมกับบริการอื่นๆใน Firebase ซึ่ง Firebase Authentication ก็เปรียบเหมือนประตูทางผ่านไปยังบริการที่สำคัญไม่ว่าจะเป็น Cloud Firestore, Realtime Database และ Cloud Storage แถมยังรองรับการทำ Custom Authentication จาก Social Provider อื่นๆและระบบสมาชิกที่มีอยู่ได้

และสำหรับบทความในวันนี้นั้น ผมจะขอเลือก LINE มาเป็นตัวอย่างในการเชื่อมต่อ ซึ่งเหตุผลที่เลือก LINE เนื่องจากวันนี้ LINE มีผู้ใช้ในไทยแล้วกว่า 42 ล้าน และ 95% จากผู้ใช้ Smartphone ในไทยก็ใช้งาน LINE ด้วย

ในมุมนักพัฒนา ด้วย LINE มี SDK และ APIs ให้พร้อมทั้ง Web, Android และ iOS จึงน่าจะเป็นตัวอย่างที่เอาไปปรับใช้ง่ายที่สุด ซึ่งภาพสุดท้ายที่ต้องการให้เกิดขึ้นในบทความนี้จะต้องเป็นประมาณนี้

ปฐมบท กับ LINE Login APIs และ SDK v2.x

ในเวอร์ชัน 2.x การทำงานของ LINE Login ก็ยึดมาตรฐาน OAuth 2.0 และ OpenID Connectโดยจะมี APIs ให้เลือกใช้ตามด้านล่างนี้

https://developers.line.me/en/docs/social-api/overview/

นอกจากนั้นก็ยังมี SDK ให้เราใช้ทั้ง Android และ iOS โดยสามารถดาวน์โหลดจากเว็บ LINE Developers ได้เลย

https://developers.line.me/en/docs/line-login/downloads/

ที่สำคัญคือเมื่อวันที่ 28 กพ ที่ผ่านมาทาง LINE Developers ก็ได้ประกาศให้นักพัฒนาสามารถขออีเมลจากผู้ใช้ที่เข้าสู่ระบบผ่าน LINE Login ได้แล้ว โดยนักพัฒนาสามารถขอ Permission นี้โดยการเข้าไปที่ LINE Developers Console แล้วเลือกเมนู Channel Settings แล้วอัพโหลด screenshot ที่ระบุเหตุผลที่ขอและการใช้งาน หลังจากนั้นไม่นาน ประมาณชั่วเคี้ยวหมากแหลก ระบบก็จะ approved (ที่ผมได้ลองคืออัพโหลดปุ๊บได้ปั๊บ)

และนักพัฒนาสามารถระบุ Scopes ของข้อมูลที่ได้หลังจาก login ว่าต้องการมากน้อยเพียงใดได้

โดยจะสังเกตุว่า นักพัฒนาสามารถขออีเมลได้แล้ว โดยการระบุ scope ทั้ง openid และ email เข้าไปใน Authorization Request API และผมมั่นใจว่านักพัฒนาเกินครึ่งที่อ่านบทความนี้ คงรอคอยอีเมลจาก LINE Login มาอย่างยาวนาน เพราะถ้าเราได้อีเมลมาก็น่าจะไปใช้ยืนยันหรือติดต่อกับผู้ใช้ง่ายขึ้น

และข้อมูลที่น่าเราสนใจในบทความนี้ก็จะประกอบไปด้วย user id, display name, profile picture และ email แต่จะสังเกตว่าอนาคตเราน่าจะขอ phone number ได้ด้วย อันนี้รอกันไปก่อนนะจ๊ะ

เดี๋ยวก่อน! ปัจจุบัน LINE SDK ทั้ง Android และ iOS ยังไม่รองรับการดึงค่าอีเมลมา คาดว่าทีม Engineer น่าจะกำลังพัฒนาอยู่ แต่ไม่เป็นไร เรามี APIs ที่รองรับการดึงอีเมลนี่ จะเชื่อมกับ Mobile ก็ไม่ใช่เรื่องยากเลยไอเสือ

Step by Step

ขั้นตอนที่จะสร้าง Firebase Custom Authentication ด้วย LINE Login จะขอแบ่งออกเป็น 6 ขั้นตอนด้วยตามในรูปด้านบน โดย

  • กล่องเขียวคือเชื่อมต่อ LINE Login
  • กล่องส้มคือเชื่อมต่อ Firebase
  • กล่องที่อยู่นอกเส้นประสีส้ม คือ Client ที่สามารถเป็นได้หมดทั้ง Web, Android และ iOS
  • กล่องที่อยู่ในเส้นประสีส้มคือ process ที่จะเกิดขึ้นใน server หรือในตัวอย่างนี้คือ Cloud Functions for Firebase

เมื่อพร้อมแล้วก็ มาเริ่มกันเลย

ขั้นตอนที่ 0 Create a Channel

ให้เราไปสร้าง Channel ของเราใน LINE Developer Console ก่อน โดยสามารถศึกษาขั้นตอนจากบทความของคุณข้าวปั้นได้

โดยเมื่อสร้าง Channel สำเร็จแล้ว เราจะได้สิ่งที่ทำคัญมา 2 อย่างด้วยกันคือ Channel ID และ Channel Secret เก็บไว้ให้ดี

ลำดับถัดไปให้ไปที่เมนู App Settings เมนูนี้ หากเราต้องการพัฒนาแอปใน platform ไหนก็ให้ระบุรายละเอียดให้ตรงกับแอปที่เราพัฒนานะครับ

สิ่งที่เราจะขาดไม่ได้ของทั้ง 3 platforms(เพราะเราจะใช้ APIs) คือ Redirect settings จะต้องระบุ URL เพื่อให้ LINE สามารถ Callback กลับมาหาเราได้ด้วย

ขั้นตอนที่ 1 Request Authorization Code

ขั้นตอนนี้จะเป็นการ Request ไปที่ API และ API จะ return HTML มาให้

https://access.line.me/oauth2/v2.1/authorize

ซึ่งประกอบไปด้วยตัวแปรที่ required 5 ตัวด้วยกันคือ

  1. response_type: สิ่งที่ต้องการจาก response นั่นก็คือ code นั่นเอง
  2. client_id: channel_id ที่ได้จากขั้นตอนที่ 0
  3. redirect_uri: url ที่เราระบุไปในขั้นตอนที่ 0 (ต้องเหมือนกันนะ)
  4. state: random string ได้ทั้งตัวเลขและตัวหนังสือ เพื่อป้องกันเคส cross-site request forgery
  5. scope: permission ที่ต้องการโดยคั่นด้วย %20 เช่น openid%20email

นอกจากนั้นก็ยังมีตัวแปร optional อื่นๆอีก สามารถศึกษาได้จากลิงค์นี้ https://developers.line.me/en/docs/line-login/web/integrate-line-login/

https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=12345&redirect_uri=https%3A%2F%2Fmokmoon.com%2Fbangkok&state=12345abcde&scope=openid%20email

ซึ่งสุดท้ายหลังจากเรา login ด้วย Web เสร็จเรียบร้อยจะมีการ redirect กลับมาตามที่เรากำหนด Callback URL ไว้ พร้อมค่า query string ของ code ไว้สำหรับขั้นตอนที่ 2 ต่อไป

https://mokmoon.com/bangkok?code=XXXYYYZZZ&state=12345abcde

ขั้นตอนที่ 2 Get Access Tokens

หลังจากเราเก็บ code ซึ่งเป็น query string จากขั้นตอนที่ 1 มาได้แล้ว ก็เรียก API ตัวถัดไปได้เลย

POST https://api.line.me/oauth2/v2.1/token

ซึ่งประกอบไปด้วยตัวแปร 5 ตัวที่ required

  1. grant_type: ประเภทของการให้สิทธิ์ ในที่นี่ให้ระบุ authorization_code
  2. code: code ที่ได้จากขั้นตอนที่ 1
  3. redirect_uri: url ที่เราระบุไปในข้อ 0(ต้องเหมือนกันนะ)
  4. client_id: channel_id ที่ได้จากขั้นตอนที่ 0
  5. client_secret: channel_secret ที่ได้จากขั้นตอนที่ 0

มั่นใจแล้วก็ปล่อยคิว

ผลลัพธ์ที่ได้จะอยู่ในรูปแบบ JSON Object ซึ่งสิ่งที่เราจะเก็บไปใช้ต่อจากขั้นตอนนี้ก็คือ access_token และ id_token นั่นเอง

เจ้า id_token ที่ได้มาเนี่ย value ของมันคือ JWT(JSON Web Tokens) ซึ่งจะประกอบไปด้วย

  • HEADER: อัลกอริทึมที่ใช้เข้ารหัส
  • Payload: ข้อมูลที่เข้ารหัส
  • Signature: ใช้ตรวจสอบว่ามีการปลอมแปลงข้อมูลหรือไม่

ซึ่งผมจะสนใจเฉพาะ Payload เพราะมันมี data ที่ผมต้องการอยู่ในนั้น เราสามารถหา libary ได้ทั้ง 3 platforms เพื่อมาแกะมัน โดยตัวอย่างนี้จะข้ามการตรวจสอบ signature ไปนะครับ

เมื่อเราแกะข้อมูล Payload มาได้เราก็จะเจอข้อมูล User info ที่ซ่อนอยู่ภายใน ซึ่งผมจะสนใจเฉพาะที่ใส่กรอบสีแดงเอาไว้ เก็บมันมาซะ

ขั้นตอนที่ 3 Verify Access Token

ตั้งแต่ขั้นตอนนี้ไปเราจะต้องมีความรู้เรื่องของ server script เข้ามา ซึ่งในที่นี่จะใช้ Cloud Functions for Firebase ซึ่งเราสามารถพัฒนาฟังก์ชันต่างๆรวมถึง APIs ด้วย Node.js โดยไม่ต้องเตรียม server เอง(ลดเวลาไปได้เยอะ) ส่วนใครยังไม่รู้จัก Cloud Functions ก็อ่านบทความนี้ก่อนนะ

ถัดไปเมื่อเราเข้าใจ Cloud Functions ไปแล้ว เราก็จะต้องมารู้จัก Firebase Admin SDK อีกตัว เพราะ Firebase Admin SDK จะช่วยให้เราได้สิทธิ์เข้าถึงบริการต่างๆใน Firebase แบบเป็น Admin ซึ่งเราจำเป็นต้องให้ Firebase Admin ช่วยสร้าง Firebase User ให้

ก่อนอื่นให้ไปที่ Firebase Console -> Project settings -> Service accounts ก็จะเจอหน้าจอประมาณนี้

จากหน้าจอนี้ จะเห็นว่าทีม Firebase นอกจากจะรองรับภาษา Node.js แล้วก็ยังมีภาษา Java, Python และ Go ด้วย แต่ในกรณี Cloud Functions for Firebase ก็ให้เลือก Node.js นะครับ เมื่อเลือกแล้วก็กด Generate new private key มาได้เลย จะได้ไฟล์ service-account.json มา ให้เราเอาไฟล์นี้ไปไว้ที่ root path ของ Cloud Functions

พร้อมแล้วก็ให้ verify token ก่อนเลยโดย ให้เราสร้าง API จาก Cloud Functions for Firebase แล้วรับค่าโพสเข้ามา โดยการโพสให้โพสเป็น JSON Object เข้ามาตามตัวอย่างด้านล่างนี้

จากตัวอย่างจะเห็นว่าผมส่งข้อมูลต่างๆที่ได้จากขั้นตอนที่ 1 และ 2 มาปั้นเป็น JSON Object

ก่อนจะถึงขั้นตอนการ verify ให้เราไปตั้งค่า config ใน Cloud Functions ก่อน โดยให้เราเอา channel_id ของเราไป config ไว้ (อ่านต่อไปเดี๋ยวรู้ว่าทำไม)

firebase functions:config:set line.channelid="<your_channel_id>"

จากนั้นเราจะต้องใช้ access_token มาเพื่อ verify ก่อนเป็นอันดับแรก

https://api.line.me/oauth2/v2.1/verify?access_token=<ACCESS_TOKEN>

ข้อมูลที่ return มาในกรอบสีแดง จะได้ค่า client_id หรีอ channel_id มา ซึ่งให้เราเอามาเปรียบเทียบกับค่าที่ config ไว้ สำคัญมากตรงนี้ เพราะไม่งั้น ใคร request มาสร้าง account ใน Firebase ได้หมดเลยน้า

ขั้นตอนที่ 4 Set / Get Firebase User

ขั้นตอนนี้เราจะสร้าง Firebase UID โดยเอาค่า User ID ไปต่อหลัง “line:”(เนื่องจากเราจะได้แยก user ใน Firease ได้ง่ายว่าใครมาจากช่องทาง LINE Login) จากนั้นเอา UID ที่ได้ไปเช็คกับ Firebase ก่อนว่ามี user คนนี้อยู่แล้วหรือไม่ ถ้ามีก็คืนข้อมูล user คนนั้นออกมาเลย ถ้าไม่มีก็ให้ไปสร้าง Firebase User ขึ้นมาใหม่ตามข้อมูลที่ Firebase รับ และข้อมูลที่เราเก็บมา เสร็จแล้วก็ return ข้อมูล user ออกไป

ขั้นตอนที่ 5 Create Firebase Custom Token

ถัดไปเราต้องสร้าง Custom Token ขึ้นมาก่อน เพราะการ Login ด้วย Firebase ได้นั้นจะต้องใช้ Credential ที่มาจาก Firebase เอง โดยเราจะส่ง Firebase UID ที่เราสร้างในขั้นตอนที่ 4 เข้าไปสร้าง จากนั้นก็ return Custom Token ให้ฝั่ง client ได้ละ

ขั้นตอนที่ 6 Login with Custom Token

มาถึงตรงนี้ก็ใกล้จะได้ไปออกรายการอาต๋อยละ ฝันที่เป็นจริง เมื่อรับค่า Custom Token ที่ return มาเราก็เอาค่านี้ไป sign in กับ Firebase ได้เลย ไม่ว่าจะเป็น Web, Android และ iOS ก็รองรับ แต่จากตัวอย่างคือ Android นะครับ

User Journey ทั้งหมด ก็จะเป็นประมาณนี้นะเออ

ที่แจ่มไปกว่านั้น คือเมื่อเรา logout แล้วไป login ใหม่ LINE Login เข้ามีสิ่งที่เรียกว่า Login Session ให้ด้วย ทำให้เราไม่ต้องไปกรอก Email กับ Password ใหม่น้า

หมายมั่น เอ้ย! หมายหัว เอ้ย! หมายเหตุ เอ้ย ถูกแล้ว!!!

1. LINE Login API v1 จะเริ่มทยอยหยุดให้บริการตั้งแต่ 31 มี.ค จนครบ ถึงวันที่ 30 มิ.ย นี้นาจา ไม่ย้ายไม่ได้นาจา เพราะ status code จะ return 4xx

2. MID จาก API v1 กับ User ID จาก API v2 นั้นไม่เหมือนกันนะเออ โดยทาง LINE Developers ได้เตรียมช่องทางการแปลงค่า MID เป็น User ID ให้แล้วที่ https://developers.line.me/en/docs/line-login/converting-mid-to-userid/ ดังนั้นใครที่ใช้ค่า MID จาก API v1 อยู่ ก็ทยอยอัพเกรดกันน้า

ปัจฉิมบท

ยินดีด้วยคุณมาถึงเส้นชัยแล้ว ซึ่งผมได้เตรียม source code ที่เป็น Android และ Cloud Functions for Firebase ให้คุณ clone ไปทดลองกัน

หวังว่าบทความนี้จะทำให้คุณใช้ LINE ซึ้งเป็น Platform ที่มีคนไทยใช้เยอะมากๆ กับแอปหรือเว็บของคุณ เพื่อเพิ่มความสะดวกสบายในการ Login ของผู้ใช้ของคุณได้ แล้วพบกันใหม่บทความหน้าครับ

--

--

Jirawatee
LINE Developers Thailand

Technology Evangelist at LINE Thailand / Google Developer Expert in Firebase