How can I use the Google OAuth2 ID token with node.js / passport.js to verify if the user is valid and authenticated? - node.js

On my front end, I'm using vue.js (not that that matters) and with the Google OAuth flow, I get back an id_token from:
let googleAuthIdToken = await this.auth2.currentUser
.get()
.getAuthResponse().id_token;
I want to then pass that token to my node.js server (Express / Passport) to verify that the user is allowed to login.
I want to use passport and send back a JWT to the front end in my response.
Can someone please guide me as to how to accomplish this?

It is easier to make use of a node module called googleapis, After installation, import the module.
import { google } from 'googleapis';
Then you need to create an OAuthClient by specifying the CLIENT_ID, CLIENT_SECRET, REDIRECT_URL.
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URL,
);
Then you can get the token from google by using the oauth2Client.
const {tokens} = await oauth2Client.getToken(code);
oauth2Client.setCredentials(tokens);
Inorder to obtain the neccessary user information to store in your own database, You need to call this method.
const plus = google.plus({ version: 'v1', oauth2Client });
const me = await plus.people.get({ userId: 'me' });
me will contain the user information that you are looking for, once you obtain the user information you can then store it using passport js.

Related

How to create a GoogleStrategy stateless authentication using nodejs and passport.js?

I'm working on a project and I'm evaluating different way to authenticate my app. After trying Firebase and see that is not ok for me I decided to authenticate my app using passport.js.
I've created LocalStrategy, JwtStrategy, Google and Facebook Strategy but I am stuck on the Google one. What I am trying to do is get an access_token that will be passed back on my client and will be used in any future request.
I would like to create a stateless authentication because my client side will be a web app and in the future an Android app.
All the example that I found for GoogleStrategy is using passport.session() to store the logged in user in the session.
First question is: using passport.js for GoogleStrategy do I have to use mandatory the passport.session() ?
By docs GoogleStrategy return an accessToken and a refreshToken..but actually it doesn't!! The refreshToken is always undefined and the accessToken is something different from a jwt token, I thought it was the authorization_code that need to be exchanged with an access_token, but I'm not sure because if I try to exchange that token with an access token I receive an error. Any ideas of what accessToken on GoogleStrategy is?
Second question: is there any way to get jwt token from google? if no, assuming google strategy successful login... should I generate inside my GoogleStrategy my own token using jsonwebtoken library and pass it back on my client?
This is an example of what I'am saying:
passport.use(
new GoogleStrategy(
googleConfig,
async (accessToken, refreshToken, profile, done) => {
// accessToken..contains something different from a JWT token.
// refreshToken..is undefined!!
try {
const existingUser = await User.findOne({ "email": profile.emails[0].value});
if (existingUser) {
// 1. update providers adding the google if not present on user record
.....
// 2. generate access_token and refresh_token
const token = user.generateAccessToken();
const refreshToken = user.generateRefreshToken();
return done(null, {token, refreshToken});
}
// Create a new user on MongoDb.
// generate tokens and returns...
done(null, {....here goes generated tokens});
} catch (error) {
done(error, false);
}
}
)
);
// The generate token function inside my User model
conts jwt = require('jsonwebtoken');
userSchema.methods.generateAccessToken = function () { // this is just an example.
return jwt.sign({
id: this._id,
email: this.email
}, jwtSecret, { expiresIn: "15m" })
}
If you have any advice it will be appreciated.
Thank you all!

Authenticating Google Gmail API using access and refresh token

