Hono on Cloudflare Workers with Better Auth always returning 401 Unauthorized

Using the better auth handler in the restricted endpoints like list sessions. It always returns unauthorized even after sign in with email. I'm using Scalar docs to test the api. The cookie is being set I've checked by logging it. But still it's returning unauthorized.
//auth.ts

import { betterAuth } from 'better-auth'
import { mongodbAdapter } from 'better-auth/adapters/mongodb'
import {
admin,
apiKey,
bearer,
jwt,
openAPI,
organization,
} from 'better-auth/plugins'
import DBClient from './db'

export const auth = () => {
const client = DBClient.getClient()
const db = client.db('__appflare__')
return betterAuth({
basePath: '/api/v1/auth',
database: mongodbAdapter(db),
emailAndPassword: {
enabled: true,
},
user: {
additionalFields: {
teamId: {
type: 'string',
required: false,
references: {
model: 'team',
field: 'id',
},
},
roles: {
type: 'string',
required: false,
},
tenantId: {
type: 'string',
required: false,
},
},
},
plugins: [
jwt(),
bearer(),
apiKey(),
organization(),
admin({
adminRoles: ['__superadmin__'],
}),
openAPI(),
],
})
}

type AuthType = ReturnType<typeof auth>['$Infer']
type UserType = AuthType['Session']['user'] | null
type SessionType = AuthType['Session']['session'] | null
export type HonoVariables = {
Variables: {
user: UserType
session: SessionType
}
}
//auth.ts

import { betterAuth } from 'better-auth'
import { mongodbAdapter } from 'better-auth/adapters/mongodb'
import {
admin,
apiKey,
bearer,
jwt,
openAPI,
organization,
} from 'better-auth/plugins'
import DBClient from './db'

export const auth = () => {
const client = DBClient.getClient()
const db = client.db('__appflare__')
return betterAuth({
basePath: '/api/v1/auth',
database: mongodbAdapter(db),
emailAndPassword: {
enabled: true,
},
user: {
additionalFields: {
teamId: {
type: 'string',
required: false,
references: {
model: 'team',
field: 'id',
},
},
roles: {
type: 'string',
required: false,
},
tenantId: {
type: 'string',
required: false,
},
},
},
plugins: [
jwt(),
bearer(),
apiKey(),
organization(),
admin({
adminRoles: ['__superadmin__'],
}),
openAPI(),
],
})
}

type AuthType = ReturnType<typeof auth>['$Infer']
type UserType = AuthType['Session']['user'] | null
type SessionType = AuthType['Session']['session'] | null
export type HonoVariables = {
Variables: {
user: UserType
session: SessionType
}
}
Solution:
Fixed it by transforming the headers when passing to the routes ``` export const getHeaders = (headers: Headers) => { const newHeaders = Object.fromEntries(headers as any) const headerObject: Record<string, any> = {}...
Jump to solution
2 Replies
Imtiaj
ImtiajOP2w ago
//auth.route.ts
import { Hono } from 'hono'
import { auth } from 'lib/auth'

const authRoute = new Hono().on(['POST', 'GET'], '/*', (c) => {
return auth().handler(c.req.raw)
})
export default authRoute
//auth.route.ts
import { Hono } from 'hono'
import { auth } from 'lib/auth'

const authRoute = new Hono().on(['POST', 'GET'], '/*', (c) => {
return auth().handler(c.req.raw)
})
export default authRoute
//app.ts
import { OpenAPIHono } from '@hono/zod-openapi'
import { auth, HonoVariables } from 'lib/auth'
import authRoute from 'routes/auth.route'
import databaseRoute from 'routes/database.route'

import { cors } from 'hono/cors'
import { getHeaders } from 'lib/header'
const app = new OpenAPIHono<HonoVariables>()
.basePath('/api/v1')
.route('/auth', authRoute)
export default app
//app.ts
import { OpenAPIHono } from '@hono/zod-openapi'
import { auth, HonoVariables } from 'lib/auth'
import authRoute from 'routes/auth.route'
import databaseRoute from 'routes/database.route'

import { cors } from 'hono/cors'
import { getHeaders } from 'lib/header'
const app = new OpenAPIHono<HonoVariables>()
.basePath('/api/v1')
.route('/auth', authRoute)
export default app
when using
auth.api.getSession
auth.api.getSession
directly by sending the headers with
c.req.raw.headers
c.req.raw.headers
also is not returning the session It seems it has something to do with cloudflare workers + headers issue. Tried same code on node it seemed to work perfectly
Solution
Imtiaj
Imtiaj2w ago
Fixed it by transforming the headers when passing to the routes
export const getHeaders = (headers: Headers) => {
const newHeaders = Object.fromEntries(headers as any)
const headerObject: Record<string, any> = {}
for (const key in newHeaders) {
const isAuthorization =
key.toLowerCase() === 'authorization' && newHeaders[key]?.Length > 7
if (isAuthorization) {
if (key !== 'cookie') {
headerObject[key] = newHeaders[key]
}
} else {
if (key !== 'authorization') {
headerObject[key] = newHeaders[key]
}
}
}

return headerObject as any as Headers
}
export const getHeaders = (headers: Headers) => {
const newHeaders = Object.fromEntries(headers as any)
const headerObject: Record<string, any> = {}
for (const key in newHeaders) {
const isAuthorization =
key.toLowerCase() === 'authorization' && newHeaders[key]?.Length > 7
if (isAuthorization) {
if (key !== 'cookie') {
headerObject[key] = newHeaders[key]
}
} else {
if (key !== 'authorization') {
headerObject[key] = newHeaders[key]
}
}
}

return headerObject as any as Headers
}

Did you find this page helpful?