web javascript Google Play API OAuth 2.0 access - javascript

Hello I have a problem with data loading from Google Play API. I tried to load leaderboard data from my game (Looney Invaders). I want show game statistic at my custom website. I tried to do this with "Google API Client Library for JavaScript" for "authorized" OAuth 2.0 access.
I used sample example of "authorized" access to a Google API (using OAuth 2.0).
Javascript code:
<script type="text/javascript">
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
//API key from google
apiKey: '***',
discoveryDocs: ["www.googleapis.com/discovery/v1/apis/games/v1/rest"],
//ClientID (for OAuth 2.0) from google develope console
clientId: '***',
scope: 'www.googleapis.com/auth/games'
}).then(function (data) {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
}, function (err) {
console.error('Our Error: ');
console.error(err);
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
makeApiCall();
}
}
function handleSignInClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
function handleSignOutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
function makeApiCall() {
// Make an API call to the People API, and print the user's given name.
console.log('api call');
return gapi.client.games.leaderboards.list()
.then(function(response) {
console.log(response);
}, function(reason) {
console.log(reason);
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
I test it locally at http://localhost, so I added "Authorized JavaScript origins" as localhost and "Authorized redirect URIs" as localhost/.
I have the following error result after API call (gapi.client.games.leaderboards.list()):
{
"error": {
"errors": [
{
"domain": "global",
"reason": "UserRegistrationIncomplete",
"message": "User has not completed registration."
}
],
"code": 401,
"message": "User has not completed registration."
}
}
Also initialization phase (gapi.client.init()) ends without any errors.
Please, help me to solve this problem, or tell what I do wrong?

Related

Google API demo does not work locally; GAPI is null

I copied Google's demo code from this tutorial:
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get
However, when I tried to run this locally, I get the error below.
testoJS.html:14 Uncaught TypeError: Cannot read property 'signIn' of null
at authenticate
I'm not sure why the gapi variable is null even though the code imports the api module beforehand.
Here is a copy of my code; my client id, api key, and spreadsheetid are correct - I tested those values in the above website's "try this API" section. The http request works great there and returns the spreadsheet's content. However, I can't seem to run it locally.
<html>
<head></head>
<body>
<script src="https://apis.google.com/js/api.js"></script>
<script>
/**
* Sample JavaScript code for sheets.spreadsheets.values.get
* See instructions for running APIs Explorer code samples locally:
* https://developers.google.com/explorer-help/guides/code_samples#javascript
*/
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/spreadsheets.readonly"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); });
}
function loadClient() {
gapi.client.setApiKey("API_KEY");
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/sheets/v4/rest")
.then(function() { console.log("GAPI client loaded for API"); },
function(err) { console.error("Error loading GAPI client for API", err); });
}
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.sheets.spreadsheets.values.get({
"spreadsheetId": "SPREADSHEETID",
"range": "A1:D4"
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
gapi.load("client:auth2", function() {
gapi.auth2.init({client_id: "CLIENT_ID"});
});
</script>
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>
</body>
</html>

Shared files can't access(get list of shared file) using drive.file scope Google Drive API

The file is shared success and the shared user gets an email notification, file display in the user google drive but when we try using API to get shared files, it is not working.
var SCOPES = ["https://www.googleapis.com/auth/drive.file", "profile"];
function createPermissions(fileId, body) {
gapi.client.load("drive", "v3", function() {
gapi.client.drive.permissions
.create({
fileId: fileId,
resource: body
})
.then(function(res) {
//console.log(res);
Swal.fire("Success!", "File has been success shared!", "success");
// do something
})
.catch(function(err) {
//console.log(err);
Swal.fire({
icon: "error",
title: "Oops...",
text: "Something went wrong! Plese try agian later!!",
footer: ""
});
// do something
});
});
}
The above code is working fine, the file is successfully shared but when shared user login in-app user can't access shared files.
Anyone please suggest/help to fix the above issue?
Thanks
I would suggest you call the Drive API in this way:
// This is a good scope for testing
const SCOPES = ["https://www.googleapis.com/auth/drive"];
// This code takes into consideration that you already did all the OAuth2.0 proccess
// correctly to connect to the Drive API
module.exports.init = async function (){
// Create the Drive service
const drive = google.drive({version: 'v3', oauth2Client});
// Create permissions for an user
await createPermissions(drive, null, null);
}
// This function will create the permissions to share a file using Promises
function createPermissions(drive, fileId, body){
// These parameters are for test, past the values you want as arguments
fileId = fileId || "your-file-id";
body = body || {
"role": "writer",
"type": "user",
"emailAddress": "user#domain"
};
// Create the promise and return the value from the promise if you want to
return new Promise((resolve, reject) => {
try {
// Call the endpoint, if there are no errors you will pass the results to resolve
// to return them as the value from your promise
return drive.permissions.create({
fileId: fileId,
resource: body
},
(err, results) => {
if(err) reject(`Drive error: ${err.message}`);
resolve(results);
});
} catch (error) {
console.log(`There was a problem in the promise: ${error}`);
}
});
}
I tried it and the files are shared successfully to the user I wanted. Keep in mind to build your body as:
{
"role": "writer",
"type": "user",
"emailAddress": "user#domain"
};
Docs
Here are some links to know more about the Drive API Permissions:
Permissions.
Permissions: create.

Getting File Not Found on Export of Google Drive

I'm getting a 404 file not found error when using the google drive v3 API. The file-Id I'm getting from google picker so I know the id is correct. The offending code is as following (javascript):
downloadFile: function () {
var _this = this;
gapi.client.init({
apiKey: this.developerKey,
clientId: this.clientId,
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'],
scope: 'https://www.googleapis.com/auth/drive'
}).then(function () {
// not working with private files
gapi.client.setToken(_this.oauthToken);
gapi.client.drive.files.export({
'fileId': _this.selectedFileId,
'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
}).then(function (response) {
console.log('success!');
});
}, function (error) {
console.log(error);
});
}, function (error) {
console.log(error);
});
}
Funnily enough it doesn't happen with all files only private files. So I assume the file not found error is just a generic response back from google indicating I wasn't allowed to access the file.
Oddly enough doing a files.get works fine:
gapi.client.drive.files.get({
fileId: _this.selectedFileId,
supportsTeamDrives: true
}).then(function (response) {
console.log('worked');
}, function (error) {
console.log('failed');
});
I saw this same error when I used the https://www.googleapis.com/auth/drive.file permission: to get export to work you need to have at least the https://www.googleapis.com/auth/drive.readonly permission granted to the OAuth token you are using.

Is there a way to execute spreadsheets.values.update without OAuth authentication?

I'm making a discord bot that will be open to the public to use, and it will work by updating a google spreadsheet with values given in a command. Unfortunately, from what I see in the API documentation's "Try this API" feature, I can only use Google OAuth v2. Using an API key as a form of authentication gives me the error: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. How can I make it so that a user doesn't need to sign in for this to work?
This is the code:
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/spreadsheets"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); });
}
function loadClient() {
return gapi.client.load("https://content.googleapis.com/discovery/v1/apis/sheets/v4/rest")
.then(function() { console.log("GAPI client loaded for API"); },
function(err) { console.error("Error loading GAPI client for API", err); });
}
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.sheets.spreadsheets.values.update({
"spreadsheetId": "1AFCiplLlZRdO5Phb4DUh8M8sKKnUimJftVDGH9UAA3M",
"range": "Ratings!H2",
"valueInputOption": "RAW",
"resource": {
"values": [
[
7.5
]
]
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
gapi.load("client:auth2", function() {
gapi.auth2.init({client_id: YOUR_CLIENT_ID});
});
Thank you if you can help me, this has been stumping me for a while now.
spreadsheet: https://docs.google.com/spreadsheets/d/1AFCiplLlZRdO5Phb4DUh8M8sKKnUimJftVDGH9UAA3M/edit#gid=569426832

Chrome Extension & FCM fetching registration token

I'm building a Chrome Extension that needs to be able to receive push notifications. An alternative would be polling the server every X seconds, but that doesn't seem like much of a good choice. For this reason I chose Firebase. The custom JWT token auth seems to be done and working. The next step is to fetch the registration token, and sending this to the server.
The problem:
The token seems to never be fetched:
var config = {
apiKey: "<KEY>",
authDomain: "<DOMAIN>",
messagingSenderId: "<SENDER_ID>"
};
var app = firebase.initializeApp(config);
var messaging = firebase.messaging(app);
function initApp() {
firebase.auth().onAuthStateChanged(function(user) {
if(user) {
// Update UI
fetchToken();
} else {
// no user is signed in
}
});
}
function fetchToken() {
messaging.requestPermission()
.then(function() {
messaging.getToken()
.then(function(currentToken) {
if (currentToken) {
sendRegistrationTokenToServer(currentToken);
} else {
console.log('No token available')
}
})
.catch(function(err) {
console.debug('An error occurred while retrieving token. ', err);
});
}).catch(function(err) {
console.log('Notification permissions denied.', err);
});
firebase.messaging().onTokenRefresh(function() {
messaging.getToken()
.then(function(refreshedToken) {
sendRegistrationTokenToServer(refreshedToken);
console.log('Token refreshed')
})
.catch(function(err) {
console.log('Unable to retrieve refreshed token', err);
});
});
}
$(document).ready(function() {
initApp();
// some other stuff
});
Does anyone know why the token isn't being fetched?
No network activity can be seen in the developer console (for fetching the token). Also no error is printed. I do, however, see network activity for getAccountInfo?key=<somekey> which carries an idToken with it, though I'm not certain this is a related request (response doesn't seem to return a token).
The problem is you cannot call messaging.requestPermission() from the background script. If the user has not allowed notifications, this call will attempt to prompt the user, which will fail silently. What you can do is request the notifications permission somewhere else in your extension that has a UI (e.g. your options page) with:
Notification.requestPermission().then((permission) => { ...
Once the user has allowed the permission you can use the Permissions API, to query if you have the permission, in place of the call to messaging.requestPermission(). This is a function I wrote to do this:
/**
* Determine if navigator Notifications permission has been granted
* Note: this will work from the background script of an extension,
* unlike the other solutions
* #see https://developers.google.com/web/updates/2015/04/permissions-api-for-the-web
* #see https://w3c.github.io/permissions/
* #see https://www.chromestatus.com/features/6443143280984064
* #returns {Promise<boolean>} true if granted
* #memberOf app.Notify
*/
hasNavigatorPermission: function() {
return navigator.permissions.query({
name: 'notifications',
}).then((status) => {
if (status.state === 'granted') {
return Promise.resolve(true);
}
return Promise.resolve(false);
});
},
And use it like this:
/**
* Get the registration token for fcm
* #returns {Promise<token>} A registration token for fcm
* #memberOf app.Fb
*/
getRegToken: function() {
return app.Notify.hasNavigatorPermission().then((granted) => {
if (!granted) {
return Promise.reject(new Error(ERROR_NOTIFICATIONS));
}
return _messaging.getToken();
}).then((token) => {
if (token) {
return Promise.resolve(token);
}
return Promise.reject(new Error(ERROR_TOKEN));
});
},
A couple other things to note:
Don't rely on Notification.permission in an extension. It does not have the correct value.
As of Chrome 59, if you dismiss the notifications dialog too many times while developing, it will stop displaying it for a period of time. You need to clear your browser data to get it to start displaying again.

Categories

Resources