honojs-middleware/packages/auth-js
Mohit Khatri 8546d40cac
Merge f46705474f into e8512f0ee9
2025-04-02 20:44:03 +11:00
..
src test: move tests to src directory (#1075) 2025-03-28 18:50:19 +09:00
CHANGELOG.md Version Packages (#815) 2024-11-08 04:55:22 +09:00
README.md Merge f46705474f into e8512f0ee9 2025-04-02 20:44:03 +11:00
package.json build: typescript project references (#1077) 2025-04-02 18:28:02 +09:00
tsconfig.build.json build: typescript project references (#1077) 2025-04-02 18:28:02 +09:00
tsconfig.json build: typescript project references (#1077) 2025-04-02 18:28:02 +09:00
tsconfig.spec.json build: typescript project references (#1077) 2025-04-02 18:28:02 +09:00
vitest.config.ts test(workspace): upgrade to vitest v3 (#1009) 2025-03-12 12:52:15 +09:00

README.md

Auth.js middleware for Hono

codecov

This is a Auth.js third-party middleware for Hono.

This middleware can be used to inject the Auth.js session into the request context.

Installation

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

Configuration

Before starting using the middleware you must set the following environment variables:

AUTH_SECRET=#required
AUTH_URL=https://example.com/api/auth

How to Use

import { Hono } from 'hono'
import { authHandler, initAuthConfig, verifyAuth } from '@hono/auth-js'
import GitHub from '@auth/core/providers/github'

const app = new Hono()

app.use(
  '*',
  initAuthConfig((c) => ({
    secret: c.env.AUTH_SECRET,
    providers: [
      GitHub({
        clientId: c.env.GITHUB_ID,
        clientSecret: c.env.GITHUB_SECRET,
      }),
    ],
  }))
)

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

app.use('/api/*', verifyAuth())

app.get('/api/protected', (c) => {
  const auth = c.get('authUser')
  return c.json(auth)
})

export default app

React component

import { SessionProvider, useSession } from '@hono/auth-js/react'

export default function App() {
  return (
    <SessionProvider>
      <Children />
    </SessionProvider>
  )
}

function Children() {
  const { data: session, status } = useSession()
  return <div>I am {session?.user}</div>
}

Default /api/auth path can be changed to something else but that will also require you to change path in react app.

import { SessionProvider, authConfigManager, useSession } from '@hono/auth-js/react'

authConfigManager.setConfig({
  basePath: '/custom', // if auth route is diff from /api/auth
})

export default function App() {
  return (
    <SessionProvider>
      <Children />
    </SessionProvider>
  )
}

function Children() {
  const { data: session, status } = useSession()
  return <div>I am {session?.user}</div>
}

SessionProvider is not needed with react query.Use useQuery hook to fetch session data.

const useSession = () => {
  const { data, status } = useQuery({
    queryKey: ['session'],
    queryFn: async () => {
      const res = await fetch('/api/auth/session')
      return res.json()
    },
    staleTime: 5 * (60 * 1000),
    gcTime: 10 * (60 * 1000),
    refetchOnWindowFocus: true,
  })
  return { session: data, status }
}

For more details on how to Popup Oauth Login see example

Middleware

You can separate this code into another file, say auth.config.ts:

function getAuthConfig(c: Context): AuthConfig {
  return {
    secret: c.env.AUTH_SECRET,
    providers: [
      GitHub({
        clientId: c.env.GITHUB_ID,
        clientSecret: c.env.GITHUB_SECRET,
      }),
    ],
  }
}

Use the same config in middleware.ts

import { getAuthConfig } from '@/auth.config'
import { getAuthUser, initAuthConfig } from '@hono/auth-js'
import { Hono } from 'hono'
import { handle } from 'hono/vercel'
import { NextResponse } from 'next/server'

const app = new Hono()

// shared config
app.use('*', initAuthConfig(getAuthConfig))

app.all('*', async (c) => {
  // Retrieve the user & session
  const authUser = await getAuthUser(c)

  const pathname = new URL(c.req.url).pathname
  const isAuthenticated = !!authUser?.session

  // Specific to Auth.js (may vary if customized)
  const isApiAuthRoute = pathname.startsWith('/api/auth')

  const isPublicRoute = ['/'].includes(pathname)
  const isAuthRoute = ['/sign-in'].includes(pathname)

  if (isApiAuthRoute) return NextResponse.next()

  if (isAuthRoute) {
    if (isAuthenticated) {
      return Response.redirect(new URL('/protected', c.req.url))
    }
    return NextResponse.next()
  }

  if (!isAuthenticated && !isPublicRoute) {
    return Response.redirect(new URL('/sign-in', c.req.url))
  }

  return NextResponse.next()
})

export default handle(app)

export const config = {
  matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
}

Middleware setup repo: https://github.com/mohit4bug/nextjs-hono-authjs

Author

Divyam https://github.com/divyam234

Contributors