I have a client server and an API, both using Apollo. When the user logs in with Facebook I want to send a token to my client server which will then be appended to the headers of every request made to the API. Without using sessions.
Here's how the API looks, this generates the token successfully when a user logs in with Facebook (I'm also checking for users in a database behind the scenes).
// API running on port 3010
app.use(expressJwt({
secret: authConfig.jwt.secret,
credentialsRequired: false,
getToken: req => req.cookies.id_token,
}));
app.use(passport.initialize());
app.get('/login/facebook',
passport.authenticate('facebook', { scope: ['email'], session: false }),
);
app.get('/login/facebook/return',
passport.authenticate('facebook', { failureRedirect: 'http://localhost:3000/login', session: false }),
(req, res) => {
const expiresIn = 60 * 60 * 24 * 1; // 1 day
const token = jwt.sign(req.user, authConfig.jwt.secret, { expiresIn });
res.redirect(`http://localhost:3000?token=${token}`); // Redirect to client and append token to param
},
);
My question is, how do I now hand this token to the client securely? I've read this and this, which led me to passing the token in a param, but I'm not sure if what I'm doing is secure.
Here's how I'm getting it on the client side:
const token = getURLParameterByName('token');
if (token) {
localStorage.setItem('token', token);
}
networkInterface.use([{
applyMiddleware(req, next) {
if (!req.options.headers) {
req.options.headers = {}; // Create the header object if needed.
}
// Get the authentication token from local storage if it exists
const localToken = localStorage.getItem('token')
req.options.headers.authorization = localToken ? `Bearer ${localToken}` : null;
next();
},
}]);
After this, using it in the API:
app.use('/graphql', apolloExpress(req => {
let token;
if (req.headers.authorization) {
token = req.headers.authorization;
console.log(token);
}
return {
schema: executableSchema,
context: {
token,
},
};
}));