🧑‍💻

Supabaseを使った認証機能とGAS API

2024/01/05に公開

はじめに

今回はログイン機能を作って勉強したいな〜と考えていたら、SupabaseでgoogleやGit Hubなどを使用したログイン機能(認証)を作れることがわかったので、試してみました。
また、GAS(Google App Script)を使用して何かしたいな〜と思っていたので、Supabaseとなら簡単にそういうことができるかなと考えていました。

Supabase

SupabaseはどういうものなのかというのがサイトTOPに書いてありました。

SupabaseはFirebaseに代わるオープンソースです。
Postgresデータベース、認証、インスタントAPI、エッジファンクション、リアルタイムサブスクリプション、ストレージ、Vectorエンベッディングでプロジェクトを始めましょう。

https://supabase.com/

要は簡単にDBを作成したり、それをフロントエンドから呼び出したり(API)、認証やその他バックエンド機能を提供してくれているものです。
私はバックエンドの構築などはあまりやったことないので、今回はこちらを使わせていただきました。

構築

  • 技術面
    • nuxt: "^3.8.2"
    • "@nuxtjs/supabase": "^1.1.4"
    • TypeScript
  • 認証
    • Google Cloud Platform
    • Supabase
    • Google App Script

今回は上記のようなものを使用してやっていきたいと思います。

手順: 認証〜TOPページまで

手順1: Nuxt環境構築

今回は nuxt.js @nuxtjs/supabase("^1.1.4") を使用して構築していきます。

まずはnuxtのプロジェクトを立ち上げます。

pnpm dlx nuxi@latest init <project-name>

こちらのコマンドで環境を立ち上げ、
Which package manager would you like to use? -> pnpm
Initialize git repository? -> no
と答えたらプロジェクトが完成です。

そして、プロジェクト配下に進み

pnpm i

を実行し、

pnpm dev

でlocalhost:3000にアクセスします。

手順2: Supabaseで認証機能の実装

先ほど構築したNuxtのプロジェクトでSupabaseを使用できるようにしてきます。

pnpm add @nuxtjs/supabase

を実行し、module追加します。

また、Supabaseのサイトにアクセスし、sign upします。
プロジェクトなどを構築するのですが、ここは公式のサイトの通りに進めてみてください。

今回はgoogleの認証機能を使用したいので、下記画像の通り、Authenticationのprovidersから、googleの部分をenableに変更してください。
また、のちにこちらにclient IDなどを入力しますが、一旦はそのままでOKです。また、CallBack URLはこの後の手順3で使用しますので、コピーして置いてください。

また、下記画像のようにsettingからURLservice_roleを確認し、のちに使うのでコピーしたりしてひとまずは置いておきます。

これでひとまずはSupabaseの設定は完了です。

手順3: Google Cloud Platformで認証設定

続いてはGoogle Cloud PlatformでSupabaseとの連携をするために設定していきます。

まずは公式サイトにアクセスして、プロジェクトを作成します。
こちらもそのまま手順通りに登録作業を行なっていくだけなので、説明はスキップします。

そして登録作業を終えたらまずはクイック アクセスAPIとサービスをクリックし、認証情報へ進みます。認証情報を作成 -> OAuthクライアントIDへ進み、作成を進めます。


  • アプリケーションの種類 -> ウェブアプリケーション
  • 名前 -> なんでもOKです
  • 承認済みのJavaScript生成元 -> 今回は"http://localhost:3000"と"http://localhost"を指定
  • 承認済みのリダイレクトURI -> SupabaseのCallBack URL

こちらの設定ができたら保存で完了です。
完了するとポップアップでクライアントIDクライアントシークレットが出てきますので、こちらをSupabaseのProviderの部分で設定します。

こちらでSupabaseとGoogle Authの設定は完了です。
次は実際にNuxtのプロジェクトで動かしていきます。

手順4: Nuxtでlogin画面とTOPページを作成してみる

続いてはフロント側の実装に入ります。
ディレクトリ構造は下記の通りにしたいと思います。

  • src
    • page
      • login.vue(Loginページ)
      • index.vue(TOPページ)
  • .env(ここにSupabaseのURLservice_roleを設定します)
  • nuxt.config.ts

下記コードでlocalhost:3000へアクセスしたら、googleAuthの画面へリダイレクトし、そこで認証を終えたらTOPページにリダイレクトする仕組みです。

nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  ssr: false,
  srcDir: "src/",
  css: [],
  vite: {},
  app: {
    head: {
      title: "Supabase and Google Auth",
      meta: [
        {
          name: "viewport",
          content: "width=device-width, initial-scale=1",
        },
        {
          charset: "utf-8",
        },
      ],
      link: [],
      style: [],
      script: [
      ],
      noscript: [],
    },
  },
  modules: [
    "@nuxtjs/supabase",
  ],
  supabase: {
    url: process.env.VITE_SUPABASE_URL,
    key: process.env.VITE_SUPABASE_KEY,
    redirectOptions: {
      login: "/login",
      callback: "",
      exclude: [],
    },
    cookieOptions: {
      maxAge: 60 * 60 * 8,
      sameSite: "lax",
      secure: true,
    },
  },
});
.env
VITE_SUPABASE_URL="SupabaseのURL"
VITE_SUPABASE_KEY="Supabaseのservice_role"
login.vue
<script setup lang="ts">
  //ここでsupabaseのAPIクライアントを呼んでます。
  const supabase = useSupabaseClient();

  //ここでsign inの設定を書きます。
  await supabase.auth.signInWithOAuth({
    provider: "google",
    options: {
      queryParams: {
        access_type: "offline",
        prompt: "consent",
      },
      redirectTo: "/",
    },
  });
