GraphQL 编辑需要授权的字段的最佳实践
Posted
技术标签:
【中文标题】GraphQL 编辑需要授权的字段的最佳实践【英文标题】:GraphQL best practice on redacting fields that require authorization 【发布时间】:2020-08-17 13:11:28 【问题描述】:考虑一个User
类型,带有一个email
字段,对于某些“匿名”用户,只有在请求得到适当授权的情况下才能访问该字段。其他用户可以公开显示他们的电子邮件。
type User
name: String!
"Anonymous users have the email only accessible to admins"
email: String!
在email
解析器中为匿名用户处理该字段的这两种方法的优缺点是什么?
throw
如果请求未经授权。在这种情况下,
email
需要声明为可空的 String
而不是 String!
、or the entire query will error。
客户端可能希望将the errors
与data
匹配。因为非匿名用户可以在未经授权的情况下访问他们的电子邮件,errors
和 data
可能有不同数量的元素,所以这种匹配似乎不可能,至少对于 apollo-server,它没有t 返回每个 errors
元素中的任何内容,以指示它属于哪个 user
。
email
会误导匿名用户 null
,将这种情况与从未添加过的电子邮件混淆。请记住,email
必须是 String
,而不是 String!
,所以null
电子邮件是合理的。
响应中有一个明确的errors
数组,所以这感觉像是“正确”的方法?
以编辑的形式返回电子邮件,例如[NOT AUTHORIZED TO ACCESS THIS USER'S EMAIL]
。
这样可以保持对象完好无损,敏感电子邮件会出现明显错误,而不是误导“空”电子邮件。
email
可以保持不可为空
无需尝试将errors
与data
匹配。
响应中没有明确的 errors
数组,所以这感觉像是 hack。
请注意,对于数组,不能返回 REDACTED
表单,因为查询可能会要求数组中的字段(例如 anonUsers email
)。唯一的选择是返回[]
(直接或通过throw
ing)。
我错过了什么吗?有没有关于这个主题的先前工作?我该如何做决定?
【问题讨论】:
联合类型会是一个好的用例吗?您可以有一个普通的User
类型和一个AnonymousUser
类型,并且可能有一些将它们分开的字段,例如is_anonymous
。所以也许AnonymousUser
没有电子邮件字段,而User
有。
@A.Lau:这回避了问题。假设所有用户都是匿名的,只有授权的请求才能看到email
;那么关于将errors
与data
匹配的意义就没有意义了,但其他的仍然存在。
也许 AnonymousUser
email
可以是一个对象,这样你就可以显示你想要的任何消息/错误代码。
【参考方案1】:
我最近做了类似的事情,似乎最有效的是为基本用户类型创建一个界面。
interface UserInformation
id: ID!
userName: String
firstName: String!
lastName: String
avatarImage: String
city: String
...
那么你会有两个独立的实现:
type UserPublic implements UserInformation
id: ID!
userName: String
firstName: String!
lastName: String
avatarImage: String
...
type UserPrivate implements UserInformation
id: ID!
userName: String
firstName: String!
lastName: String
avatarImage: String
friends: [UserInformation!]
pendingFriends: [UserInformation!]
phone: String
email: String
birthday: DateTime
...
在公开用户时,您的所有其他查询和类型都使用UserInformation
基本接口类型。然后,您的 graphql 服务器仅返回 UserPublic
或 UserPrivate
,具体取决于用户拥有的访问权限类型。
在客户端你这样查询它:
query SomeQuery
getSomeData
user
id
userName
firstName
lastName
avatarImage
...on UserPrivate
email
phone
...
然后您可以检查客户端返回的字段类型 (__typename
) 是否为 UserPublic
或 UserPrivate
并采取相应措施。
【讨论】:
以上是关于GraphQL 编辑需要授权的字段的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章
在 Typescript 应用程序中管理生成的 graphql 模式的最佳实践
使用 Apollo 重新获取部分 GraphQL 查询的最佳实践?
如何操作 AWS AppSync 和 GraphQL 以符合 DynamoDB 最佳实践?