Skip to content

Commit

Permalink
refactor(auth-js): restructure getSession and streamline configuratio…
Browse files Browse the repository at this point in the history
…n handling

- Refactored getSession based on https://github.com/nextauthjs/next-auth/blob/main/packages/frameworks-express/src/index.ts for improved alignment.
- Replaced redundant Env handling with @auth/core's setEnvDefaults for cleaner configuration.
- Removed redundant configuration checks already handled in @auth/core.
  • Loading branch information
catnaut committed Nov 9, 2024
1 parent f3b3a8e commit 80dbcec
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 45 deletions.
72 changes: 29 additions & 43 deletions packages/auth-js/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { AuthConfig as AuthConfigCore } from '@auth/core'
import { Auth } from '@auth/core'
import { Auth, createActionURL } from '@auth/core'
import type { AdapterUser } from '@auth/core/adapters'
import type { JWT } from '@auth/core/jwt'
import type { Session } from '@auth/core/types'
import type { Context, MiddlewareHandler } from 'hono'
import { env } from 'hono/adapter'
import { HTTPException } from 'hono/http-exception'
import { setEnvDefaults as coreSetEnvDefaults } from '@auth/core'
import { setEnvDefaults } from '@auth/core'

declare module 'hono' {
interface ContextVariableMap {
Expand All @@ -32,61 +32,55 @@ export interface AuthConfig extends Omit<AuthConfigCore, 'raw'> {}

export type ConfigHandler = (c: Context) => AuthConfig

export function setEnvDefaults(env: AuthEnv, config: AuthConfig) {
config.secret ??= env.AUTH_SECRET
coreSetEnvDefaults(env, config)
}


export async function getAuthUser(c: Context): Promise<AuthUser | null> {
export async function getAuthUser(c: Context) {
const ctxEnv = env(c)
const config = c.get('authConfig')
const ctxEnv = env(c) as AuthEnv
setEnvDefaults(ctxEnv, config)
const authReq = c.req.raw
const origin = new URL(authReq.url).origin
const request = new Request(`${origin}${config.basePath}/session`, {
headers: { cookie: c.req.header('cookie') ?? '' },
})
const req = c.req.raw

const url = createActionURL('session', new URL(req.url).protocol, req.headers, ctxEnv, config)

let authUser: AuthUser = {} as AuthUser

const response = (await Auth(request, {
...config,
callbacks: {
...config.callbacks,
async session(...args) {
authUser = args[0]
const session = (await config.callbacks?.session?.(...args)) ?? args[0].session
const user = args[0].user ?? args[0].token
return { user, ...session } satisfies Session
const response = await Auth(
new Request(url, { headers: { cookie: req.headers.get('cookie') ?? '' } }),
{
...config,
callbacks: {
...config.callbacks,
async session(...args) {
authUser = args[0]
const session = (await config.callbacks?.session?.(...args)) ?? args[0].session
const user = args[0].user ?? args[0].token
return { user, ...session } satisfies Session
},
},
},
})) as Response
}
)

const session = (await response.json()) as Session | null

return session?.user ? authUser : null
}

/**
* A utility middleware to verify the session of the incoming request by getAuthUser under the hood.
* If unauthorized, it will throw a 401 Unauthorized error.
*/
export function verifyAuth(): MiddlewareHandler {
return async (c, next) => {
const authUser = await getAuthUser(c)
const authUser = c.get('authUser') ?? (await getAuthUser(c))
const isAuth = !!authUser?.token || !!authUser?.user
if (!isAuth) {
const res = new Response('Unauthorized', {
status: 401,
})
throw new HTTPException(401, { res })
}
if (!isAuth) throw new HTTPException(401, { message: 'Unauthorized' })
c.set('authUser', authUser)

await next()
}
}

export function initAuthConfig(cb: ConfigHandler): MiddlewareHandler {
return async (c, next) => {
const config = cb(c)
const ctxEnv = env(c) as AuthEnv
setEnvDefaults(ctxEnv, config)
c.set('authConfig', config)
await next()
}
Expand All @@ -95,14 +89,6 @@ export function initAuthConfig(cb: ConfigHandler): MiddlewareHandler {
export function authHandler(): MiddlewareHandler {
return async (c) => {
const config = c.get('authConfig')
const ctxEnv = env(c) as AuthEnv

setEnvDefaults(ctxEnv, config)

if (!config.secret || config.secret.length === 0) {
throw new HTTPException(500, { message: 'Missing AUTH_SECRET' })
}

const res = await Auth(c.req.raw, config)
return new Response(res.body, res)
}
Expand Down
5 changes: 3 additions & 2 deletions packages/auth-js/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import { authHandler, verifyAuth, initAuthConfig } from '../src'
global.crypto = webcrypto

describe('Config', () => {
it('Should return 500 if AUTH_SECRET is missing', async () => {
test('Should return 500 if AUTH_SECRET is missing', async () => {
globalThis.process.env = { AUTH_SECRET: '' }
const app = new Hono()

app.use(
'/*',
initAuthConfig(() => {
return {
basePath: "/api/auth",
providers: [],
}
})
Expand All @@ -28,7 +29,7 @@ describe('Config', () => {
const req = new Request('http://localhost/api/auth/signin')
const res = await app.request(req)
expect(res.status).toBe(500)
expect(await res.text()).toBe('Missing AUTH_SECRET')
expect(await res.text()).include("There is a problem with the server configuration.")
})

it('Should return 200 auth initial config is correct', async () => {
Expand Down

0 comments on commit 80dbcec

Please sign in to comment.