Okay I am trying on gmail API ? It is driving me crazy, I am kind of new too it. First of all I want to print JSON response of Email and Labels to Browser or postman. Second Everytime I call API i have to reauthenticate.
any help would be really appreacited. what can I do in order to get to print response in browser which I am getting in console.
const { google } = require('googleapis');
const express = require('express');
const OAuth2Data = require('./credentials.json');
const fs = require('fs');
const { response } = require('express');
const app = express()
const TOKEN_PATH = 'token.json';
const CLIENT_ID = OAuth2Data.client.id;
const CLIENT_SECRET = OAuth2Data.client.secret;
const REDIRECT_URL = OAuth2Data.client.redirect_uris;
const oAuth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
var authed = false;
app.get('/', (req, res) => {
if (!authed) {
// Generate an OAuth URL and redirect there
const url = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://mail.google.com/'
});
console.log(url)
res.redirect(url);
} else {
const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
gmail.users.labels.list({
userId: 'me',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const labels = res.data.labels;
if (labels.length) {
console.log('Labels:');
labels.forEach((label) => {
console.log(`- ${label.name}`);
});
} else {
console.log('No labels found.');
}
});
res.send('Logged in')
}
})
app.get('/auth/google/callback', function (req, res) {
const code = req.query.code
if (code) {
// Get an access token based on our OAuth code
oAuth2Client.getToken(code, function (err, token) {
if (err) {
console.log('Error authenticating')
console.log(err);
} else {
console.log('Successfully authenticated');
oAuth2Client.setCredentials(token);
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
authed = true;
res.redirect('/')
}
});
}
});
const port = process.env.port || 5000
app.listen(port, () => console.log(`Server running at ${port}`));
app.get('/m',(req, res) => {
if (!authed) {
// Generate an OAuth URL and redirect there
const url = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://mail.google.com/'
});
console.log(url)
res.redirect(url);
}
else {
const gmail1 = google.gmail({ version: 'v1', auth: oAuth2Client });
gmail1.users.messages.list({userId: 'me', maxResults: 2}, function (err, res) {
if (err) {
console.log('The API returned an error 1: ' + err);
return;
}
// Get the message id which we will need to retreive tha actual message next.
for (let index = 0; index < 2; index++) {
var message_id = res['data']['messages'][index]['id'];
gmail1.users.messages.get({auth:oAuth2Client, userId: 'me', 'id': message_id}, function(err, res) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
console.log('data',res['data']);
});
}
// Retreive the actual message using the message id
});
}
})
Related
When calling my PUT method, I got this error:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body>
</html>
I have some jwt authentification, so I put my complete code here:
It works with GET and POST methods
const express = require('express');
const logger = require('morgan');
var fs = require('fs');
var https = require('https');
var privateKey = fs.readFileSync('/etc/letsencrypt/live/hidden/privkey.pem', 'utf8');
var certificate = fs.readFileSync('/etc/letsencrypt/live/hidden/fullchain.pem', 'utf8');
const util = require('util')
var credentials = {key: privateKey, cert: certificate};
var queryString = require('querystring');
const bodyParser = require('body-parser');
const app = express();
const jwt = require('jsonwebtoken');
// import passport and passport-jwt modules
const passport = require('passport');
const passportJWT = require('passport-jwt');
const bcrypt = require('bcryptjs');
const Sequelize = require('sequelize');
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var backend = 'http://localhost:8484';
// initialize an instance of Sequelize
const sequelize = new Sequelize({
//hiden///
});
// ExtractJwt to help extract the token
let ExtractJwt = passportJWT.ExtractJwt;
// JwtStrategy which is the strategy for the authentication
let JwtStrategy = passportJWT.Strategy;
let jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = 'hidden';
// lets create our strategy for web token
let strategy = new JwtStrategy(jwtOptions, function(jwt_payload, next) {
console.log('payload received', jwt_payload);
let user = getUser({ id: jwt_payload.id });
if (user) {
next(null, user);
} else {
next(null, false);
}
});
// use the strategy
passport.use(strategy);
app.use(passport.initialize());
app.use(logger(':date[iso] :method :url :status :response-time ms - :res[content-length]'));
// parse application/json
app.use(bodyParser.json());
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// check the databse connection
sequelize
.authenticate()
.then(() => console.log('Connection has been established successfully.'))
.catch(err => console.error('Unable to connect to the database:', err));
// create user model
const User = sequelize.define('user', {
name: {
type: Sequelize.STRING,
allowNull: false
},
code_event: {
type: Sequelize.INTEGER,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
});
// create table with user model
User.sync()
.then(() => console.log('User table created successfully'))
.catch(err => console.log('did you enter wrong database credentials?'));
// create some helper functions to work on the database
const createUser = async ({ name, password, code_event }) => {
try{
return await User.create({ name, password, code_event });
}
catch (error) {
// your catch block code goes here
}
};
const getAllUsers = async () => {
try{
return await User.findAll();
}
catch (error) {
// your catch block code goes here
}
};
const getUser = async obj => {
try{
return await User.findOne({where: obj,});
}
catch (error) {
// your catch block code goes here
}
};
// get all users
app.get('/users', function(req, res) {
getAllUsers().then(user => res.json(user));
});
// register route
app.post('/register', function(req, res, next) {
console.log(req.body);
let { name, password, code_event } = req.body;
bcrypt.genSalt(10, (err, salt) => {
if(err) throw err;
bcrypt.hash(password, salt,
(err, hash) => {
if(err) throw err;
password = hash;
createUser({ name, password, code_event }).then(user =>
res.json({ user, msg: 'account created successfully' })
)
.catch(err => res.status(400).json(err));
});
});
});
// login route
app.post('/login', async function(req, res, next) {
console.log(req.body);
const { name, password , code_event} = req.body;
if (name && password) {
// we get the user with the name and save the resolved promise returned
let user = await getUser({ name, code_event});
if (!user) {
res.status(401).json({ msg: 'No such user found', user });
}
bcrypt.compare(password, user.password)
.then(isMatch => {
if (isMatch) {
const payload = {id: user._id};
// let token = jwt.sign(payload, jwtOptions.secretOrKey, { expiresIn: 36000 }, (err, token) => {
// if (err) res.status(500).json({ error: "Error signing token", raw: err });
// res.json({ msg: 'ok', token: token });
// });
let token = jwt.sign(payload, jwtOptions.secretOrKey);
res.json({ msg: 'ok', token: token });
} else {
res.status(401).json("Password is incorrect");
}
});
}
});
apiProxy.on( 'proxyReq', ( proxyReq, req, res, options ) => {
console.log("body " +util.inspect(req.body, false, null, true /* enable colors */));
if ( !req.body || !Object.keys( req.body ).length ) {
return;
}
let contentType = proxyReq.getHeader( 'Content-Type' );
let bodyData;
if ( contentType.includes( 'application/json' ) ) {
bodyData = JSON.stringify( req.body );
}
if ( contentType.includes( 'application/x-www-form-urlencoded' ) ) {
bodyData = queryString.stringify( req.body );
}
if ( bodyData ) {
proxyReq.setHeader( 'Content-Length', Buffer.byteLength( bodyData ) );
proxyReq.write( bodyData );
}
});
app.all("/*", passport.authenticate('jwt', { session: false }), function(req, res) {
console.log("req all" + req);
apiProxy.web(req, res, {target: backend});
});
app.on('upgrade', function (req, socket, head) {
console.log("req on" + req);
apiProxy.ws(req, socket, head, {target: backend});
});
var httpsServer = https.createServer(credentials, app);
// start the app
httpsServer.listen(8383, function() {
console.log("Express is running on port 3000");
});
It works with my POST methods.
I don't know where it goes because, when calling a method, I should have a trace in my log files. I can see POST ot GET calls but not PUT ones.
Any ideas?
I am trying to use Oauth2 with googleapis but I got some error like this.
I found someone got same error but they are using IOS, I am using NodeJS in this case.
I do follow this example: https://dev.to/uddeshjain/authentication-with-google-in-nodejs-1op5
This is my code:
const { google } = require('googleapis');
const express = require('express')
const OAuth2Data = require('./google_key.json')
const app = express()
const CLIENT_ID = OAuth2Data.client.id;
const CLIENT_SECRET = OAuth2Data.client.secret;
const REDIRECT_URL = OAuth2Data.client.redirect
const oAuth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
var authed = false;
app.get('/', (req, res) => {
if (!authed) {
const url = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: 'https://www.googleapis.com/auth/gmail.readonly'
});
res.redirect(url);
} else {
const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
gmail.users.labels.list({
userId: 'me',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const labels = res.data.labels;
if (labels.length) {
console.log('Labels:');
labels.forEach((label) => {
});
} else {
}
});
res.send('Logged in')
}
})
app.get('/auth/google/callback', function (req, res) {
const code = req.query.code
if (code) {
oAuth2Client.getToken(code, function (err, tokens) {
if (err) {
console.log('Error authenticating')
console.log(err);
} else {
console.log('Successfully authenticated');
oAuth2Client.setCredentials(tokens);
authed = true;
res.redirect('/')
}
});
}
});
const port = process.env.port || 3000
app.listen(port, () => console.log(`Server running at ${port}`));
And credentials file: google_key.json
{
"client": {
"id": "xxx-rm7s51vmr320brk5b5mrhopgma0e65o9.apps.googleusercontent.com",
"secret": "nIMQpHo6LRMs128Hp8sjh6-bxxxx",
"redirect": "testauth.com:3000"
},
"credentials": {
"access_token": "your access_token",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "your refresh_token"
}
}
Any help!
I am trying to create a client-side script that allows someone to login to their Google Account and then access a Firestore database once they are authenticated. Everything works except for some reason after signing in using firebase.auth it isn't passing this data to firebase.firestore to say they are authenticated.
Here is the script that I am using, the only part that is failing is when I am trying to add to a Firestore collection.
const firebase = require ("firebase/app");
require("firebase/auth");
require("firebase/firestore");
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
const util = require('util')
var config = {
**HIDDEN**
};
firebase.initializeApp(config);
const SCOPES = ['email','profile'];
const TOKEN_PATH = 'token.json';
fs.readFile('credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// Authorize a client with credentials, then call the Gmail API.
authorize(JSON.parse(content), listLabels);
});
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function listLabels(auth) {
var credential = firebase.auth.GoogleAuthProvider.credential(auth.credentials.id_token);
firebase.auth().signInAndRetrieveDataWithCredential(credential).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
console.log(errorCode);
console.log(errorMessage);
});
var firestore = firebase.firestore();
firestore.settings({
timestampsInSnapshots: true
});
firestore.collection("users").add({
test: "Hello"
});
firebase.auth().signOut();
}
And below is my rules for the database, if I change it to just if true; it works perfectly fine. But I want to make sure only an authenticated user can access that database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
The method signInAndRetrieveDataWithCredential returns a promise, and you aren't waiting for it to finish before accessing the data on Firestore, so that is probably what is causing the issues. I believe this might work:
function listLabels(auth) {
var credential = firebase.auth.GoogleAuthProvider.credential(auth.credentials.id_token);
firebase.auth().signInAndRetrieveDataWithCredential(credential)
.then(user => {
var firestore = firebase.firestore();
firestore.settings({
timestampsInSnapshots: true
});
firestore.collection("users").add({
test: "Hello"
});
firebase.auth().signOut();
})
.catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
console.log(errorCode);
console.log(errorMessage);
});
}
I am trying to return the value of the data object from the function listLabels in my code below. I would like to have it be accessed from an Express endpoint, e.g. (localhost:3001).
I have been able to console log the object and I have been able to send myself emails. Any help in returning the value when accessing the Express endpoint would be greatly appreciated.
const express = require('express')
const app = express()
const fs = require('fs')
const readline = require('readline')
const {google} = require('googleapis')
app.get('/', function(req, res) {
res.setHeader('Content-Type', 'application/json')
let data = getLabels()
console.log('data: ' + data)
res.json(data)
})
app.get('/hello', function (req, res) {
res.send('hello there')
})
app.listen(3001, () => console.log('server up on 3001'))
const SCOPES = ['https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.send'
];
const TOKEN_PATH = 'credentials.json';
function getLabels() {
fs.readFile('client_secret.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
authorize(JSON.parse(content), listLabels);
});
}
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
fs.writeFile('getCredentials.txt', authUrl, (err) => {
if (err) throw err;
console.log('getCredentials.txt saved!')
})
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return callback(err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function listLabels(auth) {
const gmail = google.gmail({version: 'v1', auth});
console.log('here')
gmail.users.messages.list({
userId: 'me',
maxResults: 10
}, (err, {data}) => {
if (err) return console.log('The API returned an error: ' + err);
console.log('data in listlabels ' + JSON.stringify(data))
//return data
let dataForExpress
messages.forEach(function (message, index) {
gmail.users.messages.get({
userId: 'me',
id: data.messages[index].id,
format: 'raw'
}, (err, {data}) => {
if (err) return console.log('Error: ' + err)
console.log(data)
dataForExpress.push(data)
});
})
return dataForExpress
})
}
The data you are expecting is coming back in an asynchronous fashion, so you will need to handle it asynchronously using either callbacks or async await.
Here is an example using callbacks.
const express = require('express')
const app = express()
const fs = require('fs')
const readline = require('readline')
const {google} = require('googleapis')
app.get('/', function(req, res) {
res.setHeader('Content-Type', 'application/json')
// let data = getLabels()
getLabels((labels) => {
console.log(labels)
res.json(labels)
})
//console.log('data: ' + data)
//res.json(data)
})
app.get('/hello', function (req, res) {
res.send('hello there')
})
app.listen(3001, () => console.log('server up on 3001'))
const SCOPES = ['https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.send'
];
const TOKEN_PATH = 'credentials.json';
function getLabels(callback) {
fs.readFile('client_secret.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// so here, instead of passing it listLabels directly, we will pass it just a regular callback, and call listlabels inside that callback. This way we can choose what to do with listlabels return value.
authorize(JSON.parse(content), (auth) => {
listLabels(auth, (listOfLabels) => {
console.log(listOfLabels) // we should have the list here
callback(listOfLabels)
}) //match the original arguments
});
});
}
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
fs.writeFile('getCredentials.txt', authUrl, (err) => {
if (err) throw err;
console.log('getCredentials.txt saved!')
})
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return callback(err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function listLabels(auth, callback) {
const gmail = google.gmail({version: 'v1', auth});
console.log('here')
gmail.users.messages.list({
userId: 'me',
maxResults: 10
}, (err, {data}) => {
if (err) return console.log('The API returned an error: ' + err);
console.log('data in listlabels ' + JSON.stringify(data))
//return data
let dataForExpress
let messages = data.messages
messages.forEach(function (message, index) {
console.log("Inside foreach, message and index :", message, index)
gmail.users.messages.get({
userId: 'me',
id: message.id,
format: 'raw'
}, (err, {data}) => {
if (err) return console.log('Error: ' + err)
console.log(data)
dataForExpress.push(data)
if dataForExpress.length == messages.length { // we done
callback(dataForExpress)
}
});
})
})
}
I want to let users to connect to my node.js server with their gmail. I have created a project in the Google Developers Console. Then use the following code:
const express = require('express');
const google = require('googleapis');
const googleAuth = require('google-auth-library');
const credentials = require('../link/of/some/file.json'); // google credential
let clientSecret = credentials.web.client_secret;
let clientId = credentials.web.client_id;
let redirectUrl = credentials.web.redirect_uris[0];
const SCOPES = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.readonly'
];
let auth = new googleAuth();
let oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
app.get('/connect', (req, res) => {
let authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
res.redirect(authUrl);
});
when /connect is called, it will redirect to google page to verify user. After user give access of his/her account, google will automatically call the following api with a code query parameter:
app.get('/auth/callback', (req, res) => {
// 'req.query.code' is provided by google
return oauth2Client.getToken(req.query.code, (err, token) => {
// token value:
/*
{
access_token: 'ya29.Gls2Ba_rXEA5EoBaFH5bPdDDzgaSWOtb0GSJcnaTP47Jh7HwHdF2ZJZOlQaCJBC5wjpq-sOLBVlIM9L8BMslVyHw22nveU0MwQ4iJPTq5vkjXDeitqtoYH8JO83w',
refresh_token: '1/S0C3w-8vnqcrGE4Z2mSW9ctYkaitVuZquBSJ0WJJHUs',
token_type: 'Bearer',
expiry_date: 1514897380473
}
*/
});
});
Now, My problem is, in the above token value, I cannot understand how can I get gmail address from that token. What am I missing???
Any Suggestion? Thanks in advance.
the first steps I would suggest is to store your token somewhere so you don't request it all the time.
Then when you recieve the token you put it in oauth2Client.credentials
oauth2Client.getToken(req.query.code, (err, token) => {
if (err) {
console.log(err);
return;
}
//TODO: Save token somewhere
oauth2Client.credentials = token;
});
Then you use the oauth2Client to do API calls
var gmail = google.gmail('v1');
gmail.users.labels.list({
auth: oauth2Client,
userId: 'me',
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var labels = response.labels;
if (labels.length == 0) {
console.log('No labels found.');
} else {
console.log('Labels:');
for (var i = 0; i < labels.length; i++) {
var label = labels[i];
console.log('- %s', label.name);
}
}
});
Solved:
I have solve this problem, just calling getProfile, where userId is me. My code is given below:
const SCOPES = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.compose'
];
app.get('/auth/callback', (req, res) => {
return oauth2Client.getToken(req.query.code, (err, token) => {
oauth2Client.credentials = token;
var gmail = google.gmail('v1');
gmail.users.getProfile({
auth: oauth2Client,
userId: "me",
}, function(error, response) {
console.log("getProfile : ", {error, response});
/*
output:
{
emailAddress: 'some.address#gmail.com',
messagesTotal: xxx,
threadsTotal: xxx,
historyId: 'xxxxx'
}
*/
});
});
});
Thanks to all of you.