I want to authenticate gapi client library so I could create a spreadsheet on behalf of another user, i.e. oauth.
This code used to work:
gapi.load('client:auth2', function() {
gapi.auth2.init({
clientId: 'CLIENT_ID',
scope: 'https://www.googleapis.com/auth/spreadsheets',
}).then(function() {
return gapi.auth2.getAuthInstance().signIn();
}).then(function() {
console.log('Signed in!');
}, function(error) {
console.error(error);
});
});
Now however it is saying that gapi.auth2 is deprecated, so I try to do following
google.accounts.id.initialize({
client_id: 'CLIENT_ID',
callback: handleCredentialResponse
});
google.accounts.id.prompt();
function handleCredentialResponse(response) {
gapi.client.setToken(response.credential)
}
And then
function createSpreadsheet() {
gapi.client.sheets.spreadsheets
.create({
properties: {
title: "My New Spreadsheet",
},
})
.then((response) => {
// The spreadsheet is created successfully
console.log("Spreadsheet created:", response.result.spreadsheetUrl);
})
.catch((err) => {
console.error("Failed to create spreadsheet", err);
});
}
And this gives me "Missing credential error"
I've also tried setting credential like this:
gapi.auth.setToken({ access_token: token })
Same error.
What am I missing?
After some time I've figured it out and was able to authenticate gapi to use spreadsheets API.
I was confused by ID token and Authorization token, those are 2 different things. Without further due, here's the working example:
var token;
function initGoogle() {
// init client
const client = google.accounts.oauth2.initTokenClient({
client_id: "YOUR_CLIENT_ID",
callback: handleCredentialResponse,
scope: "https://www.googleapis.com/auth/spreadsheets",
});
// send authorize request
// this prompts user to grant access
client.requestAccessToken();
}
// this thing is needed to load spreadsheet client library JSON dicovery document
async function fetchDiscoveryDoc() {
const resp = await fetch(
"https://sheets.googleapis.com/$discovery/rest?version=v4"
);
return resp.json();
}
async function handleCredentialResponse(response) {
console.log("loading client library");
await new Promise((resolve) => {
gapi.load("client", () => {
resolve();
});
});
const discoDoc = await fetchDiscoveryDoc();
console.log("Loading spreadsheets");
// loading spreadsheet library using discovery document
await new Promise((resolve, reject) => {
gapi.client.load(discoDoc).then(() => {
console.log("Spreadsheets loaded");
resolve();
});
});
console.log("Setting authorization token");
gapi.client.setToken(response);
console.log("All set. Client is ready to make authorized API calls. Creating spreadsheet");
await gapi.client.sheets.spreadsheets.create({
properties: {
title: "My New Spreadsheet",
},
});
}
Note, that this is implicit authorization flow, that is less secure, but does not involve backend. Read more here: https://developers.google.com/identity/oauth2/web/guides/use-token-model