🪄

Magicを使ったマジックリンクログインをReactでの素振りサンプルと感想

2021/03/10に公開

Magicというマジックリング認証に特化したサービスを知ったので素振りしてみた記録。

サーバーサイドまで含め入ったサンプルは公式のチュートリアルにある

逆にSPAのようなクライアントログインの最低限パターンのサンプルが見当たらなかったので、素振りを書いてみた

サンプル

import { Magic } from 'magic-sdk'
import { useState, useEffect } from 'react'

// Dashboardに表示されたpublishable keyを持ってくる。これは公開してよいキー
const MAGIC_LINK_PUBLIC = "pk_test_****************"

// hooksに処理をまとめる
const useMagicLogin = () => {
  const [isReady, setIsReady] = useState<boolean>(false)
  const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false)
  const [loginEmail, setLoginEmail] = useState<string | null>(null)

  const getMetadata = async () => {
    const magic = new Magic(MAGIC_LINK_PUBLIC)
    const isLoggedIn = await magic.user.isLoggedIn()
    setIsLoggedIn(isLoggedIn)
    if (!isLoggedIn) {
      return
    }
    const metadata = await magic.user.getMetadata()
    setLoginEmail(metadata.email)
  }

  const checkLogin = async () => {
    setIsReady(false)
    await getMetadata()
    setIsReady(true)
  }
  const login = async (email: string) => {
    await new Magic(MAGIC_LINK_PUBLIC, { locale: "ja" })
      .auth
      .loginWithMagicLink({
        email: email,
        // showUI: false // 英語画面を避けたければこのオプションを付ける。
      })
    checkLogin()
  }
  const logout = async () => {
    const magic = new Magic(MAGIC_LINK_PUBLIC)
    await magic.user.logout()
    setLoginEmail(null)
    checkLogin()
  }
  useEffect(() => {
    checkLogin()
  }, [])
  return { isReady, isLoggedIn, logout, login, loginEmail, checkLogin }
}

// ログインフォーム
const LoginForm = ({ login }) => {
  const handleSubmit = async (event) => {
    event.preventDefault()
    const { elements } = event.target
    login(elements.email.value)
  }

  return <div>
    <form onSubmit={handleSubmit}>
    <label htmlFor="email">Email</label>
      <input name="email" type="email" />
      <button>Log in</button>
    </form>
  </div>
}

// ログイン後ページ
const AfterLogin = ({ logout, loginEmail}) => {
  return <div>
    <div>Welcome: {loginEmail}</div>
    <button onClick={() => { logout() }}>logout</button>
  </div>
}

// ルート部分
export const App = () => {
  const { isReady, isLoggedIn, logout,login, checkLogin,loginEmail } = useMagicLogin()
  if (!isReady) {
    return <div>loading...</div>
  }
  if (!isLoggedIn) {
    return <LoginForm login={login} />
  }
  return <AfterLogin logout={logout} loginEmail={loginEmail}/>
}

感想

良い点

  • pk_*** / sk_**** というキーの区分けはstripeっぽく明快で扱いやすい
  • ReactNative版があるの嬉しい。ほぼ上記と同じような実装で行ける
  • マジックリンク実装に特化してるのは嬉しい部分
    • OAuth連携もあるっぽいが未検証
    • firebase認証より全体的に簡易に感じる
  • もうすぐ新プライシングになるらしい(問い合わせると教えてくれる)

課題点

Discussion