useSession？なにそれおいしいの？

## はじめに
2024年5月から案件が変わり、自社の既存案件でPythonやReactでコーディングしてます。
学んだことの忘備録をつけようと思い、貴重な土曜日捧げます。

先月までは(1~4月)、客先でテスターしており一気に環境変わりましたが何とかやれております。
https://qiita.com/naoya_347/items/4dbb411fad84160221e0

## 前提
今回の任務としては、Googlge Driveの情報をwebアプリに取り込むというものです。
[こんな感じ](https://developers.google.com/drive/api/reference/rest/v3)の外部APIを毎日叩いている人生です。

で、フロントとサーバーに繋ぎ込みをしているときにuseSessionってすごいと感じ、アウトプットしようと思いました。

## 本編

#### フロントとサーバーの通信について
一つの例として、以下の流れのパターンがありました。
① フロントからGoogle認可サーバーに通信(ユーザーにGoogle認証してもらう)
② 認可コードを取得し、アプリに戻る（リダイレクトURLでアプリに帰ってきてもらう)
③ この時、認可コードをサーバーに送り、アクセストークンを発行し保存する

この③の時、サーバーにユーザー認証のトークンを送信するため、どうやってフロントでトークンを取得するのか悩んでいたときにuseSessionを知りました。
https://next-auth.js.org/getting-started/client

#### コード例
サーバー側にHTTPリクエストするときこんな感じの関数にしました。

```ts
import { useSession } from 'next-auth/react'

export const useHogeClient = () => {
  const { data: session } = useSession()

  const getHeaders = async () => {
    const token = session?.user.token

    return {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`
    }
  }

  async function post({
    url,
    data,
    options
  }: {
    url: string
    data?: {}
    options?: {}
  }) {
    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: await getHeaders(),
        body: JSON.stringify(data || {}),
        ...options
      })
      const json = await response.json()
      return json
    } catch (err) {
      // 略
    }
  }
```

#### useSessionとは
useSessionは、Next.jsアプリケーションにおけるユーザーの認証状態を管理するためのReactフック。
このフックを使用することで、現在のユーザーのセッション情報を簡単に取得し、ユーザーが認証されているかどうかを確認することができる。すごい（KONAMI感）
https://next-auth.js.org/getting-started/client

sessionオブジェクトの中身例
```typescript
{
  user: {
    name: string
    email: string
    image: string
  },
  expires: Date // This is the expiry of the session, not any of the tokens within the session
}
```

#### 基本的な使い方
useSessionフックを使用するには、まずnext-authライブラリをインポート。
次に、useSessionフックを呼び出してセッション情報を取得。
セッション情報には、ユーザーの名前、メールアドレス、画像などが含まれます。

↓公式引用
```typescript
import { useSession } from 'next-auth/react'

const MyComponent = () => {
  const { data: session, status } = useSession()

  if (status === "loading") {
    return <p>Loading...</p>
  }

  if (status === "authenticated") {
    return <p>Signed in as {session.user.email}</p>
  }

  return <p>Not signed in</p>
}
```

#### セッション情報のカスタマイズ
今回、ユーザー認証のトークンを送信するためにセッション情報のカスタマイズして使いました。
これは、next-authの設定ファイルでセッション情報をカスタマイズすることができます。
https://next-auth.js.org/configuration/callbacks

Sessionコールバックを使用してトークンに追加情報を含めました。
https://next-auth.js.org/configuration/callbacks#session-callback
```typescript
...
  callbacks: {
    // sessionにJWTトークンからのユーザ情報を格納
    async session({ session, token }) {
      session.user.uid = token.uid
      session.user.token = token.idToken
      return session
    }
  }
}
...
```

これにより今回のようにサーバー側にトークンを送信できました。
```ts
import { useSession } from 'next-auth/react'

export const useHogeClient = () => {
  const { data: session } = useSession()

  const getHeaders = async () => {
    const token = session?.user.token // ここでトークン取得できる

    return {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`
    }
  }
```

## 雑感
フロントエンドのエンジニアの方の偉大さを改めて感じました。
今の機能チームでは、レビューがないかつフロントエンドもいないため、キャッチアップしながらのコーディングですが引き続き頑張りたいです。心が折れない程度に。
あと、今後も実務で知れたことアウトプットして血肉にしたいと思ったりしてます！