iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 5
2
Modern Web

Next.js + 各種套件組合系列 第 5

Next.JS & Firebase Auth

介紹
在各種前後端分離的驗證方式常見的有Jwt+Passport,基層以Jwt為基礎結合各家快速登入驗證的可以少寫很多程式碼, Friebase Auth 與 DATABASE並具有即時通知功能

Google 為範例
https://ithelp.ithome.com.tw/upload/images/20171208/201034384lBltbx5UD.png
進入 Friebase 控制台後 直接打開 Authentication 的登入方式 Google Friebase 因為已經是Google的產品所以設定只要打開就可以用了

再引入一個 Client 端與 Friebase 的連結設定檔,這邊是以 Web 為範例所以選第三個

https://ithelp.ithome.com.tw/upload/images/20171208/20103438k9dTTXLHIC.png

開始寫一個 index.js (可以參考最底下的範例)
先 import Friebase 以及上方的認證設定檔(以下程式碼為 clientCredentials ),並在元件 DiDMount 後開始初始化 Friebase,程式碼中的 onAuthStateChanged 可以監聽登出登入狀況,所以這邊就可以改變登出登入 State 狀況

index.js

 componentDidMount() {
    if (!firebase.apps.length) {
      firebase.initializeApp(clientCredentials)
    }
     firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.setState({ user: user })
      } else {
        this.setState({ user: null })
      }
    })
  }

這樣就完成基本的設定了接下來在程式碼中設定一個登入按鈕觸發以下的程式碼就可以完成 SPA 的登入,與上方程式碼會監聽下面按下後的登入狀況

_LoginClick=()=>{
   firebase.auth().signInWithPopup(new firebase.auth.GoogleAuthProvider())
}

加入其他登入
因為是策略模式所以如果要趕成 Twitter 或 Facebook 如圖中有提供的登入方式只要改對應的 AuthProvider()

例如

firebase.auth().signInWithPopup(new firebase.auth.FacebookAuthProvider())
firebase.auth().signInWithPopup(new firebase.auth.TwitterAuthProvider())
等等

除了在 Friebase Authentication 要打開才能使用,登入方法再打開都有附上說明都只要到各家 console 對應欄位填入資訊即可

Next.js with Friebase SSR介紹

後端準備工作 需要先記錄已登入狀況,使用 Sesson 來記錄已登入最適合,使用 Express 搭配 connect-redis,Friebase 也要用後端使用的lib firebase-admin 跟 後端的驗證

Server Part 引入以下設定檔

const express = require('express');
const bodyParser = require('body-parser');
const session = require('express-session');
var RedisStore = require('connect-redis')(session);
const next = require('next');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

Server Part 可以參考前幾篇介紹的 Next.js & Server 這邊多了一些 Session Part

const session = require('express-session');
var RedisStore = require('connect-redis')(session);

server.js 設定一下 REDIS MIDDLEWAVE

server.use(session({ 
    store: new RedisStore({
      host:'localhost',
      port: 6379
    }),
    secret: 'geheimnis',
    saveUninitialized: true,
  }));

如果 Client SPA 有偵測到異動也要同步更新後端 Session ,這邊修改一下ComponentDidMount的
firebase.auth().onAuthStateChanged 的,加入前後端同步的 Code

    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.setState({ user: user })
        return firebase.auth().currentUser.getToken()
          .then((token) => {
            return fetch('/api/login', {
              method: 'POST',
              headers: new Headers({ 'Content-Type': 'application/json' }),
              credentials: 'same-origin',
              body: JSON.stringify({ token })
            })
          })
      } else {
        this.setState({ user: null })
        fetch('/api/logout', {
          method: 'POST',
          credentials: 'same-origin'
        })
      }
    })

server.js 同步後端 Session 登出登入

server.post('/api/login', (req, res) => {   
    if (!req.body) return res.sendStatus(400)
    const token = req.body.token
    firebase.auth().verifyIdToken(token)
      .then((decodedToken) => {
        console.log('step1')
        req.session.decodedToken = decodedToken
        return decodedToken
      })
      .then((decodedToken) => res.json({ status: true, decodedToken }))
      .catch((error) => res.json({ error }))
  })
  server.post('/api/logout', (req, res) => {
    req.session.decodedToken = null
    res.json({ status: true })
  })

這樣如果有需要在 SSR 的時候就可以 getInitialProps 直接抓 USER 資料加快速度

  static async getInitialProps({ req, query }) {
    const user = req && req.session ? req.session.decodedToken : null
    // 看看後端是否有值
    return { user}
  }

總結

導入 Firebase Auth 程式碼可以少寫很多,設定上也簡化許多,之後如果還有要用 Firebase Database 或 Firebase 各項服務也很容易結合,在 Next.js PART 部分也是SSR的部分要比較注意, SPA有onAuthStateChanged 的時候記得後端要同步一下,範例使用的 File Session 這邊建議使用 Redis 會比較快

Firebase Auth 還有提供免費的 SMS 與 EMAIL 也有客製化登入 都是打開就可以使用的非常容易

https://www.youtube.com/watch?v=zWm7KgXceNU&t=130s (SMS 可以參考)

官方範例連結 (注意本次解說把範例中的 Database Part 抽掉 方便更容易理解)
https://github.com/zeit/Next.js/tree/canary/examples/with-firebase-authentication


上一篇
Next.js & Redux and Mobx
下一篇
Next.js & Material-UI
系列文
Next.js + 各種套件組合30

尚未有邦友留言

立即登入留言