caleb
caleb
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I made sure jwt and secret are both set. I even logged it to make sure
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I verified that jwt and secret in the providers code are not null or blank, which is what it looks like the error I'm getting would be caused by. I also confirmed they're the exact same from when the JWT is being signed.
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I was using middleware to parse and validate the auth cookie but needed to use Prisma. I had issues adding Prisma to edge runtime so I instead moved it over to my providers.tsx file. Discord isn't letting me post the code for some reason so here's a Hastebin link with the providers code: https://hastebin.com/share/enomewaken.javascript
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
Here's the /src/app/api/sign/route.ts file:
import { NextResponse } from 'next/server'
import { api } from '~/trpc/server'
import * as jose from 'jose'
import { env } from '~/env'

export async function GET(req: Request, { params }: { params: { token: string } }) {
const token = params.token

const { message } = await api.authentication.verifyUserAuthenticationTokenCode({ token })

if (message === 'not_found') {
return NextResponse.redirect(new URL('/signin?message=code_not_found', req.url))
} else if (message === 'expired') {
return NextResponse.redirect(new URL('/signin?message=code_expired', req.url))
} else if (message === 'verified') {
const secret = new TextEncoder().encode(env.JWT_SECRET)

const user = await api.user.getUserByAuthToken({ token })

if (!user) {
return NextResponse.redirect(new URL('/signin?message=user_not_found', req.url))
}

const jwt = await new jose.SignJWT().setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setIssuer('urn:caaampus:issuer').setAudience('urn:caaampus:audience').setSubject(JSON.stringify(user.id)).setExpirationTime('72h').sign(secret)

const response = NextResponse.redirect(new URL('/profile', req.url))
response.cookies.set('Authorization', jwt, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/',
expires: new Date(Date.now() + 72 * 60 * 60 * 1000)
})

return response
}
}
import { NextResponse } from 'next/server'
import { api } from '~/trpc/server'
import * as jose from 'jose'
import { env } from '~/env'

export async function GET(req: Request, { params }: { params: { token: string } }) {
const token = params.token

const { message } = await api.authentication.verifyUserAuthenticationTokenCode({ token })

if (message === 'not_found') {
return NextResponse.redirect(new URL('/signin?message=code_not_found', req.url))
} else if (message === 'expired') {
return NextResponse.redirect(new URL('/signin?message=code_expired', req.url))
} else if (message === 'verified') {
const secret = new TextEncoder().encode(env.JWT_SECRET)

const user = await api.user.getUserByAuthToken({ token })

if (!user) {
return NextResponse.redirect(new URL('/signin?message=user_not_found', req.url))
}

const jwt = await new jose.SignJWT().setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setIssuer('urn:caaampus:issuer').setAudience('urn:caaampus:audience').setSubject(JSON.stringify(user.id)).setExpirationTime('72h').sign(secret)

const response = NextResponse.redirect(new URL('/profile', req.url))
response.cookies.set('Authorization', jwt, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/',
expires: new Date(Date.now() + 72 * 60 * 60 * 1000)
})

return response
}
}
7 replies