🔒

Auth.jsを使ってHonoにGoogle認証を設定する

2024/12/08に公開

はじめに

みなさんHono使っていますか?
わたしは実務でHonoを使っています!好きなHonoの機能はRPCです

https://hono.dev/

わたし的に、Honoは触っていて楽しいので、Honoだけで完結させたくなるときがあります
今、小さいアプリをHonoで作成しているのですが、簡単にGoogle認証を設定できたので、この記事ではその手順を紹介します

基本は、サードパーティミドルウェアであるAuth.js middleware for Honoを使うだけです

実践

Hono

まずは、Honoアプリを作成します

npm create hono@latest

今回は、Node.js向けに作成しました

index.ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

const port = 3000
console.log(`Server is running on http://localhost:${port}`)

serve({
  fetch: app.fetch,
  port
})

npm run devして http://localhost:3000/ にアクセスすると、Honoが動作している様子が確認できます

Google OAuth 2.0 クライアント

Google CloudコンソールからOAuth 2.0 クライアントを作成し、次を設定しておきます

  • 承認済みの JavaScript 生成元: http://localhost:3000
  • 承認済みのリダイレクト URL: http://localhost:3000/api/auth/callback/google

また、次を取得しておきます

  • クライアントID
  • クライアントシークレット

Auth.js middleware for Hono

では、Auth.js middleware for Honoを設定します

まずは、必要なライブラリをインストールします

npm i @hono/auth-js @auth/core

.envファイルを作成し、必要な環境変数を記述します

.env
AUTH_SECRET=<openssl rand -base64 32で生成したランダムな文字列>
AUTH_URL=http://localhost:3000/api/auth
AUTH_GOOGLE_ID=<先ほど取得したクライアントID>
AUTH_GOOGLE_SECRET=<先ほど取得したクライアントシークレット>

Hono自体はNext.jsのように.envファイルを読み込む機能は提供していないので、dotenvを使って.envファイルを読み込みます

npm i dotenv
index.ts
import 'dotenv/config'

Auth.jsを初期設定します

index.ts
app.use(
  '*',
  initAuthConfig((c) => ({
    secret: c.env.AUTH_SECRET,
    providers: [
      Google,
    ],
  }))
)

認証に必要なハンドラーを登録します

index.ts
app.use('/api/auth/*', authHandler())

認証していないリクエストが来た場合、401エラーとするハンドラーを登録します
今回は、全てのページで認証を必須とします

index.ts
app.use('*', verifyAuth())

認証していないリクエストが来た場合、サインインページにリダイレクトするようにします

index.ts
app.onError((err, c) => {
  if (err instanceof HTTPException && err.status === 401) {

    return c.redirect('/api/auth/signin')
  }

  return c.text('Other Error', 500)
})

サインインしているユーザの情報は、c.get('authUser')で取得できます

index.ts
app.get('/', (c) => {
  const auth = c.get('authUser')

  return c.text(`Hello, ${auth.session.user?.name}`)
})

コード全体はこちらです

index.ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'
import { authHandler, initAuthConfig, verifyAuth } from '@hono/auth-js'
import Google from '@auth/core/providers/google'
import 'dotenv/config'

const app = new Hono()

app.use(
  '*',
  initAuthConfig((c) => ({
    secret: c.env.AUTH_SECRET,
    providers: [
      Google,
    ],
  }))
)

app.onError((err, c) => {
  if (err instanceof HTTPException && err.status === 401) {

    return c.redirect('/api/auth/signin')
  }

  return c.text('Other Error', 500)
})

app.use('/api/auth/*', authHandler())

// 全てのページで認証を必須にする
app.use('*', verifyAuth())

app.get('/', (c) => {
  const auth = c.get('authUser')

  return c.text(`Hello, ${auth.session.user?.name}`)
})

const port = 3000
console.log(`Server is running on http://localhost:${port}`)

serve({
  fetch: app.fetch,
  port
})

動作確認

実際に動作確認してみましょう

http://localhost:3000 にアクセスすると、http://localhost:3000/api/auth/signin にリダイレクトされます

ここでサインインすると、http://localhost:3000 に遷移し、ユーザ情報が取得できていることが確認できます

HonoにGoogle認証を設定することができました 🎉

おわりに

とてもシンプルなコードで、HonoでAuth.jsを利用してGoogle認証を設定することができました
Honoで小さなアプリをシュッと作るときに便利そうですね!

今回のコードはこちらに置いてあります

https://github.com/hirokisakabe/hono-authjs-sample

ちなみにHonoだけでなくReactも含めたコードサンプルは、次が参考になります

https://github.com/divyam234/next-auth-hono-react

Discussion