I can't find much resources regarding Field-level authorization, more so with the N+1 problem, but if you know of one, please let me know.
Currently, the best way so far I have found with field-level authorization is with this style.
Schema
Type User {
id: ID
profile: Profile
...
}
type Profile {
...
emailAddress: String
}
Parent User resolver
@ResolveField('profile')
async profile(
@Parent() parent: User,
// Type added for the sake of TS. This includes the things I want to pass from the parent to this level. I'm not using @Parent(), because then, I would have to return emailAddress from the parent, and hope that this federation (?) is not broken and this fieldResolver runs. And if it's broken, then it would just return from the parent
@Context() context: ProfileContext
): Promise<UserProfileWithoutEmail> {
...
const profile = profileDataLoader.loader(parent.id)
context.emailAddress = profile.emailAddress
return {
...fields except emailAddress, and for someone reason, this doesn't include an id I can use as the dataloader in the ProfileResolver class
}
}
Child Field to authorize.
@ResolveField('emailAddress')
async emailAddress(
@Context() context: ReadOnlyProfileContext,
// From Keycloak. I've set it up to include a permission array
@AuthenticatedUser() user: AuthenticatedUserType
): Promise<string | null> {
// Authorization check - users with email view permissions
// Runs N+1 times
if (user.permissions.include('emailView')) {
return context.emailAddress
}
return null
}
But as you can see, the auth part runs N+1. It looks alright here because it's only .include(), but what if it's a more complicated auth check?
Is there a guide or a best practice to mitigate N+1 auth checks?