I have searched for an answer to this specifically but can't seem to find it. Apologies if it's a repeat.
I have the access token and the refresh token and want to send the emails using these tokens. The tokens are generated using the passport.js library and I am storing them in the DB along with other profile data. Like this
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_APP_CLIENT_ID,
clientSecret: process.env.GOOGLE_APP_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_APP_CALLBACK_URL,
passReqToCallback: true
},(request:any,accessToken: string, refreshToken: string, profile: any, done: any)=>{
//save credentials in database
}));
Now using the access token and the refresh token I want to access the Gmail API. Contrary to the example (https://developers.google.com/gmail/api/quickstart/nodejs) provided by Google. In which they are providing the Oauth client created from executing Oauth2 flow.
What is needed is something like this
const gmail = google.gmail({version: 'v1', auth:{accessToken,refreshToken});
In summary: Pretty much what DalmTo said in his comment. You need to also add the client ID, secret and redirect URL.
Explanation: It may be a little hard to see but the sample that you provided does show how to authenticate with locally stored information. I'll try to simplify it.
The most relevant parts are under the authorize() function:
//first create a google.auth.OAuth2 object
//for this you still have to use your app's client_id, client_secret and redirect_uri
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
The sample app creates a token.json file that it uses to reauthenticate. It's just a simple object with the tokens (there are a couple additional fields which I removed since they are not relevant to this):
{
"access_token":"ya29...",
"refresh_token":"1//..."
}
Then the sample shows that you have to call setCredentials() on the oAuth2Client object using this token file that was created.
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
Then once you have set the credentials to the oAuth2Client object you can use it to authorize the API:
const gmail = google.gmail({version: 'v1', oAuth2Client});
The sample works with a locally stored file, but since you store the tokens in your database in your case it might look more like this:
//get the tokens from somewhere in your database
const tokens = {
"access_token" : ACCESS_TOKEN,
"refresh_token" : REFRESH_TOKEN
}
const oAuth2Client = new google.auth.OAuth2(
process.env.GOOGLE_APP_CLIENT_ID,
process.env.GOOGLE_APP_CLIENT_SECRET,
process.env.GOOGLE_APP_CALLBACK_URL
);
oAuth2Client.setCredentials(tokens);
const gmail = google.gmail({version: 'v1', oAuth2Client});
You'll probably also need to handle reauthorization in case that the refresh token has expired or the user has revoked access but I hope this gives you a general idea.
More info: Google API's Node.js Client

Can't get user google account gender and birthday fields with google People API. (Using OAuth2client)

I am implementing authentication with google in my mobile flutter app. I get the access_token in my app, and then I send it to backend which is written with Node.js. And thene I need to fetch user basic info + birthday and gender. In Google Cloud Platform console I did all configs, I added certain scopes,'https://www.googleapis.com/auth/user.birthday.read', 'https://www.googleapis.com/auth/user.gender.read',. I enabled Google People API. But I still can not get birthday and gender. Here is backend part from.
const token =
"HARDCODED_ACCESS_TOKEN";
var google = require("googleapis").google;
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2();
oauth2Client.setCredentials({
access_token: token,
scope: "https://www.googleapis.com/auth/user.gender.read",
});
var oauth2 = google.oauth2({
auth: oauth2Client,
version: "v2",
});
oauth2.userinfo.get(function (err, res) {
if (err) {
console.log(err);
} else {
console.log(res.data);
}
});
And here what I got in response.
I tried almost everything, but still couldn't get gender and birthday.
In order to get information about gender and birthdays from the authenticated user, you can call People API's people.get with resourceName=people/me and personFields=genders,birthdays:
oauth2Client.setCredentials({
access_token: token,
});
const service = google.people({version: 'v1', auth: oauth2Client});
service.people.get({
resourceName: 'people/me',
personFields: 'genders,birthdays'
}, (err, res) => {
// Do your thing
});
Notes:
You didn't provide the code for most of the authentication process, but please note that the scopes have to be provided before retrieving the access_token, since the access token depends on those scopes. Also, I'd suggest you to set a refresh_token, since the access_token will expire in an hour. For more information about the OAuth process, please take a look at the Node.js quickstart.
It is assumed that both genders and birthdays are added to the authenticated user's account.

How to get users from azure active directory to azure function

I am developing a server less application using azure functions using Node js. Function app auth via azure active directory. My scenario is I want to get particular user data ex(email,username etc) by using his email or username during execution of one of http trigger function. There are several options that I already checked (ad and activedirectory libraries. These library seems not updated and I want to know is there any way to do this by using azure's Node Js SDK?
I am seeking a solution for without JWT. because, when 'function' need to get some user information function doesn't have any token.here user data requested by the function app not the user.Hence user data only use by the function app those info not exposed to user.
for Example: We can get user data by 'querying' user table when we need to get user data inside of some application running MySQL. If we specify email we can query.
I am asking same thing by using azure active directory.
You can get the access token using client credential flow(not related to specific user) in your function.
const APP_ID = '[COPIED_APP_ID]';
const APP_SECERET = '[COPIED_APP_SECRET]';
const TOKEN_ENDPOINT ='https://login.microsoftonline.com/[COPIED_TENANT_ID]/oauth2/v2.0/token';
const MS_GRAPH_SCOPE = 'https://graph.microsoft.com/.default';
const axios = require('axios');
const qs = require('qs');
const postData = {
client_id: APP_ID,
scope: MS_GRAPH_SCOPE,
client_secret: APP_SECERET,
grant_type: 'client_credentials'
};
axios.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded';
let token = '';
axios
.post(TOKEN_ENDPOINT, qs.stringify(postData))
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
Reference:
HOW TO — Get an Access Token for Microsoft Graph API using Node.JS
Then you can use this token to call Microsoft Graph API.

Google Contacts API nodejs

I've been looking through the Google NodeJS API docs, but I don't see one listed for the Contacts API. Am I missing something or is that not included in the module?
Google's official API for NodeJS doesn't use Contacts API. They use instead the People API. If you need to access "Other Contacts", you will need Contacts API.
You can still connect with Contacts API using the official googleapis library if you're already using it for other purposes by sending a request to the Contacts API after creating the auth client. If you're not using the googleapis library, it might be an overkill, and it's better to use the other libraries suggested by other answer.
Given that you already have the access token of the user (e.g. if you generated it using Passport, here's the code:
const {google} = require("googleapis");
const authObj = new google.auth.OAuth2({
access_type: 'offline',
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
});
Refresh access token automatically before it expires
authObj.on('tokens', (tokens) => {
const access_token = tokens.access_token
if (tokens.refresh_token){
this.myTokens.refreshToken = tokens.refresh_token
// save refresh token in the database if it exists
}
this.myTokens.accessToken = tokens.access_token
// save new access token (tokens.access_token)
}
authObj.setCredentials({
access_token:this.myTokens.accessToken,
refresh_token:this.myTokens.refreshToken,
});
Make the request to Contacts API:
authObj.request({
headers:{
"GData-Version":3.0
},
params:{
"alt":"json",
//"q":"OPTIONAL SEARCH QUERY",
//"startindex":0
"orderby":"lastmodified",
"sortorder":"descending",
},
url: "https://www.google.com/m8/feeds/contacts/default/full"
}).then( response => {
console.log(response); // extracted contacts
});
According to Google NodeJS API for Google Contacts API, the links below maybe could help you out:
https://github.com/jimib/nodejs-google-contacts
https://github.com/elentok/gcontacts
https://github.com/mattnull/node-googlecontacts

Resources