</script>

<template>
  <div class="login"></div>
</template>

<style scoped lang="scss">
  .login {
    width: 100vw;
    height: 100vh;
    background-color: #f5f5f5;
  }
</style>
index.vue
<script setup lang="ts"></script>

<template>
  <div class="top">Success log in!!!!</div>
</template>

<style scoped lang="scss">
  .top {
    width: 100vw;
    height: 100vh;
    background-color: #f5f5f5;
  }
</style>

こちらで認証を終えてログインできる機能を実装することができました。

手順: TOPページからGASで定義した関数を呼び出す

手順1: GASプロジェクトの設定

google app scriptでまずはプロジェクトを作成します。
公式サイトへアクセスし、左側のメニューから新しいプロジェクトを選択します。
そうするとコードエディタが出てきます。

function myFunction() {
  return "done Function!!!";
}

上記のような感じで、呼び出した後に"done Function!!!"という文字列が返ってくるように設定してみます。

手順2: GASプロジェクトのデプロイ

次にデプロイ作業です。右上のデプロイから新しいデプロイを選択します。
種類の選択から実行可能APIを選択し、そしてプロジェクトの種類を変更を選択します。すると設定の画面に飛ぶので、Google Cloud Platform(GCP)プロジェクトまでスクロールします。

プロジェクト変更 -> プロジェクト番号入力

となりますが、ここの番号はGoogle Cloud Platformのトップページのプロジェクト番号になります。
またアクセスできるユーザーについては、ご自身で決めていただいて大丈夫ですが、セキュリティなどの観点から限定する方がおスメです。

手順3: NuxtプロジェクトからGASを呼ぶ

今回呼び出すにあたって下記のGoogle APIを使用します。
https://developers.google.com/apps-script/api/reference/rest/v1/scripts/run?hl=ja#http-request

scriptIdデプロイIDになります。
GASの
デプロイ -> デプロイを管理 -> 自分が先ほどあげたプロジェクトのデプロイID
で確認することができます。

今回はlogin.vueでログインした後にindex.vue(TOPページ)からGASの関数を呼び出すという流れを想定します。

index.vue
<script setup lang="ts">
  // access_tokenを取得
  const accessToken = computed(() => {
    const token = localStorage.getItem("sb-hogehoge-auth-token");
    return JSON.parse(token!).provider_token;
  });

  const executionGoogleAppScript = () => {
    fetch( "https://script.googleapis.com/v1/scripts/{scriptId}:run",
      {
        method: "POST",
        headers: {
          Authorization: "Bearer " + accessToken.value,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          function: "myFunction",
        }),
      }
    )
      .then((res) => {
        res.json().then((data) => console.log(data.response.result));
      })
      .catch((err) => {
        console.log(err);
      });
  };

  executionGoogleAppScript();
</script>

<template>
  <div class="top">Success log in!!!!</div>
</template>

<style scoped lang="scss">
  .top {
    width: 100vw;
    height: 100vh;
    background-color: #f5f5f5;
  }
</style>

このようにログインごとに毎回生成される"sb-hogehoge-auth-token"(名前はsupabaseのURLになっているはずです)の中のprovider_tokenをlocalStorageへ取得しにいきます。
そのtokenをfetchするときのheaderに用いて"https://script.googleapis.com/v1/scripts/{scriptId}:run"へ実行命令をpostします。
bodyの箇所で自分がGASで定義した関数名(myFunction)を入れ実行し、data.response.resultの中に関数が返した文字列が入っているという流れになります。
consoleで確認すると、"done Function!!!"と表示されているはずです。

まとめ

今回はSupabaseとGoogleを使用し、認証ログインを可能にし、その後GASで定義した関数を実行するという流れで記事を書きました。
認証ではリダイレクトの設定を行うことや毎回access tokenが発行されるという当たり前のことを学んだほか、ネットワークを学ばなくてはいけないなと思ういい機会になりました。(TCP/IPなど)
そしてGASをフロントエンド側から呼ぶことができることも知り、より開発の幅が広がったなと思いました。
実際に使う機会があるのかと言われればまだ思いつかないのですが、今後この仕組みを利用して何か作りたいと思います。

参考

https://developers.google.com/apps-script/api/reference/rest/v1/scripts/run?hl=ja#http-request
https://zenn.dev/ficilcom/articles/f518ce531b2d42#はじめに
https://blog.shinonome.io/google-api/
https://recruit.gmo.jp/engineer/jisedai/blog/run-gasscript-via-api/

Discussion