Open5

NextAuth.js を触ってみる

izuchyizuchy

NextAuth.js

  • OAuth service, it supports OAuth 1.0, 1.0A, 2.0 and OpenID Connect をサポート
  • 多くの認証プロバイダーをサポート
  • 電子メール、パスワードレス認証をサポート
  • Active Directory、LDAP などのステートレス認証をサポート
  • JWT や データベースセッションをサポート
  • AWS Lambda、Docker、Heroku などのサーバーレス環境で動作するように設計されている
  • MySQL, MariaDB, Postgres, SQL Server, MongoDB and SQLite をビルトインサポート
  • データベースなしでも仕様可能
  • あらゆるデータベースと併用可能
  • デフォルトでセキュア

Next.js に NextAuth.js を組み込む

  1. pages/api/auth[...nextauth].js を作成する
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"

export default NextAuth({
  // Configure one or more authentication providers
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    // ...add more providers here
  ],
})

上記ルーティングにファイルを置くことで、api/auth/* へのすべてのリクエスト(signIn、callback、signOutなど)は、自動的に NextAuth.js によって処理されるようになります。

認証プロバイダを追加する方法について

izuchyizuchy

一般的な OAuth のフロー

ビルトイン OAuth 認証プロバイダーの使い方

  1. 該当の認証プロバイダーの開発者ポータルでアプリケーションを登録する
  2. リダイレクト URL は /api/auth/callback/[provider] のフォーマットに従う
  3. .env ファイルをルートに作成する
TWITTER_ID=YOUR_TWITTER_CLIENT_ID
TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET
  1. pages/api/auth/[...nextauth].js に使用したい認証プロバイダーを追加する
import TwitterProvider from "next-auth/providers/"
...
providers: [
  TwitterProvider({
    clientId: process.env.TWITTER_ID,
    clientSecret: process.env.TWITTER_SECRET
  })
],// 配列に認証プロバイダーを追加する
...
  1. プロバイダーの設定が完了すると、/api/auth/signin でサインインすることができる
izuchyizuchy

Twitter 認証を行う例

該当の認証プロバイダーの開発者ポータルでアプリケーションを登録する

Twitter の場合は、Developer Portal 上からアプリを作成できる
https://developer.twitter.com/en/portal/projects-and-apps

  • process.env.TWITTER_ID つまり clientId は API Key
  • process.env.TWITTER_SECRET つまり clientSecret は API Key Secret

を設定する

リダイレクト URL は /api/auth/callback/[provider] のフォーマットに従う

callback 先は、ローカル環境の Next.js の URL を設定する
http://localhost:3000/api/auth/callback/twitter

callback 先を設定するには、3-legged OAuth を有効にする必要がある

pages/api/auth/[...nextauth].ts に使用したい認証プロバイダーを追加する

 export default NextAuth({
  providers: [
    Providers.Twitter({
      clientId: process.env.TWITTER_CLIENT_ID,
      clientSecret: process.env.TWITTER_CLIENT_SECRET
    })
  ],
})

プロバイダーの設定が完了すると、/api/auth/signin でサインインすることができる

import {signIn, signOut, useSession} from "next-auth/client";
// 略
<Button onClick={()=>signIn()}>ログイン</Button>

siginIn() すると NextAuth のログイン画面を経由して、Twitter のログイン画面が表示される

ユーザーから見た画面遷移

    const [session, loading] = useSession();
    console.log(session);

認証を通すと、session から以下のようなユーザー情報が取得できる

{
    "user": {
        "name": "izuchy | UI でワクワクしたいエンジニア",
        "email": null,
        "image": "https://pbs.twimg.com/profile_images/1460468685269733379/tvbUktX1.png"
    },
    "expires": "2021-12-25T06:30:36.608Z"
}
izuchyizuchy

LINE 認証を行う例

アプリの作成

https://developers.line.biz/console/
から LINE ログインのアプリを作成する

Provider の追加

pages/api/auth/[...nextauth].ts に LINE の Provider を追加する

 export default NextAuth({
  providers: [
    Providers.LINE({
      clientId: process.env.LINE_CLIENT_ID,
      clientSecret: process.env.LINE_CLIENT_SECRET
    })
  ],
})

.env の設定

  • LINE_CLIENT_ID は チャネルID
  • LINE_CLIENT_SECRET は チャネルシークレット

を設定する

LINE ログインする

<Button onClick={()=>signIn("line")}>LINE ログイン</Button>

LINE のログイン画面が表示され許可すると、ログインできる

認証を通すと、session から以下のようなユーザー情報が取得できる

{
    "user": {
        "name": "Izuchi Takahiro",
        "email": null,
        "image": "https://profile.line-scdn.net/ch/v2/p/u4389e516fcb74cde112e54b1eea25fe9/1350387500003"
    },
    "expires": "2021-12-25T07:53:16.489Z"
}
izuchyizuchy

REST API で使われている各エンドポイントについて

GET /api/auth/signin

  • サインイン画面を表示する

POST /api/auth/signin/:provider

  • 指定したプロバイダーの OAuth のサインインを開始
  • /api/auth/csrf で取得した CSRF トークンが必要

GET /api/auth/callback/:provider

  • OAuth の認証プロバイダーから返ってくるリクエストを処理する
  • state オプションをサポートしている OAuth 2.0 プロバイダの場合、state パラメーターはサインインフローが開始されたときのものと照合する

GET /api/auth/signout

  • サインアウトページを表示する

POST /api/auth/signout

  • サインアウトとの処理
  • 悪意のあるリンクでユーザーの同意無しにサインアウトが行われることを防ぐための POST リクエスト
  • /api/auth/csrf で取得した CSRF トークンが必要

GET /api/auth/session

  • セッションオブジェクトを応答する
  • 応答されるセッションオブジェクトの内容は callback の設定で設定可能

GET /api/auth/csrf

  • CSRF トークンを返す
  • NextAuth.js は、すべての認証ルートに CSRF 対策が行われている
  • 「ダブルサブミットクッキー方式」という方法
  • 署名入り HTTPOnly、ホストオンリーのクッキーを使用
  • CSRF トークンは POST 送信時に csrfToken というフォーム変数で渡す必要がある

GET /api/auth/providers

  • 設定されている OAuth のサービスリスト、サービスの詳細(サインインやコールバック URL)などを返す
  • 動的にカスタムサインアップページを作ったり、設定されているコールバック URL の確認が可能