I am trying to implement a React - Node js application that authenticates the user with Google and then retrieve its YouTube channel Id with google apis. I'm new to Google APIs, so I need some help to make this code works. The authentication with Google perfectly works, but I have a lot of difficulties in making the request to retrieve the channel id.
This is the code to focus in the React authentication component implemented with react-google-login:
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
buttonText="Log in with Google"
onSuccess={handleGoogleLoginSuccess}
onFailure={handleGoogleLoginFailure}
cookiePolicy={'single_host_origin'}
scope='https://www.googleapis.com/auth/youtube.readonly'
/>
const handleGoogleLoginSuccess = (googleData) => {
//The token id is in googleData.tokenId
console.log(googleData);
axios.post('auth/googleLogin', {
token: googleData.tokenId,
access_token: googleData.accessToken
}).then(response => {
//Login success
if(response.data.loginStatus === 'ok') {
setLoginMessage(''); //Reset message
const user = response.data.user;
console.log(user.email + " " + user.firstName + " " + user.lastName)
registerUser(user); //Register user in the context
//console.log(currentUser.email + " " + currentUser.firstName + " " + currentUser.lastName)
localStorage.setItem('user', JSON.stringify(user)); //Push user in the storage
history.push('/home'); //Redirect to home page
}else{ //Login fail
//Set error messages.
const message = response.data.message;
setLoginMessage(message);
}
});
}
const handleGoogleLoginFailure = () => {
setLoginMessage("Impossible to login with Google at the moment. Please retry later.")
}
While the end point in the express server is:
router.post('/googleLogin', async (req, res) => {
const { token, accessToken } = req.body;
const ticket = await client.verifyIdToken({
idToken: token,
audience: process.env.CLIENT_ID
});
const {email, given_name, family_name} = ticket.getPayload();
const { OAuth2 } = google.auth;
const oauth2Client = new OAuth2();
oauth2Client.setCredentials({ access_token: accessToken });
var service = google.youtube({
version: 'v3',
auth: oauth2Client,
});
service.channels.list({
key: process.env.GOOGLE_API_KEY,
auth: client,
mine: true,
part: 'snippet',
}, (err, response) => {
if(err) {
console.log(err);
return;
}
var channels = response.data.items;
console.log(channels);
});
const [user, created] = await User.upsert({
email: email,
firstName: given_name,
lastName: family_name,
youtubeChannelId: 'TODO'
});
if(user) {
const accessToken = createTokens(user);
res.cookie("access-token", accessToken, {
maxAge: 60 * 60 * 24 * 1000, //one day
httpOnly: true
});
return res.json({
loginStatus: 'ok',
user: user
});
}else{
console.log("Error in login with Google");
}
});
I'm getting the error: Error: No access, refresh token, API key or refresh handler callback is set.
Some ideas?
if you're using the Google OAuth 2.0 flow, I'm not sure why you're using the API key, since you're sending the user Access Token used to identify the user who completed the OAuth flow with your Client ID.
Also, I recommend using the global service auth, so you don't need to send auth credentials to each service call.
List my YouTube channels | View in Fusebit |
---|
const { OAuth2 } = google.auth;
const oauth2Client = new OAuth2();
oauth2Client.setCredentials({ access_token: accessToken });
// Add global service auth
google.options({ auth: oauth2Client });
const youtube = googleClient.youtube('v3');
const channelsResponse = await youtube.channels.list({
part: 'id,statistics,snippet',
mine: true
});