I am using google sign in on my app and I am using ionic v3 and the native google plugin so the user is directed to google to sign in and allow us access. Once the user allows access and I send the request to my backend where i use the userId sent from Google to get the users info. I get all the info I need except for the email address. Not sure why the users email is not showing up. Here is my backend code:
const plus = googleAPI.google.plus({
version: 'v1',
auth: 'My API Key'
});
plus.people.get({
userId: googleUserId,
fields: 'displayName,emails,name'
})
.then((user) => {
console.log('Google plus user: ' + JSON.stringify(user.data));
console.log('Emails: ' + user.data.emails)
})
.catch((err) => {
console.log('Google plus error: ' + err);
})
Seems like its a permissions issue because on the app I set a iOS webClientId which is different than my API key. If so how do I go about fixing it?
Figured it out the api call was missing the accessToken as part of the get
Related
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.
I am using Node.js on backend and creates a token for a user each time logins. angularx-social-login package makes it very easy to integrate Google OAuth with Angular but how to use it with API? After successful login the Google returns user information with token. I was thinking to send this information to backend and login the user but for that I need to create a route which accepts email address and logins user. And this will return JWT token which is not secure. By secure I mean, anyone can access the route without Google Authentication and generate token.
I am looking for ideas how developers achieved this.
I found google-auth-library client package for Node.js managed by Google.
Here is the follow:
Login user with Angular
Send the idToken to backend
Validate token and response to Angular
Node.js:
exports.googleLogin = function(req, res, next) {
//verify the token using google client
return googleClient
.verifyIdToken({
idToken: req.body.token,
audience: config.google.clientID
})
.then(login => {
//if verification is ok, google returns a jwt
var payload = login.getPayload();
var userid = payload['sub'];
//check if the jwt is issued for our client
var audience = payload.aud;
if (audience !== config.google.clientID) {
throw new Error(
'error while authenticating google user: audience mismatch: wanted [' +
config.google.clientID +
'] but was [' +
audience +
']'
);
}
//promise the creation of a user
return {
name: payload['name'], //profile name
pic: payload['picture'], //profile pic
id: payload['sub'], //google id
email_verified: payload['email_verified'],
email: payload['email']
};
})
.then(user => {
return res.status(200).json(user);
})
.catch(err => {
//throw an error if something gos wrong
throw new Error(
'error while authenticating google user: ' + JSON.stringify(err)
);
});
};
I was attempting to build a signup/signin application using Nodejs. By looking at the articles, I came to know that it's a good structure to design your app so that your backend is actually a RESTful API and your client accesses that API. (Both client & server running on different servers, whereas the client is just a plain old static file server).
Now things went smooth until I had to sign users in. When the API endpoint (/signin) with the specific data is accessed, the data is validated against the database and if Okay, I am signing a JSON Web Token and passing it along to the client.
But the problem is that with this, I can only secure routes on my API i.e. I can only enforce that a user must be signed in to access a specific backend API endpoint.
But what can I do to enforce the same thing on my client with this JWT? For example, if in my client I have dashboard.html and I want it only accessible to signed in users, a user can go ahead and get a JWT generated. But how does this JWT come into play about restricting client routes?
My Signin Route:
app.post('/signin', (req, res) => {
var data = req.body;
if (!exists(data.username) || !exists(data.password))
return res.status(422).json({
message: 'All fields are required'
});
const users = db.get('users');
users
.findOne({
username: data.username,
password: shajs('sha256').update(data.password).digest('hex')
})
.then((user) => {
if (user) {
jwt.sign({
_id: user._id,
username: user.username
}, 'keyboard_cat', {
expiresIn: '1h'
}, (err, tok) => {
return res.status(200).json({
message: 'OK',
token: tok
});
});
return;
}
return res.status(200).json({
message: 'Invalid Username or Password.'
})
});
});
You can use conditional render on the front-end side. You can fire an api with the api token (generated from '/signin' api) which will tell you wether the api token is valid or not whenever you enter the route.
On the basis of the response from the server about the token you can decide which page to render (normal one or the unauthorised page).
There is also a better approach, send the api token in every route in the header, and if the token is malformed or invalid return 401 error from backend. Catch this error globally(or you can use response interceptor which is provided by axios) and then do conditional rendering.
I use a custom auth scheme for Firebase. Tokens are generated by my nodejs backend:
mFirebase
.getAuth(token)
.createCustomToken(uid, claims)
.then(sendToken)
.
.
When I check out the "Users" section of Firebase console, the "Identifier" field is always empty.
I wonder if this is the expected behavior or I can provide additional things from my backend such as the username or email, to be displayed there.
This is expected. You need to set the email on the user if you want it to show.
You have 2 options.
set before you mint custom token:
return admin.auth().createUser({
uid: 'customUserUid',
email: 'user#example.com'
}).then((userRecord) => {
return admin.auth().createCustomToken(userRecord.uid);
}).catch((error) => {
// Error.
});
Update user email client side after sign in:
firebase.auth().signInWithCustomToken(customToken).then((result) => {
return result.user.updateEmail(userEmail);
}).catch((error) => {
// Error.
});
I'm using Google Play Android Developer API to server to server check subscription status of our users' subscriptions but after successful authorization and asking for an existing subscription I get the 401 response with the following message 'The current user has insufficient permissions to perform the requsted operation'.
Visiting https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=XXXXXX I can see that I do have the requested scope (https://www.googleapis.com/auth/androidpublisher) but I still get the same response everytime.
Did anyone else have the same problem?
Edit: I've seen what the Explore API app does, it adds the key in the query string of a request but I don't have that value. In the console I've created a Service Account Client Id which has a client id, email address and a private key but there is no API key which apparently Explore API uses.
Edit no. 2: I've added the service account generated email both to Google Play Developer Console and Google Wallet console but I still have no acces. I'm using nodejs and the google-oauth-jwt because there is not google provided lib for nodejs.
Here is the code I'm using to make a request:
var request = require('google-oauth-jwt').requestWithJWT();
function makeReq() {
request({
url: 'https://www.googleapis.com/androidpublisher/v1.1/applications/{packageName}/subscriptions/{subscriptionId}/purchases/{purchaseToken}',
jwt: {
// use the email address of the service account, as seen in the API console
email: 'blahblahtrutjtrutj#developer.gserviceaccount.com',
// use the PEM file we generated from the downloaded key
keyFile: 'purchases-test.pem',
// specify the scopes you wish to access
scopes: ['https://www.googleapis.com/auth/androidpublisher']
}
}, function (err, res, body) {
if (err) {
console.log(err);
} else {
console.log("BODY IS ------------------------------------------");
console.log(JSON.parse(body));
}
});
}
If your app is only released in a closed alpha track, you'll also have to add your service account's email address (client_email) to the License Testers at Settings -> Account detail in the Play Console.
There is an email address associated with your service account.
This needs to have appropriate permissions in both the dev console AND the Play store. Make sure to add the service address to the Play store.
The way I approached it was to use
var googleAuth = require('google-oauth-jwt'),
authObject = {
email: 'blahblahtrutjtrutj#developer.gserviceaccount.com',
keyFile: 'purchases-test.pem',
scopes: ['https://www.googleapis.com/auth/androidpublisher']
};
googleAuth.authenticate(authObject, function (err, token) {
next(err, token);
});
I store the token in redis for an hour and use that token to make my request to the store:
var opts = {
url : verifyUrl + payload.packageName + '/inapp/' + payload.productId + '/purchases/' + payload.token,
headers: {
authorization : 'Bearer ' + token
}
};
request.get(opts, function (error, response, body) {
next(error, response, body);
});