Issue #947
Sometimes Row Level Security is not enough and we want to do all logic server side, then we need a way for the server to get hold onto current user token.
Send JWT token in Authorization header
From client, we can get session
from supabase auth, then send that as Bearer
in Authorization
header
const session = await supabase.auth.getSession().data.session
const token = session.access_token
const response = await fetch(url, {
'GET',
headers: {
Authorization: `Bearer ${token}`
}
})
Decode token
From the nextjs API Route, we can handle all auth logic in middleware. We will use jwt-decode to decode token
src/middleware.ts
import { NextRequest, NextResponse } from "next/server"
import jwt_decode from 'jwt-decode'
export function middleware(request: NextRequest) {
const res = NextResponse.next()
const authorization = request.headers.get('Authorization')
const token = authorization?.split(' ')[1] || ''
const decodedToken = jwt_decode(token) as any
const userId = decodedToken.sub
return res
}
export const config = {
matcher: "/api/:path*",
}
The decoded object looks like this, where sub
, meaning subject, is usually the user id
{
"aud": "authenticated",
"exp": 1615824388,
"sub": "0334744a-f2a2-4aba-8c8a-6e748f62a172",
"email": "d.l.solove@gmail.com",
"app_metadata": {
"provider": "email"
},
"user_metadata": null,
"role": "authenticated"
}
With the user id, we can query Supabase Postgres database to check if this user is valid or not
Validate token
To validate json token, we can use the JWT Secret from Supabase to verify, using jsonwebtoken
package
import jwt, { type JwtPayload } from 'jsonwebtoken';
const token = authorization.split('Bearer ').pop()
const user = jwt.verify(token, process.env.SUPABASE_JWT_SECRET) as JwtPayload
user.id = user.sub
Get user
In the server, we get initiate createClient
with service role key, and call auth.getUser(jwt)
to get user
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY, {
auth: {
autoRefreshToken: false,
persistSession: false,
}
})
const authorization = request.headers.get("Authorization")!
const token = authorization.split("Bearer ").pop()
const user = await supabase.auth.getUser(token)