9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NextAuthで認証してGitHubのアクセストークンを取得でのハマりポイント

Last updated at Posted at 2020-07-09

Next.jsで認証するのに何を使おうか・・

せっかく**Next.js使ってるしNextAuthを使ってみよう!**ということで、軽い気持ちで導入したらドハマリしました。

今回GitHubのアクセストークンを取得する認証の仕組みを作りたいなと思いNextAuthを使いました。

GitHubで認証してアクセストークンの取得でハマったポイントを書きます。

Next.jsでAPIを定義

NextAuthではAPIを使うのでまずはNext.jsのAPI定義方法をさらっと。

Next.jsではpages/api配下にファイルを配置することで、APIのエンドポイントを定義することができます。

pages/api/user.js
export default (req, res) => {
  res.statusCode = 200
  res.setHeader('Content-Type', 'application/json')
  res.end(JSON.stringify({ name: 'John Doe' }))
}

NextAuthでAPIを実装

NextAuthではNext.jsのAPIルーティングの機能を利用してpages/api/[...nextauth].jsを作ることによって認証に必要なAPIを定義することができます。

pages/api/[...nextauth].js

import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'

const options = {
  site: process.env.SITE || 'http://localhost:3000',

  // Configure one or more authentication providers
  providers: [
    Providers.GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET
    }),
  ],

  // A database is optional, but required to persist accounts in a database
  database: process.env.DATABASE_URL,
}

export default (req, res) => NextAuth(req, res, options)

NextAuthのセッション管理の種類

NextAuthではセッション管理に2パターンあります。

  • DB
  • JWTトークン

オプションのdatabaseはDBを使う場合に指定が必要ですが、今回はJWTでのトークン発行を使いたいのでoptionsから消してしまって問題ありません。

もしdatabaseの指定がない場合はオプションのsession.jwtが自動的にtrueになり、JWTトークンによるセッション管理になります。

公式のオプションにあるsessionの項目にも記載があります。


// Use JSON Web Tokens for session instead of database sessions.
// This option can be used with or without a database for users/accounts.
// Note: `jwt` is automatically set to `true` if no database is specified.

セッションの取得

NextAuthでセッションを取得するにはuseSession()やgetSession()を使います。

そしてドキュメントを見るとデータは下記のような感じで返ってくるんだな、と理解したのですがここがひとつハマりポイントでした。

{
  user: {
    name: string,
    email: string,
    image: uri
  },
  accessToken: string,
  expires: "YYYY-MM-DDTHH:mm:ss.SSSZ"
}

実際にuseSessionを使ってみると返ってくるデータが下記。

{
  user: {
    name: string,
    email: string,
    image: uri
  },
  expires: "YYYY-MM-DDTHH:mm:ss.SSSZ"
}

一番欲しいはずのaccessTokenがない・・。

callbacksを使ってaccessTokenを追加

session.jwtがtrueの場合はaccessTokenが含まれません。
そのため最初に紹介したoptionsで下記のようなcallbacksを追加します。


コメント頂いたので追記
GitHubのトークンをaccessTokenというキーで返却してしまっていますが、セッション管理のトークンとしての役割ではありません。(キー名がわかりにくい・・)



callbacks: {
  session: async (session, token) => {
    return Promise.resolve({
      ...session,
      accessToken: token.account.accessToken
    })
  }
}

callbacks.sessionはセッション情報を取得しようとしたときに呼ばれ、返すデータを変更することできます。

デフォルトでは引数のsessionをそのまま返すため、tokenに含まれるaccessTokenをデータへ含めるようにします。
(上記追記の通り)

引数のsessionとtokenはそれぞれの下記のようデータです。

■session


interface Session {
  user: {
    name: string
    email: string | null
    image: string
  }
  expires: string
}

■token

interface Token {
  user: {
    name: string
    email: string | null
    image: string
  }
  account: {
    provider: 'github'
    type: string
    id: number
    refreshToken?: string
    accessToken: string
    accessTokenExpires: string
  }
  iat: number
  expt: number
}

GitHubのscopeを設定

GitHubで欲しい情報に制限がかかっている場合はscopeを事前に設定した上でアクセストークンを取得する必要があります。

NextAuthでGitHub認証のscopeを設定するにはProviders.GitHubにscopeを追加します。


providers: [
  Providers.GitHub({
    clientId: process.env.GITHUB_ID,
    clientSecret: process.env.GITHUB_SECRET,
    scope: 'repo read:org'
  })
],

scopeの指定は文字列で複数指定する場合にはスペースをいれて並べることで指定可能です。

scopeの指定方法に注意

NextAuthのドキュメントでscopeの指定方法を見つけることができず、scopeの設定に苦戦してしまいました・・。

scopeは文字列で指定するのが正解ですが、配列で指定しても動いているような挙動になっていたんですよね。


scope: ['repo', 'read:org']

こんな感じです。
この指定方法では適切にscopeが設定されたトークンを取得できないので注意が必要です。

まとめ

わかってしまえばNextAuthはとても便利!という印象を受けましたが、ドキュメントのコードサンプルがもうちょっとあると嬉しいです。

(ちゃんとドキュメントを読んで、コードを読めばいいんですけど・・)

9
9
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?