简体   繁体   中英

Using Express Middleware in Actions on Google

As mentioned in other newbie question ( Google Assistant - Account linking with Google Sign-In ) I have an Express app which supports Google authentication and authorization via Passport and now with the help of @prisoner my Google Action (which runs off the same Express app) supports Google login in this way https://developers.google.com/actions/identity/google-sign-in .

My question now is how can I use the varous middlewares that my Express app has as part of the Google Assistant intent fullfillments? A couple of examples:

1) I have an intent

// Handle the Dialogflow intent named 'ask_for_sign_in_confirmation'.
gapp.intent('Get Signin', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    return conv.ask('You need to sign in before using the app.');
  }
  const payload = conv.user.profile.payload
  console.log(payload);
  conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
});

Now just because the user is signed in to Google in my action presumably doesn't mean that they have authenticated (via the Google Passport strategy) into my Express app generally? However from the above I do have access to payload.email which would enable me to use my site Google login function

passportGoogle.authenticate('google', 
    { scope: ['profile', 'email'] }));'  

which essentially uses Mongoose to look for a user with the same details

User.findOne({ 'google.id': profile.id }, function(err, user) {
    if (err)
    return done(err);

    // if the user is found, then log them in
    if (user) {
      return done(null, user);
     ....

ok, I would need to modify it to check the value of payload.email against google.email in my DB. But how do I associate this functionality from the Express app into the intent fullfillment?

2) Given the above Get Signin intent how could I exectute an Express middleware just to console.log('hello world') for now? For example:

gapp.intent('Get Signin', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    return conv.ask('You need to sign in before using the app.');
  }
  authController.assistantTest;
  const payload = conv.user.profile.payload
  console.log(payload);
  conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
});

Here authController.assistantTest; is

exports.assistantTest = (req, res) => {
    console.log('hello world');
};

Any help / links to docs really appreciated!

It looks like you're trying to add a piece of functionality that runs before your intent handler. In your case, it's comparing user's email obtained via Sign In versus what's stored in your database.

This is a good use case for a middleware from Node.js client library (scroll down to "Scaling with plugins and middleware " section). The middleware layer consists of a function you define that the client library automatically runs before the IntentHandler. Using a middleware layer lets you modify the Conversation instance and add additional functionality.

Applying this to your example gives:

gapp.middleware(conv => {
  // will print hello world before running the intent handler
  console.log('hello world');
});

gapp.intent('Get Signin', (conv, params, signin) => {
  if (signin.status !== 'OK') {
    return conv.ask('You need to sign in before using the app.');
  }
  authController.assistantTest;
  const payload = conv.user.profile.payload
  console.log(payload);
  conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
});

You could perform the authentication logic in the middleware, and potentially utilize conv.data by keeping track if user's email matched records from your database.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM