🔏

Nuxt + Vercel + SSG =「え、Basic認証使えないんですか!?」から始まる疑似的パスワード認証

2022/01/19に公開

こんにちは。
最近、業務でNuxt+Vercel+HeadlessCMSでSSGをしたサイトを作ることが多いのですが、SSGだとBasic認証が使えないという現象にぶつかりました。
単にBasic認証を使うのであれば、VercelではなくNetlify、もしくはSSGではなくSSRをして Nuxt.js basic auth module などを使う方法もあります。
https://www.npmjs.com/package/nuxt-basic-auth-module

しかしNetlifyのリージョンは日本にはなく、UIも使いづらいし....SSRにするとHeadlessCMS側が鯖落ちしたときにタイムアウトでサイトが見れなくなるというリスクを抱えてしまいますよね。

結論から話すと

fakeBasicAuth.js
const fakeBasicAuth = () => {
  const setPass = 'I am ironman 🤌'
  const whiteURL = ['192.168.86.87:3000', 'example.com']

  const htmlElStyle = document.querySelector('html').style
  htmlElStyle.opacity = 0
  const localPass = localStorage.getItem('fakeAuthStr')

  if (whiteURL.includes(location.host)) {
    htmlElStyle.opacity = 1
    return
  }
  if (localPass !== null && localPass === setPass) {
    htmlElStyle.opacity = 1
    return
  }
  window.setTimeout(() => {
    const password = window.prompt('パスワードを入力してください', '')
    if (password === setPass) {
      localStorage.setItem('fakeAuthStr', password)
      htmlElStyle.opacity = 1
    } else {
      htmlElStyle.opacity = 0
      htmlElStyle.pointerEvents = 'none'
      window.alert('パスワードが違います')
    }
  }, 500)
}
fakeBasicAuth()

上記の fakeBasicAuth.js をNuxtのプロジェクトのpluginsに格納して、

nuxt.config.js
plugins: [
    { src: '@/plugins/fakeBasicAuth', mode: 'client' },
],

とclientで読み込みます。

コードの説明

アラートでパスワードを聞いて、そのパスと定数setPassの文字列が一緒ならOKというシンプルなものです。
二度目はローカルストレージに保存しているので、再度打たなくてもいいようにしてあります。
また定数whiteURLは、パスを聞かなくてもいい開発環境や公開後のURLを配列に入れておきます。
失敗したらhtmlのスタイルを透明にしてポインターイベントをOFFにします

そもそもBasic認証の文化ってなんだっけ

Basic認証自体は認証と名前がついていますが、打ち込んだパスワードと名前サーバーに送る際に漏洩してしまうリスクがあるため安全ではありません。
しかし認証をつけないと、クライアントから「いや、これWeb上に公開されてるよね? 漏洩怖いから一応かけておいてよ」と言われてしまいがちです。
今回書いたコード、私は実務では使いませんがきっと何かの役に立つと思い立ってこのコミュニティに残しておきます。
もしもこれを読んでくれた方が Vercel+Nuxt+SSG の組み合わせで安全な認証をご存知でしたら教えてくれると嬉しいです。
読んでくれてありがとうございました。

Discussion