I have the below schema
extend type Query @middleware(checks: ["api", "auth:api"]) {
users: [User!]! @paginate(type: "paginator" model: "App\\Models\\User")
user(id: ID @eq): User @find(model: "App\\Models\\User")
}
type User {
id: ID!
name: String!
email: String! @can(ability: "viewEmail", model: "App\\Models\\User")
createdAt: DateTime! @rename(attribute: "created_at")
updatedAt: DateTime @rename(attribute: "updated_at")
}
I would expect that the middleware is first triggerd and I would be logged in first based on the middleware. However the @can is triggered first. This means, that I don't have the authenticated user and that this will always throw an 403.
I would expect that it works the other way around.
The more general question: How is it possible to block a specific field inside for a type based on someones permissions? For example: an employee can view all users but not their email adres, only their name. Admins can view all data.
Lighthouse Version: 3.7.0
Laravel Version: 5.7
I agree with your expectation. Can you provide a PR with a failing test case so we can work on fixing this issue?
I ran into a similar problem just now, and I suspect it is caused by the same implementation detail. I would propose the broader formulation for this issue as follows:
Individual field / mutation middleware is executed before the parent query / mutation middleware is executed, resulting in unexpected behavior.
Example:
# This doesn't work as expected (the "admin" middleware won't have access to the
# currently logged in user, because it is executed before the "auth:api" middleware
# at the group level)
type Mutation @group(middleware: ["auth:api"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete @middleware(checks: ["admin"])
}
# This works, but of course we wouldn't want to apply "admin" middleware to the
# addPost mutation
type Mutation @group(middleware: ["auth:api", "admin"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete
}
# A workaround would be to explicitly add the "auth:api" before the "admin"
# middleware, but this seems somewhat counterintuitive.
type Mutation @group(middleware: ["auth:api"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete @middleware(checks: ["auth:api", "admin"])
}
I will try to provide a PR with a failing test soon.
@sgtlambda @group is removed in v4, can you try upgrading first?
Upgrading to v4, and replacing @group(middleware: [ .. ]) with @middleware(checks: [ .. ]), the problem persists. Updated examples as follows:
# This doesn't work as expected (the "admin" middleware won't have access to the
# currently logged in user, because it is executed before the "auth:api" middleware
# at the group level)
type Mutation @middleware(checks: ["auth:api"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete @middleware(checks: ["admin"])
}
# This works, but of course we wouldn't want to apply "admin" middleware to the
# addPost mutation
type Mutation @middleware(checks: ["auth:api", "admin"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete
}
# A workaround would be to explicitly add the "auth:api" before the "admin"
# middleware, but this seems somewhat counterintuitive.
type Mutation @middleware(checks: ["auth:api"]) {
addPost(id: ID!, contents: String): Post @create
deleteUser(id: ID!): Record @delete @middleware(checks: ["auth:api", "admin"])
}
I understand the problem you are describing. I think that @middleware is fundamentally flawed in a few ways and we can look for alternative solutions, see https://github.com/nuwave/lighthouse/issues/880
Thank you @sgtlambda for doing my work馃槄. Was a little too bussy at home and missed the notifications. Great to hear this progress
@middleware is deprecated in v5. If you want to have the authenticated user available in the context, use a global middleware.
Most helpful comment
I understand the problem you are describing. I think that
@middlewareis fundamentally flawed in a few ways and we can look for alternative solutions, see https://github.com/nuwave/lighthouse/issues/880