Search code examples
google-apidialogflow-esgoogle-oauthgoogle-home

Accessing google apis on behalf of google home user


I'm trying to develop a simple ProofOfConcept to interract with Google APIs from a Google Home using the authorization of the user through Dialogflow Fullfilment.

For example, we want to be able to create/read/update/delete contacts of users.

It's relatively easy to implement the Google SignIn but I don't know how to ask for additionnal scopes

Also, I never implemented an OAuth server before and I'm still not sure if I need too or if I could reuse en existing one.

I looked at many posts here on SO most of them was answered by @Prisoner who also provided a detailed flow in Google Home Authorization Code and Authentication with Google Account

In his answer, he mentions that we can "redirect the user to a web login page" but I still don't understand how to do that from the fullfilment

Here's the fullfilment code I used to use the Google SignIn:

//requirements
const { dialogflow, SignIn} = require('actions-on-google');
const functions = require('firebase-functions');

//initialisation
const app = dialogflow(
{
    debug: true,

    // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
    clientId: '1111111111111-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com'
});

//Welcome Intent
app.intent('Default Welcome Intent', (conv) => {
    conv.ask(`Welcome to the demo agent, say "Connect-me" to proceed`);
}); 

//Default Intent
app.intent('Default Fallback Intent', (conv) => {
    conv.ask(`Sorry, can you repeat please?`);
}); 

//Intent starting the Google SignIn
//  Create an intent with the name "Start Signin"
app.intent('Start Signin', (conv) => {
    //SignIn Helper (https://developers.google.com/actions/assistant/helpers#account_sign-in)
    conv.ask(new SignIn(`Need to identify you`));
});


//Intent called when the user complete the authentication
//  Create an intent with the name "Get Signin" and assign it the event "actions_intent_SIGN_IN"
app.intent('Get Signin', (conv, params, signin) => {
    if (signin.status === 'OK') {
        const payload = conv.user.profile.payload;

        conv.ask(`Hello ${payload.name}. You can now access your contacts informations...  but not really `);
    } else {
        conv.ask(`Sorry but you should authentify yourself `);
    }
});

//Example of intent that I would like to make it works
app.intent('How many contacts', (conv) => {
    /*
    TODO: How to ask for additional scopes ("https://www.google.com/m8/feeds/" : read/write access to Contacts and Contact Groups)
    NOTE: Actually, I'm more interrested on how to get the additional scopes.  
          I could probably do the querying contacts part by myself since it's quite documented (https://developers.google.com/contacts/v3/)
    */

    conv.ask(new SignIn(`You have ${nbContacts} contacts defined in your Google Contact`));
});

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

Solution

  • You have a few related questions bundled here.

    How do I ask for additional scopes with Google Sign In?

    Unfortunately you can't.

    This is for the user's security. Since it isn't always obvious when you're granting additional permissions via voice, and asking for too many scopes can be overwhelming with voice, they don't allow this right now.

    Ok. So how do I get those additional scopes?

    You referenced another post that goes through the method I propose to do that. It involves signing in and granting the scopes through a web page in the same Google Cloud Project. Under Google's cross-client identity system, these would then apply when the user connects through the Assistant as well.

    So how do I direct them to a web page?

    I typically either use a card with a link button for the website or a link out suggestion to the site. Both of these, however, depend on being on a visual interface that supports a web browser. So you might wish to check for this using surface capabilities.

    If you are using your own OAuth server, using the combination "OAuth and Google Sign-In" method, the Assistant will take care of these sorts of things for you.

    Do I need to write my own OAuth server?

    No. You can use something like Auth0 to handle the OAuth part for you.