Nuxt.jsでNCMB（ニフクラ mobile backend）のSNS連携機能を利用する

前回（[Nuxt.jsでNCMB（ニフクラ mobile backend）のデータストアを利用する](https://qiita.com/JQinglong/items/a586f5a1c1e1f8f2ea37)）、Nuxtアプリで、NCMBのデータストアへの登録・参照を試してみました。

それで終わるつもりでしたが、せっかくなのでBaaSとしての2大機能（勝手に言ってます）のもう一つ、認証関連の機能も見てみることにしました。

## NCMB の会員管理、認証機能

NCMBのドキュメントでは、下記のように機能紹介がされています。

![スクリーンショット 2020-09-04 16.39.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77307/e785d799-8a76-a306-d5b3-17754cb1588e.png)

サービスの画面は下記のようになっていて、会員管理、という表現が日本っぽくて面白いなと思いました。

![スクリーンショット 2020-09-04 16.40.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77307/5905cbf5-7f29-bf98-d3b5-3679979871b7.png)

## NCMB のSNS連携機能

そして、SNS連携機能機能が用意されているわけですが、どういうものかというと、SNSで認証を行なって取得した情報を使って、NCMBの会員として登録したり、ログインしているという状態を管理したりすることができる、というものです。
私個人はちょっと誤解していたのですが、各SNS認証はそれぞれ行う必要があります。

例えば、公式ドキュメントに記載のある、[Facebook連携のサンプル](https://mbaas.nifcloud.com/doc/current/sns/facebook_javascript.html#gsc.tab=0)を見ると、Facebook SDKを使って認証情報を取得していますし、あるいは、[Googleの例](https://blog.mbaas.nifcloud.com/entry/2018/10/29/153113)（なお、このGoogle＋の認証は現状方式が変更になっているようです）でも、Google+ APIで認証を行っています。

## Nuxt.js におけるOAuth認証導入

では、このサンプルを基に、Nuxtアプリで認証を行おうと思ったら、そのまま転用するのは難しかったです。
そして、その必要はなく、Nuxt用のモジュールが用意されていました。

Auth Module
[https://auth.nuxtjs.org/](https://auth.nuxtjs.org/)

この辺の記事を参考にさせていただきました。

- [Nuxt.js と auth-module で  OAuth 認証によるログインを実装する](https://blog.8tak4.com/post/176366654280/impl-oauth-nuxtjs)
- [NuxtでOAuth認証を導入する](https://tech.windii.jp/frontend/nuxt/oauth2)

これを使うことにより、FacebookやGoogleの画面を呼び出して、認証情報を返してもらうところは、ある程度、共通の書き方で、自動的に処理することができます。

若干わかりにくかったのが、情報の受け取り方でした。
例えば、Googleの場合だと、

```js
this.$auth.loginWith('google')
```

と書くのですが、これがPromiseを返すというので、thenで続けて、その中でResponseを受け取るようなことを書くのかなと思ったのですが、そうではなく、これによって、Googleログインのページに飛んで行き、正しくログインすると、callbackページに指定したURLに帰ってきて、さらに、homeページのURLに遷移します。
この間にState情報として認証情報がセットされているので、例えば、

```js
{{ $auth.user }}
```

としてあげれば、名前やメールドレス等が取得されていることが表示されます。

## 改めて、NCMB のSNS連携機能

このようにして認証情報が取得された状態で、今度はNCMBの会員情報として連携することになります。
以下Google連携の例です。

そのために用意されているのが、
[signUpWithメソッド](https://mbaas.nifcloud.com/assets/sdk_doc/javascript/jsdoc/classes/NCMB.User.html#method_signUpWith) と、[User.loginWithメソッド](https://mbaas.nifcloud.com/assets/sdk_doc/javascript/jsdoc/classes/NCMB.User.html#method_User.loginWith) です。

最初は、こちらのドキュメントを見ることになると思います。
[Google連携](https://mbaas.nifcloud.com/doc/current/sns/google_javascript.html#gsc.tab=0)
最初、何も書いてないじゃんと思いました。
が、ある意味これが全てであり、最初にGoogleログインを行ってね、と書いてあるので、上の Auth Module でのログインを行う必要があること分かり、

- ユーザーID
- アクセストークン

が必要だと書いてあるので、認証情報からそれを取得する必要があることが分かります。（けどやはり情報が足りない・・・）

上記二つのメソッドは、各プロバイダ（Google, Facebook ...）共通のメソッドとなっており、ただし、引き渡すdata（認証に必要な情報を保持したJSON形式のオブジェクト）はプロバイダごとに違っていて、Googleの場合は、最低限、ユーザーIDとアクセストークンが必要ということです。

では、具体的にどのような形のオブジェクトを作れば良いのか。一つのヒントは、上で紹介したFacebook連携のサンプルとかGoogleの例ですが、よりよい参考資料を見つけました。

https://github.com/NIFCLOUD-mbaas/ncmb_js/tree/8d29dc44273b975cab84a2805f70782c4b8ef47a/test/stub
この中からgoogleで検索して、[こちら](https://github.com/NIFCLOUD-mbaas/ncmb_js/blob/8d29dc44273b975cab84a2805f70782c4b8ef47a/test/stub/2013-09-01_classes_users_post_google_success.json)を見ると、 id と、 access_token という名前でオブジェクトを作れば良いことが分かります。

ということで、こんな形にしてみました。

```js:pages/todo.vue
  mounted () {
    const NCMB = require('ncmb');
    const ncmb = new NCMB(process.env.APPLICATION_KEY, process.env.CLIENT_KEY);

    if (this.$auth.user) {
      console.log(this.$auth.$storage)
      const authInfo = {
        id: this.$auth.user.sub,
        access_token: this.$auth.getToken('google').replace('Bearer ', '')
      }

      const user = new ncmb.User;
      user.signUpWith('google', authInfo);
      ncmb.User.loginWith('google', authInfo);
    }
  },
```

```js:nuxt.config.js
  auth: {
    redirect: {
      login: '/',  // 未ログイン時のリダイレクト先
      logout: '/',  // ログアウト処理を実行した直後のリダイレクト先
      callback: '/callback',  // コールバックURL（各プロバイダで設定したものと同じPathにする）
      // home: false,  // ログイン後に遷移するページ
      home: '/todo',  // ログイン後に遷移するページ
    },
    strategies: {
      github: {
        client_id: process.env.GITHUB_CLIENT_ID,
        client_secret: process.env.GITHUB_CLIENT_SECRET,
        scope: ['read:user'],  // デフォルトだと ['user', 'email'] となり、権限がやや強いので絞る
      },
      google: {
        client_id: process.env.GOOGLE_OAUTH_CLIENT_ID,
      },
    },
  },
```

正直、これで良いか分かりません・・・動いてはいますので、入り口で悩んでいる方用のはじめの一歩と捉えてください。
home に '/todo' を指定しているので、認証に成功したら、pages/todo.vue に処理が来ます。
その mounted で、ncmbへの会員情報連携を行うという仕組みです。

上に書いたように、Auth Module で認証に成功すると、this.$auth.user に情報が入っています。
this.$auth.user の中身を見てみると、sub にIDが入っているのが分かりますので、オブジェクトに詰め込むidはこれを使用します。
ちょっとハマったのは、access_token の方です。
Auth Module のドキュメントでも、トークンの取得方法は書かれていません。ただ、setToken があるのだから、getToken もあるだろう、のノリで試してみたらあった、という感じです。
ただし、取得したままだと、"Bearer ya29.bAoB..." というような値になっています。
これをこのまま使うと、signUpWith メソッド内で401エラーが発生します。
下記に書かれているのと同じエラーです。
https://github.com/NIFCLOUD-mbaas/UserCommunity/issues/1123

ですので、「.replace('Bearer ', '')」 というダサいことしています。
本当はどうするのが正解ですか？？

## まとめ
以上により、NCMBサインアップにも成功して、冒頭の画像のように会員として登録されました。

ここまでくるのは結構苦労しましたが、これで認証連携も使えるようになりました。

Firebase から乗り換えても良いんじゃない？？もう少し検討・・・