Closed pauleeeeee closed 4 years ago
The library does handle the auto refreshing of tokens.
What happens when you try to start a new session when the token expires? I've never seen this happen (and I've had an instance of this running on a server for months).
Can you paste the error the next time you get it? I'm going to start a session and let it sit there and see what happens when I try again in an hour or so.
Thanks for your response. Here is the error:
Conversation Error: { Error: 16 UNAUTHENTICATED: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project. at Object.exports.createStatusError (/srv/node_modules/grpc/src/common.js:91:15) at ClientDuplexStream._emitStatusIfDone (/srv/node_modules/grpc/src/client.js:233:26) at ClientDuplexStream._receiveStatus (/srv/node_modules/grpc/src/client.js:211:8) at Object.onReceiveStatus (/srv/node_modules/grpc/src/client_interceptors.js:1311:15) at InterceptingListener._callNext (/srv/node_modules/grpc/src/client_interceptors.js:568:42) at InterceptingListener.onReceiveStatus (/srv/node_modules/grpc/src/client_interceptors.js:618:8) at /srv/node_modules/grpc/src/client_interceptors.js:1127:18 code: 16, metadata: Metadata { _internal_repr: { 'www-authenticate': [Array] }, flags: 0 }, details: 'Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.' }
I think it has to do with the fact that I am not passing an oAuth2Client object... although I wish too but can't because of typings file doesn't specify it...?
no no, oAuth2Client is optional (you can see in the example files), it's just another way to use the regular Google OAuth (say from a web sign-in) without having to ask the user to auth again.
Mind pasting some of your code? I didn't create the typings file (was a PR), but I'm happy to look at what you've got to see if I can find anything out of wack.
Thanks for your response again Here is my code:
import * as functions from 'firebase-functions';
import { google } from 'googleapis';
const OAuth2 = google.auth.OAuth2;
import {resolve} from 'path';
// const googleAssistantCredentials = require('../src/credentials.json');
// const googleAssistantTokens = require('../src/googleAssistantTokens.json');
const authConfig = {
keyFilePath: resolve(__dirname,'../src/googleAssistantCredentials.json'),
savedTokensPath: resolve(__dirname,'../src/googleAssistantTokens.json')
}
import GoogleAssistant = require("google-assistant");
export const googleAssistant = functions.https.onRequest((request, response)=>{
if (request.body.command){
var command = request.body.command;
const conversation = {
isNew:true,
textQuery:command
}
const startConversation = (conversation:any) => {
conversation
.on('response', (text:any) => {
console.log('Assistant Text Response:', text);
response.status(200).send(text);
})
.on('error', (error:any) => {
console.log('Conversation Error:', error);
response.status(200).send('failed');
});
}
const assistant: GoogleAssistant = new GoogleAssistant(authConfig);
assistant.on('ready', () => {
// start a conversation!
assistant.start(conversation);
})
.on('started', startConversation)
.on('error', (error:any) => {
console.log('Assistant Error:', error);
response.status(200).send('failed');
});
} else {
console.log('error no command received')
response.status(200).send('failed');
}
});
Maybe because I am declaring the auth config outside the scope of the cloud function?
Your code pasted a bit wacky, but it looks like you're going new GoogleAssistant each time there is a new request. You only need to init it once and then your startConversation call should happen on the request.
Yeah sorry about the formatting - I tried to fix it but it just wouldn't take. Thanks for the idea. I will move the init to the global scope outside of the cloud function, re-up my credentials, and try again.
so for formatting, wrap it in tripple tick `
(without the spaces)
Just wanted to check in to see how you made out. Moving the new GoogleAssistant
out of the request fix things up?
Hi endoplasmic,
So I moved the instantiation out of the function scope, but that means that the function could not receive the "ready" event (which means the callback to start did not fire). So I instead called the assistant.start() function which worked just fine. However, after one hour, I still got the unauthenticated error. I think it has to do with the way that your Auth module refreshes the token. I am using Firebase and I am just not sure that the tokens are refreshed and saved to the global memory of my Firebase instance. So, I used the oAuth2Client library to update my tokens myself on each function invocation (if necessary). Then I modified the index.d.ts file in your library to allow me to pass the oAuth2Client object. This worked for me. I would suggest configuring the library to allow the user to pass the oAuth2Client object. I know that you have done this in JS but, as I mentioned, you cannot do so in a strict TypeScript environment.
Hope that gives you some ideas... and thank you for this library and all of your help!
Glad you got it sorted. Would you mind doing a PR on that index file? That way others in your shoes can benefit!
It would be my very first pull request ever... So... Just be warned LOL
Does this library automatically handle refreshing the user's access token if the token is expired? It does not seem that way. More context:
Environment: Google Cloud Function Status: Works until access token expires. Then, invocations of the cloud function fail due to invalid credentials. Other information: