【发布时间】:2021-04-22 21:34:36
【问题描述】:
访问/刷新时,应用会检查 cookie 中的刷新令牌。如果有一个有效的,Apollo Express 服务器将给出一个访问令牌。这在我的桌面上运行良好,但在 iPhone 上使用 Chrome 或 Safari 时,用户在每次刷新时都会被发送到登录页面。
使用 Apollo 客户端反应应用程序
useEffect(() => {
fetchUser();
}, []);
const fetchUser = async () => {
const res = await fetch('https://website.com/token', {
method: 'POST',
credentials: 'include',
});
const { accessToken } = await res.json();
if (accessToken === '') {
setIsLoggedIn(false);
}
setAccessToken(accessToken);
setLoading(false);
};
Apollo 客户端还会检查访问令牌是否有效
const authLink = setContext((_, { headers }) => {
const token = getAccessToken();
if (token) {
const { exp } = jwtDecode(token);
if (Date.now() <= exp * 1000) {
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
}
}
fetch('https://website.com/token', {
method: 'POST',
credentials: 'include',
}).then(async (res) => {
const { accessToken } = await res.json();
setAccessToken(accessToken);
return {
headers: {
...headers,
authorization: accessToken ? `Bearer ${accessToken}` : '',
},
};
});
});
const client = new ApolloClient({
link: from([authLink.concat(httpLink)]),
cache: new InMemoryCache(),
connectToDevTools: true,
});
这会处理 Express 服务器上的令牌链接
app.use('/token', cookieParser());
app.post('/token', async (req, res) => {
const token = req.cookies.rt;
if (!token) {
return res.send({ ok: false, accessToken: '' });
}
const user = await getUser(token);
if (!user) {
return res.send({ ok: false, accessToken: '' });
}
sendRefreshToken(res, createRefreshToken(user));
return res.send({ ok: true, accessToken: createAccessToken(user) });
});
以及cookie的设置
export const sendRefreshToken = (res, token) => {
res.cookie('rt', token, {
httpOnly: true,
path: '/token',
sameSite: 'none',
secure: true,
});
};
与前端在 Netlify 上的站点相同。
【问题讨论】:
-
我已将问题隔离为 cookie 设置。我还没有弄清楚 iOS Chrome 和 Safari 不喜欢哪个设置,但是在我的开发服务器上,没有相同的站点,并且安全,cookie 保存得很好。我还设置了一个 maxAge,这使它不再是会话 cookie。
标签: heroku apollo react-apollo netlify