34
17

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 1 year has passed since last update.

面倒なログインはNextAuthにやらせよう

Last updated at Posted at 2023-04-19

social-media-card.png

前書き

いつからでしょうか:sweat_smile:、何か新しいサービスを試す際に、GoogleアカウントやGitHubアカウントを利用してログインするしかやらなくなった。

ユーザーネームとパスワードを設定し:writing_hand_tone1:、メール認証を済ませて初めて利用可能になるようなサービスは自分でも嫌なので、多くの人にとっても面倒でしょう、これからサービス作る際に、いっそう認証周り全部OAuthに任せようと思いました。

いろいろ調べた結果、最終的にNextAuthに辿り着きました。

NextAuthとは

公式ドキュメント

NextAuthとは何か?とChatGPTに尋ねたら、以下のような回答が返ってきました。
1C05E983-470A-449E-A03A-4B3B56827E2D_4_5005_c.jpeg

大まか合ってますが、現時点ではSvelteKit, SolidStartでも利用することができるらしいです。

NextAuthの使い方

NextAuthの使い方は非常にシンプルです、Next.js制のプロジェクトでは三つのステップで基本形ができます。

  • NextAuthインストール
npm install next-auth or yarn add next-auth
  • 認証プロバイダーを設定する

認証プロバイダーを設定することによって、ユーザーがログインする方法を決められます。
たとえば、GitHub、Google、Facebook、TwitterなどのOAuthプロバイダーを使用できます。
次のように、pages/api/auth/[...nextauth].jsというファイルを作成して、認証プロバイダーとsecretを設定します。
secretの値は下記のコマンドで生成できます、セキュリティに関連する目的に使用されるため、設定しないとエラーになる可能性があります。

openssl rand -base64 32
pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github';

export default NextAuth({
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],
 secret: process.env.SECRET,
})

Githubのプロバイダを設定した場合、下記のURlにアクセスして、新規OAuth Appを作る必要がある、New OAuth Appから作れる。
https://github.com/settings/developers

E7CEFE09-0A72-4515-A3BC-BA0A2907F8A0_4_5005_c.jpeg

Application nameHomepage URLcallback URL 指定すればClient IDClient secretsを取得できる。

FA13B752-7EC6-4614-A9C1-93D14886222F.jpeg

Homepage URL指定したURLは.envに追加する、定義しなければhttp://localhost:3000/になる。

.env
NEXTAUTH_URL=http://localhost:3002/

他のプロバイダ使用する場合も手順が大体同じ。

  • 認証機能をアプリケーションに実装する

最後に、認証機能をアプリケーションに実装する必要があります。たとえば、ユーザーがログインしているかどうかを確認するために、useSessionというNext.jsのフックを使用できます。次のように、pages/index.jsというファイルにuseSessionをインポートして使用します。

/pages/_app.jsx
import { SessionProvider } from "next-auth/react"

export default function App({
  Component, pageProps: { session, ...pageProps }
}) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps}/>
    </SessionProvider>
  )
}

ログインするためにsignInメソッドも用意されてます、プロバイダ指定してログインする場合、プロバイダー名をパラメーターとして渡すことができます、signIn('github')

/pages/index.tsx
import { useSession, signIn, signOut } from "next-auth/react"

export default function Home() {
  const { data: session } = useSession()
  if(session) {
    return <>
      Signed in as {session.user.email} <br/>
      <button onClick={() => signOut()}>Sign out</button>
    </>
  }
  return <>
    Not signed in <br/>
    <button onClick={() => signIn()}>Sign in</button>
  </>
}

この状態でサーバーを立ち上げると、下記の画面が表示されます。

1C6CCBF0-FA1C-42A6-9FD7-6FE4CA712BFD_4_5005_c.jpeg
Sign inボタンをクリックすればgithub用のOAuthログイン画面が表示されます。
3F74D54D-2332-46D8-A740-C9BE1F40A227.jpeg
クリックすれば、githubのOAuthログイン画面にリダイレクトされて、許可すれば、ホームページにまたリダイレクトされます。
2DDCE51A-BFAA-4219-8278-7C9BBFF8D23E.jpeg
githubに登録されてメールアドレスが表示されることが確認できたら、実装完了です。
E2B4525B-824A-4677-9A07-ADC6D8924804_4_5005_c.jpeg

データベース使用する場合

先ほどのログインはセッションにユーザー情報を保存してましたが、データベースに保存することもできます。
その場合、NextAuthが期待するテーブル構造を用意してあげる必要があります。
詳細は公式ドキュメントを参照してください。
5B492A7C-166A-46A4-9556-9B3E94A130EA.jpeg
prisma使用する場合、モデルの定義は下記の記述になります。

model Account {
  id                 String  @id @default(cuid())
  userId             String
  type               String
  provider           String
  providerAccountId  String
  refresh_token      String?  @db.Text
  access_token       String?  @db.Text
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?  @db.Text
  session_state      String?
  oauth_token_secret String?
  oauth_token        String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}
34
17
0

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
34
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?