Clerk auth + GraphQL resolver + current user

I’m trying to get the current user ID in a GraphQL resolver.

I’ve created a SDL and service for a me field.

The resolver is defined as:

export const me: QueryResolvers['me'] = async (args, { context }) => {
  return { id: context.currentUser.id }
}

context.currentUser is undefined. Any way I can do this? Thanks!

Possible duplicate/related issue for awareness: Redwood v7.0.0 Upgrade Guide - #66 by n1tsua

1 Like

Hi @willmruzek as @Grayson noted, the request needs to be authenticated such that the context is populated.

in your me GraphQL query operation did you set @requrieAuth and that auth provider are you using?

If in

export const me: QueryResolvers['me'] = async (args, { context }) => {
  return { id: context.currentUser.id }
}

the request isn’'t authenticated, then the currentUser won’t exist on the context. In that case where you are trying to get authenticated info in a not authenticated request, you can:

import { AuthenticationError } from '@redwoodjs/api'

export const me: QueryResolvers['me'] = async (args, { context }) => {
  if (context.currentUser) {
    return { id: context.currentUser.id }
 }

 throw new AuthenticationError('Not allowed')
}
1 Like

Hi dthyresson @grayson, it appears I didn’t @requireAuth on the me resolver. I’m now able to access context.currentUser.id.

One thing I’m noticing is that id on currentUser is on the current user type. It’d be nice to have that somehow.

Thank you both!

@willmruzek Glad it’s working!

As for the type of the CurrentUser that can depend on your implementation. For example, in Supabase the auth lib ships as:

/**
 * Represents the user attributes returned by the decoding the
 * Authentication provider's JWT together with an optional list of roles.
 */
type RedwoodUser = Record<string, unknown> & { roles?: string[] }

/**
 * ........ 
 * @returns RedwoodUser
 */
export const getCurrentUser = async (
  decoded,
  /* eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars */
  { token, type },
  /* eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars */
  { event, context }
): Promise<RedwoodUser> => {
  if (!decoded) {
    return null
  }

  const { roles } = parseJWT({ decoded })

  if (roles) {
    return { ...decoded, roles }
  }

  return { ...decoded }
}```

So, `getCurrentUser` is typed as a `RedwoodUser`. Which for Supabase is an object of JWT claims (plus role moved to top level).

Depending our what you return from `getCurrentUser` would should be able to type it and -- I think -- have `id ` and other properties available to you. 

If your user is a Prisma model then it can be that type.

Just as always if using Prisma, make sure no sensitive fields are added to that data returned as currentUser like password hash or salt.