nexus-plugin-prisma icon indicating copy to clipboard operation
nexus-plugin-prisma copied to clipboard

Authorization

Open andres-valdes opened this issue 5 years ago • 5 comments

Hi!

I’m really excited to use this package for my latest project but I’m not really sure how to manage authorization with this.

How can I protect the t.crud and t.model fields from unauthorized users?

Is graphql-shield the only option? The type unsafety there feels really cumbersome.

How do you guys authorize users to access certain mutations and queries?

andres-valdes avatar Feb 07 '20 05:02 andres-valdes

Indeed I wish there was an authorization pattern integrated within this plugin, because I'm not a big fan of having the declaration rules inside a single centralized shield object...

I would prefer defining my permissions logic right inside the t.crud and t.model and have just a generic logic in the plugin options to express generic rules like default: IsAdmin or read-only: everyone.

Otherwise you can implement kind of an authorization middleware by overriding the resolve function: https://nexusjs.org/pluginss/prisma/runtime#resolve

gabsn avatar Aug 25 '20 16:08 gabsn

I am using this:

async function resolveIfAdmin(root: any, args: any, ctx: any, info: any, originalResolve: any) {
  const isAdmin = await ctx.isAdmin() // you need to implement isAdmin yourself
  if (isAdmin) {
    return originalResolve(root, args, ctx, info)
  } else {
    throw Error("You need to be admin to perform this action")
  }
}

export const mutateYear = extendType({
  type: 'Mutation',
  definition(t) {
    t.crud.createOneYear({
      resolve: resolveIfAdmin, // action will fail if you are not admin
    })
    t.crud.updateOneYear({
      resolve: resolveIfAdmin, // action will fail if you are not admin
    })
  },
})

It's probably not perfect, but it works for me.

HendrikJan avatar Jan 13 '21 15:01 HendrikJan

I'm using https://github.com/Sytten/nexus-shield which is very nice.

import { hasRole } from "../rules";
import { Role } from "../generated/types";

export const UserQuery = extendType({
  type: "Query",
  definition(t) {
    t.crud.user({ shield: hasRole(Role.Editor)() });
    t.crud.users({ shield: hasRole(Role.Editor)() });
  },
});

lewebsimple avatar Jan 13 '21 16:01 lewebsimple

Maybe https://nexusjs.org/docs/plugins/field-authorize is of interest:

t.field('postById', {
  type: Post,
  args: { id: idArg() },
  authorize: (root, args, ctx) => ctx.auth.canViewPost(args.id),
  resolve(root, args, ctx) {
    return ctx.post.byId(args.id)
  },
})

mikkelsl avatar Jan 23 '21 20:01 mikkelsl

Catching up on this old thread as I'm trying to figure out the best option here as well. @mikkelsl the fieldAuthorize seems to be a good simple option, but it's unclear if that has the automatic caching built in like the shield options do?

koriner avatar Nov 16 '21 05:11 koriner