I am trying to create an application with passwordless authentication, with social medias like Facebook and by mail.
I'm stupidly stuck a one point, maybe I have not understand something.
Lets name my project MyApp:
If a user try to log to facebook from myapp.com/
, he will be redirected to facebook.com/login
, then facebook redirect him to myapp.com/callback
.
So, on my server, the route /
and /callback
are quite the same: they just send my React app to he user, but /callback
generate a JWT token.
From here is my problem : How can I send my JWT token to the client in the same time that the React app?
Maybe I have missed something from another provider, but the passwordless principle by mail is the same thing : just a link to authenticate the user, and just a redirection to the /callback
, no external provider.
I'm completely lost :(
Thank you!
You can put the JWT into the query string of the URL you want to redirect the user to. Then you get the JWT in the client from accessing the query string, and save it to local storage. I've done it myself recently check out my repo server here, client here
Edit: I post the code of the callback route in the server and getting the token in the client for more details check the links to my repo above
Callback Route
app.get('/auth/github/callback', (req,res) => {
githubAuth.code.getToken(req.originalUrl)
.then(user => {
console.log(user.data);
return fetch('https://api.github.com/user?access_token=' + user.accessToken);
})
.then(result => {
return result.json();
})
.then(json => {
//console.log(json);
//res.send(json);
return User.findOne({githubId: json.id})
.then(currentUser => {
if(currentUser){ // user already exists
console.log('User exists with GitHub Login: ' + currentUser);
return currentUser;
}
else{ // User doesn't exist
// saved automatically using mongoose, returns Promise
return new User({
username: json.login,
githubId: json.id
}).save()
.then(newUser => {
console.log('New User created with GitHub Login: ' + newUser);
return newUser;
});
}
});
})
.then(user => {
// Now use user data to create a jwt
const token = jwt.sign({id: user._id}, process.env.JWT_ENCRYPTION_KEY, {
expiresIn: 86400 // expires in 24 hours
});
const encodedToken = encodeURIComponent(token);
res.status(200);
res.redirect('/profile?token=' + encodedToken);
})
.catch(err => console.log(err));
});
Token Retrieval in Client
class UserProfile extends React.Component{
constructor(props){
super(props);
this.state = {username: ''};
}
componentDidMount(){
const query = new URLSearchParams(this.props.location.search)
// When the URL is /the-path?some-key=a-value ...
let token = query.get('token')
console.log(token)
if(token){ // it's the first time we receive the token
// we save it
console.log('Saving token');
localStorage.setItem('userjwt', token);
}
else{
// if qrstring is empty we load the token from storage
token = localStorage.userjwt;
console.log('Loading token: ' + token);
}
if(token){
const headers = new Headers({
'x-access-token': token
});
const reqOptions = {
method: 'GET',
headers: headers
};
fetch('/user', reqOptions)
.then(res => res.json())
.then(user => {
console.log(user);
console.log(user.username);
this.setState({username: user.username});
})
}
}
render(){
if(this.state.username === ''){
return(
<div className="social-profile">
<h2>Login first</h2>
</div>
);
}
else{
return(
<div className="social-profile">
<h2>User: {this.state.username}</h2>
</div>
);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With