How to set Supabase auth credentials in NodeJS?

70 views Asked by At

I'm attempting to break my supabase database interactions out of my client Flutter app and into it's own dedicated NodeJS express app. At the moment, I've attached the credentials from the logged in user into the header of my api requests (shown below).

In my nodeJS api, I am able to verify the jwt against the the secret key. However, I'm not sure how to set or inject the credentials into my NodeJS Supabase client. Consequently, the requests i'm sending to my database that require authenticated users to access are failing ... and I'm not sure what I'm doing wrong.

flutter request header (client)

// adding the accessToken from session to my header

final session = supabase.auth.currentSession;
final token = session?.accessToken;

final response = await http.get(
  Uri.parse(apiUrl),
  headers: {
    'Authorization': 'Bearer $token',
  },
);

nodeJS api middleware

// middleware to extract and validate access token

function authenticateToken(req, res, next) {
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1];

  if (token == null) return res.sendStatus(401);

  jwt.verify(
    token,
    "my-secret-key",
    (err, decodedToken) => {
      if (err) return res.sendStatus(403);
      // the token is decoded, if that matters
      console.log("decodedToken ===>", decodedToken);

      // at this point i'm spitballing random ideas, unsure...
      supabase.auth.getUser(decodedToken).then((r) => {
        req.user = r;
        return r;
      });
      next();
    }
  );
}
app.use("/locations", authenticateToken, locations);

where the database call occurs

async getRegionDetails(regionId: string) {
  const testing = await this.supabase.auth.getUser();

  console.log("testing", testing);

  const { data, error } = await this.supabase.from("regions").select();


  return data;
}

the error that returns:

error: AuthApiError: invalid claim: missing sub claim

1

There are 1 answers

0
kevin On

I did some sleuthing and found and found some answers.

In my case, I needed to add both the accessToken and refreshToken into my request header and then combined, the values are able to set the session for the request.

client

final session = supabase.auth.currentSession;
final token = session?.accessToken;
final refreshToken = session?.refreshToken;

final response = await http.get(
  Uri.parse(apiUrl),
  headers: {
    'Authorization': 'Bearer $token',
    'RefreshToken': '$refreshToken',
  },
);

server

...
const authHeader = req.headers["authorization"];
const refreshToken = req.headers["refreshtoken"];
const accessToken = authHeader && authHeader.split(" ")[1];
...
if (refreshToken && accessToken) {
  supabase.auth.setSession({
    access_token: accessToken,
    refresh_token: refreshToken,
  });
} else {
  throw new Error("User is not authenticated.");
}

helpful resources:

supabase docs

blog post