What is the best way to separate sensitive (access tokens) and non-sensitive (user) data? #74
-
I'm not quite sure how to get this working. If I attempt to set session data like so: async ({ accessToken, refreshToken, extraParams }) => {
const idDecoded = await validateToken('id', extraParams.id_token)
const accessDecoded = await validateToken('access', accessToken)
const session = await sessionStorage.getSession()
session.set('accessToken', accessToken) // <--- save to session
session.set('refreshToken', refreshToken) // <--- save to session
await sessionStorage.commitSession(session, { // <--- commit session
maxAge: accessDecoded.exp,
})
return {
id: idDecoded.profile as string,
name: idDecoded.name as string,
email: idDecoded.email as string,
exp: accessDecoded.exp as number,
}
} I'm not able to access it later in a loader: const loader = async ({ request }: LoaderFunctionArgs) => {
const user = await authenticator.isAuthenticated(request)
if (!user) return redirect('/login')
if (user.exp * 1000 < Date.now()) return redirect('/login')
const session = await getSession(request.headers.get('Cookie')) // <--- contains `user` but not `accessToken`
const accessToken = session.get('accessToken') // <--- fails, is empty
const response = await apiFetch(session.get('accessToken'), uri)
return {
user,
data: response.data,
} as ApiLoaderResponse
} Is it possible to store sensitive accessTokens in the session while also only returning the user from the authenticator? Or do I need to store the accessToken as part of the user data returned from the authenticator? This means devs need to "be careful" not to expose the token in a loader. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
I figured out how to do it. In the server you need to throw a redirect instead of returning the user. This appears to be the only way to ensure the cookie is actually set. async ({ accessToken, refreshToken, extraParams, request }) => {
const idDecoded = await validateToken('id', extraParams.id_token)
const accessDecoded = await validateToken('access', accessToken)
const cookie = request.headers.get('Cookie')
const session = await getSession(cookie)
const user: AuthorizedSession = {
id: idDecoded.profile as string,
name: idDecoded.name as string,
email: idDecoded.email as string,
exp: accessDecoded.exp as number,
}
session.set('user', user)
session.set('accessToken', accessToken)
session.set('refreshToken', refreshToken)
throw redirect('/', {
headers: {
'Set-Cookie': await commitSession(session, {
maxAge: accessDecoded.exp,
}),
},
})
} |
Beta Was this translation helpful? Give feedback.
-
If you don't set successRedirect on the callback route, you will get the value returned by the strategy. Then you can set yourself the session and keep part of the data somewhere else. |
Beta Was this translation helpful? Give feedback.
If you don't set successRedirect on the callback route, you will get the value returned by the strategy. Then you can set yourself the session and keep part of the data somewhere else.