我是apollo / graphql的新手,我试图在绿地项目中正确完成我的身份验证。我的身份验证提供程序是AWS cognito
。我写了一个认知辅助模块来与它进行交互。
虽然我不太确定如何将我的apollo客户端与我的身份验证状态同步。
export const authenticate = (username: string, password: string) => {
const authDetails = new AuthenticationDetails({
Username: username,
Password: password,
})
const cognitoUser = getCognitoUser(username)
return new Promise((resolve, reject) => {
cognitoUser.authenticateUser(authDetails, {
onSuccess: result => {
resolve(result)
},
onFailure: err => {
reject(err)
},
})
})
}
export const getCurrentUserToken = () => {
return new Promise((resolve, reject) => {
const currentUser = userPool.getCurrentUser()
if (currentUser) {
currentUser.getSession((error, session) => {
if (error) {
reject(error)
}
resolve(session.getIdToken().getJwtToken())
})
} else {
resolve(null)
}
})
}
export const logout = () => {
const currentUser = userPool.getCurrentUser()
if (currentUser) {
currentUser.signOut()
}
}
现在我只是通过在我的react组件处理程序中调用它们来使用这些函数来处理我的登录。我配置了一个apollo-link来添加auth头。将我的JWT令牌数据注入后端的上下文中,并在后端实现currentUser
查询解析器。
const resolvers = {
RootQuery: {
currentUser: (obj, args, context) =>
context.tokenData
? {
id: context.tokenData.sub,
name: context.tokenData.name,
email: context.tokenData.email,
username: context.tokenData['cognito:username'],
}
: null,
},
}
在我的应用程序布局中,我得到了一个UserPanel
组件,用于查询currentUser
查询。
const CURRENT_USER_QUERY = gql`
query {
currentUser {
name
}
}
`
export default graphql(CURRENT_USER_QUERY)(UserPanel)
当我现在登录时,显然UserPanel不会更新其currentUser
查询,除非我重新加载页面ofc。虽然我也很难找到一个很好的解决方案来同步它们。
我正在考虑使用apollo-link-state通过graphql变异实现我的登录,以便在本地执行此操作,并在有人登录/注销时观察这些重新获取。我不确定这是否正常,因为在我看来,这个链接无法解析其突变解析器中的异步内容(例如promises)。
我想到的另一个选择是将auth进程与apollo客户端彻底解耦,并使用Observables
实现一些auth pubsub系统,如果身份验证状态发生变化,让react组件重新获取查询。
我非常不确定如何继续,而我所考虑的每一种解决方案都不适合推荐的方式。
答案 0 :(得分:0)
我没有全面了解您的React设置,但我在这里。可能是Apollo-client在本地缓存CURRENT_USER_QUERY并向您显示先前查询的结果。您可以在查询中尝试network-only
选项:
export default graphql(CURRENT_USER_QUERY, { options: {fetchPolicy: 'network-only' }})(UserPanel)
我在React中的内容是AppContainer
,它是我的父组件。它会检查用户是否已登录:
const loggedInUser = gql`
query loggedInUser{
user {
id
role
}
}`
export default graphql(loggedInUser, { options: {fetchPolicy: 'network-only' }})(AppContainer)
然后在我的UserProfile页面上,我使用数据容器来获取数据,然后将其传递给UserProfile子组件。我认为loggedInUser查询会自动更新apollo商店中的用户。有了它,apollo-client意识到它需要重新获取userQuery
。这有帮助吗?
const userQuery = gql`
query userQuery {
user {
id
name
email
role
company
}
}
`
export default graphql(userQuery, {name: 'userQuery'})(UserDataContainer);