How to grab access token from getClaims call?

Good afternoon, I was wondering if it's possible to get a users access token from a getClaims call. I'm working on an API call that sends off a request to Inngest to run some background tasks. In one of the steps I need to create the client with the access token to update data for the user. Since this is all server side, I don't want to use getSession on the server as it's not recommended. Is there a better way to handle this? My API that sends the request to Inngest:
import { NextResponse } from 'next/server'
import { inngest } from '@/lib/inngest/client'
import { createClient } from '@/lib/supabase/server'

export async function POST(req: Request) {
try {
const supabase = await createClient()

const { data: claimsData, error: authError } = await supabase.auth.getClaims()

if (authError || !claimsData?.claims) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

const { data: sessionData, error: sessionError } = await supabase.auth.getSession()

if (sessionError || !sessionData || !sessionData.session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

const body = await req.json()
const { fileData, fileType } = body

if (!fileData || !fileType) {
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })
}

await inngest.send({
name: 'process',
data: {
fileData,
fileType,
userId: claimsData.claims.sub,
accessToken: sessionData.session.access_token,
},
})

return NextResponse.json({
success: true,
message: 'Processing started',
})
} catch (error) {
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
import { NextResponse } from 'next/server'
import { inngest } from '@/lib/inngest/client'
import { createClient } from '@/lib/supabase/server'

export async function POST(req: Request) {
try {
const supabase = await createClient()

const { data: claimsData, error: authError } = await supabase.auth.getClaims()

if (authError || !claimsData?.claims) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

const { data: sessionData, error: sessionError } = await supabase.auth.getSession()

if (sessionError || !sessionData || !sessionData.session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

const body = await req.json()
const { fileData, fileType } = body

if (!fileData || !fileType) {
return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })
}

await inngest.send({
name: 'process',
data: {
fileData,
fileType,
userId: claimsData.claims.sub,
accessToken: sessionData.session.access_token,
},
})

return NextResponse.json({
success: true,
message: 'Processing started',
})
} catch (error) {
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
6 Replies
garyaustin
garyaustin6d ago
The JWT is the access token. So if getClaims works then the access token is valid.
Vikram
VikramOP6d ago
I see thank you. Just to follow up on this with more context, I am trying to send the JWT to the Inngest environment to create the client. Maybe I'm just not understanding which field of the getClaims response is the proper JWT to use here.
export default inngest.createFunction(
{ id: 'process' },
{ event: 'process' },
async ({ event, step }) => {
const { fileData, fileType, userId, accessToken } = event.data

if (!fileData || !fileType) {
throw new Error('No fileData or fileType provided in event payload')
}

const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL
const SUPABASE_ANON_KEY = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY

if (!SUPABASE_URL || !SUPABASE_ANON_KEY) {
throw new Error('Missing Supabase environment variables')
}

const supabase = createBrowserClient<Database>(SUPABASE_URL, SUPABASE_ANON_KEY, {
accessToken: () => accessToken,
})
export default inngest.createFunction(
{ id: 'process' },
{ event: 'process' },
async ({ event, step }) => {
const { fileData, fileType, userId, accessToken } = event.data

if (!fileData || !fileType) {
throw new Error('No fileData or fileType provided in event payload')
}

const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL
const SUPABASE_ANON_KEY = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY

if (!SUPABASE_URL || !SUPABASE_ANON_KEY) {
throw new Error('Missing Supabase environment variables')
}

const supabase = createBrowserClient<Database>(SUPABASE_URL, SUPABASE_ANON_KEY, {
accessToken: () => accessToken,
})
garyaustin
garyaustin6d ago
GetClaims is provided the JWT. Default it used the JWT from the user session. That is where the claims come from.
Vikram
VikramOP6d ago
So this case sending access_token back to create the client is fine since getClaims was successful prior to that
garyaustin
garyaustin6d ago
Probably was fine anyway. If you just use Supabase-js to make calls with it , verification happens when you hit the REST API.
Vikram
VikramOP6d ago
Awesome, thanks for your help Gary!

Did you find this page helpful?