Google Sign-In: how to easily decode token when using dialogflow-fulfillment library instead of...












0















I need to get the email address from Google user's profile.



I'm using Dialogflow and I implemented google-sign-in procedure to get the Client ID (issued by Google to your Actions), and I'm also fulfilling actions.intent.SIGN_IN intent (as explained here). I do receive the Google ID token that contains the user's Google profile information, the problem is about decoding the token.



If I were using Actions on Google client library for Node.js, I could just follow the example from google-sign-in authentication flow:




If you use the Actions on Google client library for Node.js, it takes care of validating and decoding the token for you, and gives you access to the profile content, as shown in the following code snippet:




const { dialogflow } = require('actions-on-google');
const app = dialogflow({
// REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
clientId: CLIENT_ID,
})

// Intent that starts the account linking flow.
app.intent('Start Signin', conv => {
conv.ask(new SignIn('To get your account details'))
})

// Create a Dialogflow intent with the `actions_intent_SIGN_IN` event.
app.intent('Get Signin', (conv, params, signin) => {
if (signin.status === 'OK') {
const payload = conv.user.profile.payload
conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
} else {
conv.ask(`I won't be able to save your data, but what do you want to do next?`)
}
})


The problem is that I'm using Dialogflow Fulfillment Library (because I'm working with Google Assistant and with other integrations as well).



From their sample code, I'm following this approach using the WebhookClient:



const functions = require('firebase-functions');
const { WebhookClient } = require('dialogflow-fulfillment');

function someIntent(agent) {
if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
// let conv = agent.conv( );
// do some google specific stuff... conv.ask( ... );
agent.add('You came from Actions on Google');
} else {
agent.add('You came from any other source...');
}
}

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
let intentMap = new Map( );
intentMap.set('some-intent', someIntent);
agent.handleRequest(intentMap);
});


So, the question is: Is it possible to pass my clientId (from my actions project) to dialogflow-fulfillment for it to decode the token (just as actions-on-google does)?



ps: I know there are JWT-decoding libraries and a suggested procedure I could follow to validate and decode the token. But since dialogflow-fulfillment I guess uses actions-on-google internally somehow, I'm just wondering whether there's a much easier way to do it.










share|improve this question





























    0















    I need to get the email address from Google user's profile.



    I'm using Dialogflow and I implemented google-sign-in procedure to get the Client ID (issued by Google to your Actions), and I'm also fulfilling actions.intent.SIGN_IN intent (as explained here). I do receive the Google ID token that contains the user's Google profile information, the problem is about decoding the token.



    If I were using Actions on Google client library for Node.js, I could just follow the example from google-sign-in authentication flow:




    If you use the Actions on Google client library for Node.js, it takes care of validating and decoding the token for you, and gives you access to the profile content, as shown in the following code snippet:




    const { dialogflow } = require('actions-on-google');
    const app = dialogflow({
    // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
    clientId: CLIENT_ID,
    })

    // Intent that starts the account linking flow.
    app.intent('Start Signin', conv => {
    conv.ask(new SignIn('To get your account details'))
    })

    // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event.
    app.intent('Get Signin', (conv, params, signin) => {
    if (signin.status === 'OK') {
    const payload = conv.user.profile.payload
    conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
    } else {
    conv.ask(`I won't be able to save your data, but what do you want to do next?`)
    }
    })


    The problem is that I'm using Dialogflow Fulfillment Library (because I'm working with Google Assistant and with other integrations as well).



    From their sample code, I'm following this approach using the WebhookClient:



    const functions = require('firebase-functions');
    const { WebhookClient } = require('dialogflow-fulfillment');

    function someIntent(agent) {
    if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
    // let conv = agent.conv( );
    // do some google specific stuff... conv.ask( ... );
    agent.add('You came from Actions on Google');
    } else {
    agent.add('You came from any other source...');
    }
    }

    exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    const agent = new WebhookClient({ request, response });
    let intentMap = new Map( );
    intentMap.set('some-intent', someIntent);
    agent.handleRequest(intentMap);
    });


    So, the question is: Is it possible to pass my clientId (from my actions project) to dialogflow-fulfillment for it to decode the token (just as actions-on-google does)?



    ps: I know there are JWT-decoding libraries and a suggested procedure I could follow to validate and decode the token. But since dialogflow-fulfillment I guess uses actions-on-google internally somehow, I'm just wondering whether there's a much easier way to do it.










    share|improve this question



























      0












      0








      0


      1






      I need to get the email address from Google user's profile.



      I'm using Dialogflow and I implemented google-sign-in procedure to get the Client ID (issued by Google to your Actions), and I'm also fulfilling actions.intent.SIGN_IN intent (as explained here). I do receive the Google ID token that contains the user's Google profile information, the problem is about decoding the token.



      If I were using Actions on Google client library for Node.js, I could just follow the example from google-sign-in authentication flow:




      If you use the Actions on Google client library for Node.js, it takes care of validating and decoding the token for you, and gives you access to the profile content, as shown in the following code snippet:




      const { dialogflow } = require('actions-on-google');
      const app = dialogflow({
      // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
      clientId: CLIENT_ID,
      })

      // Intent that starts the account linking flow.
      app.intent('Start Signin', conv => {
      conv.ask(new SignIn('To get your account details'))
      })

      // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event.
      app.intent('Get Signin', (conv, params, signin) => {
      if (signin.status === 'OK') {
      const payload = conv.user.profile.payload
      conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
      } else {
      conv.ask(`I won't be able to save your data, but what do you want to do next?`)
      }
      })


      The problem is that I'm using Dialogflow Fulfillment Library (because I'm working with Google Assistant and with other integrations as well).



      From their sample code, I'm following this approach using the WebhookClient:



      const functions = require('firebase-functions');
      const { WebhookClient } = require('dialogflow-fulfillment');

      function someIntent(agent) {
      if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
      // let conv = agent.conv( );
      // do some google specific stuff... conv.ask( ... );
      agent.add('You came from Actions on Google');
      } else {
      agent.add('You came from any other source...');
      }
      }

      exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
      const agent = new WebhookClient({ request, response });
      let intentMap = new Map( );
      intentMap.set('some-intent', someIntent);
      agent.handleRequest(intentMap);
      });


      So, the question is: Is it possible to pass my clientId (from my actions project) to dialogflow-fulfillment for it to decode the token (just as actions-on-google does)?



      ps: I know there are JWT-decoding libraries and a suggested procedure I could follow to validate and decode the token. But since dialogflow-fulfillment I guess uses actions-on-google internally somehow, I'm just wondering whether there's a much easier way to do it.










      share|improve this question
















      I need to get the email address from Google user's profile.



      I'm using Dialogflow and I implemented google-sign-in procedure to get the Client ID (issued by Google to your Actions), and I'm also fulfilling actions.intent.SIGN_IN intent (as explained here). I do receive the Google ID token that contains the user's Google profile information, the problem is about decoding the token.



      If I were using Actions on Google client library for Node.js, I could just follow the example from google-sign-in authentication flow:




      If you use the Actions on Google client library for Node.js, it takes care of validating and decoding the token for you, and gives you access to the profile content, as shown in the following code snippet:




      const { dialogflow } = require('actions-on-google');
      const app = dialogflow({
      // REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
      clientId: CLIENT_ID,
      })

      // Intent that starts the account linking flow.
      app.intent('Start Signin', conv => {
      conv.ask(new SignIn('To get your account details'))
      })

      // Create a Dialogflow intent with the `actions_intent_SIGN_IN` event.
      app.intent('Get Signin', (conv, params, signin) => {
      if (signin.status === 'OK') {
      const payload = conv.user.profile.payload
      conv.ask(`I got your account details, ${payload.name}. What do you want to do next?`)
      } else {
      conv.ask(`I won't be able to save your data, but what do you want to do next?`)
      }
      })


      The problem is that I'm using Dialogflow Fulfillment Library (because I'm working with Google Assistant and with other integrations as well).



      From their sample code, I'm following this approach using the WebhookClient:



      const functions = require('firebase-functions');
      const { WebhookClient } = require('dialogflow-fulfillment');

      function someIntent(agent) {
      if (agent.requestSource === agent.ACTIONS_ON_GOOGLE) {
      // let conv = agent.conv( );
      // do some google specific stuff... conv.ask( ... );
      agent.add('You came from Actions on Google');
      } else {
      agent.add('You came from any other source...');
      }
      }

      exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
      const agent = new WebhookClient({ request, response });
      let intentMap = new Map( );
      intentMap.set('some-intent', someIntent);
      agent.handleRequest(intentMap);
      });


      So, the question is: Is it possible to pass my clientId (from my actions project) to dialogflow-fulfillment for it to decode the token (just as actions-on-google does)?



      ps: I know there are JWT-decoding libraries and a suggested procedure I could follow to validate and decode the token. But since dialogflow-fulfillment I guess uses actions-on-google internally somehow, I'm just wondering whether there's a much easier way to do it.







      dialogflow actions-on-google






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 25 '18 at 12:59







      maganap

















      asked Nov 24 '18 at 18:59









      maganapmaganap

      522410




      522410
























          2 Answers
          2






          active

          oldest

          votes


















          1














          No, as far as I know the token verification is done in Dialogflow class in actions-on-google which handles all actions and communication with Dialogflow's API. That is replaced with WebhookClient in Dialogflow Fulfillment library which doesn't do that. You can check out this link for token verification.






          share|improve this answer































            0














            TL;DR



            const { OAuth2Client } = require('google-auth-library');
            const CLIENT_ID = '<your own actions client id>.apps.googleusercontent.com';
            const client = new OAuth2Client(CLIENT_ID);
            ...
            // Then, on intent fulfillment method:
            let conv = agent.conv( ); // Get Actions on Google library conversation object
            let payload = await conv.user._verifyProfile(client, CLIENT_ID); // payload.email


            Longer story:



            Thanks to @RezaNasiri's link to Using a Google API Client Library, I ended up searching where in actions-on-google source code google-auth-library was used.



            I found out that google Conversation object has an User object, which includes a _verifyProfile method. It's supposed to be hidden, though, so be careful when using this with a different library version.



            So, if using dialogflow-fulfillment webhook client:



            const { WebhookClient } = require('dialogflow-fulfillment');


            You need to add google-auth-library:



            const { OAuth2Client } = require('google-auth-library');
            const CLIENT_ID = '<your own client id>.apps.googleusercontent.com';
            const client = new OAuth2Client(CLIENT_ID);


            Then you can verify and decode the token like this. Here, signInGetData is the fulfillment method for the actions.intent.SIGN_IN intent:



            async function signInGetData(agent) {
            let ctx = agent.context.get('actions_intent_sign_in');
            let signin = ctx.parameters.SIGN_IN;
            let conv = agent.conv( ); // Get Actions on Google library conversation object

            if (signin.status === 'OK') {
            // let idToken = conv.user.profile.token; // here's the token, but we don't need it
            let payload = await conv.user._verifyProfile(client, CLIENT_ID); // <<-- HERE
            if ( payload.email ) {
            conv.ask(`Got your email: ${payload.email}`);
            } else {
            conv.ask(`Got profile but not authorized to get your email...`)
            }
            } else {
            conv.ask(`No access to user data. Never mind...`)
            }
            agent.add(conv);
            }





            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461422%2fgoogle-sign-in-how-to-easily-decode-token-when-using-dialogflow-fulfillment-lib%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              No, as far as I know the token verification is done in Dialogflow class in actions-on-google which handles all actions and communication with Dialogflow's API. That is replaced with WebhookClient in Dialogflow Fulfillment library which doesn't do that. You can check out this link for token verification.






              share|improve this answer




























                1














                No, as far as I know the token verification is done in Dialogflow class in actions-on-google which handles all actions and communication with Dialogflow's API. That is replaced with WebhookClient in Dialogflow Fulfillment library which doesn't do that. You can check out this link for token verification.






                share|improve this answer


























                  1












                  1








                  1







                  No, as far as I know the token verification is done in Dialogflow class in actions-on-google which handles all actions and communication with Dialogflow's API. That is replaced with WebhookClient in Dialogflow Fulfillment library which doesn't do that. You can check out this link for token verification.






                  share|improve this answer













                  No, as far as I know the token verification is done in Dialogflow class in actions-on-google which handles all actions and communication with Dialogflow's API. That is replaced with WebhookClient in Dialogflow Fulfillment library which doesn't do that. You can check out this link for token verification.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 24 '18 at 23:32









                  Reza NasiriReza Nasiri

                  6211115




                  6211115

























                      0














                      TL;DR



                      const { OAuth2Client } = require('google-auth-library');
                      const CLIENT_ID = '<your own actions client id>.apps.googleusercontent.com';
                      const client = new OAuth2Client(CLIENT_ID);
                      ...
                      // Then, on intent fulfillment method:
                      let conv = agent.conv( ); // Get Actions on Google library conversation object
                      let payload = await conv.user._verifyProfile(client, CLIENT_ID); // payload.email


                      Longer story:



                      Thanks to @RezaNasiri's link to Using a Google API Client Library, I ended up searching where in actions-on-google source code google-auth-library was used.



                      I found out that google Conversation object has an User object, which includes a _verifyProfile method. It's supposed to be hidden, though, so be careful when using this with a different library version.



                      So, if using dialogflow-fulfillment webhook client:



                      const { WebhookClient } = require('dialogflow-fulfillment');


                      You need to add google-auth-library:



                      const { OAuth2Client } = require('google-auth-library');
                      const CLIENT_ID = '<your own client id>.apps.googleusercontent.com';
                      const client = new OAuth2Client(CLIENT_ID);


                      Then you can verify and decode the token like this. Here, signInGetData is the fulfillment method for the actions.intent.SIGN_IN intent:



                      async function signInGetData(agent) {
                      let ctx = agent.context.get('actions_intent_sign_in');
                      let signin = ctx.parameters.SIGN_IN;
                      let conv = agent.conv( ); // Get Actions on Google library conversation object

                      if (signin.status === 'OK') {
                      // let idToken = conv.user.profile.token; // here's the token, but we don't need it
                      let payload = await conv.user._verifyProfile(client, CLIENT_ID); // <<-- HERE
                      if ( payload.email ) {
                      conv.ask(`Got your email: ${payload.email}`);
                      } else {
                      conv.ask(`Got profile but not authorized to get your email...`)
                      }
                      } else {
                      conv.ask(`No access to user data. Never mind...`)
                      }
                      agent.add(conv);
                      }





                      share|improve this answer




























                        0














                        TL;DR



                        const { OAuth2Client } = require('google-auth-library');
                        const CLIENT_ID = '<your own actions client id>.apps.googleusercontent.com';
                        const client = new OAuth2Client(CLIENT_ID);
                        ...
                        // Then, on intent fulfillment method:
                        let conv = agent.conv( ); // Get Actions on Google library conversation object
                        let payload = await conv.user._verifyProfile(client, CLIENT_ID); // payload.email


                        Longer story:



                        Thanks to @RezaNasiri's link to Using a Google API Client Library, I ended up searching where in actions-on-google source code google-auth-library was used.



                        I found out that google Conversation object has an User object, which includes a _verifyProfile method. It's supposed to be hidden, though, so be careful when using this with a different library version.



                        So, if using dialogflow-fulfillment webhook client:



                        const { WebhookClient } = require('dialogflow-fulfillment');


                        You need to add google-auth-library:



                        const { OAuth2Client } = require('google-auth-library');
                        const CLIENT_ID = '<your own client id>.apps.googleusercontent.com';
                        const client = new OAuth2Client(CLIENT_ID);


                        Then you can verify and decode the token like this. Here, signInGetData is the fulfillment method for the actions.intent.SIGN_IN intent:



                        async function signInGetData(agent) {
                        let ctx = agent.context.get('actions_intent_sign_in');
                        let signin = ctx.parameters.SIGN_IN;
                        let conv = agent.conv( ); // Get Actions on Google library conversation object

                        if (signin.status === 'OK') {
                        // let idToken = conv.user.profile.token; // here's the token, but we don't need it
                        let payload = await conv.user._verifyProfile(client, CLIENT_ID); // <<-- HERE
                        if ( payload.email ) {
                        conv.ask(`Got your email: ${payload.email}`);
                        } else {
                        conv.ask(`Got profile but not authorized to get your email...`)
                        }
                        } else {
                        conv.ask(`No access to user data. Never mind...`)
                        }
                        agent.add(conv);
                        }





                        share|improve this answer


























                          0












                          0








                          0







                          TL;DR



                          const { OAuth2Client } = require('google-auth-library');
                          const CLIENT_ID = '<your own actions client id>.apps.googleusercontent.com';
                          const client = new OAuth2Client(CLIENT_ID);
                          ...
                          // Then, on intent fulfillment method:
                          let conv = agent.conv( ); // Get Actions on Google library conversation object
                          let payload = await conv.user._verifyProfile(client, CLIENT_ID); // payload.email


                          Longer story:



                          Thanks to @RezaNasiri's link to Using a Google API Client Library, I ended up searching where in actions-on-google source code google-auth-library was used.



                          I found out that google Conversation object has an User object, which includes a _verifyProfile method. It's supposed to be hidden, though, so be careful when using this with a different library version.



                          So, if using dialogflow-fulfillment webhook client:



                          const { WebhookClient } = require('dialogflow-fulfillment');


                          You need to add google-auth-library:



                          const { OAuth2Client } = require('google-auth-library');
                          const CLIENT_ID = '<your own client id>.apps.googleusercontent.com';
                          const client = new OAuth2Client(CLIENT_ID);


                          Then you can verify and decode the token like this. Here, signInGetData is the fulfillment method for the actions.intent.SIGN_IN intent:



                          async function signInGetData(agent) {
                          let ctx = agent.context.get('actions_intent_sign_in');
                          let signin = ctx.parameters.SIGN_IN;
                          let conv = agent.conv( ); // Get Actions on Google library conversation object

                          if (signin.status === 'OK') {
                          // let idToken = conv.user.profile.token; // here's the token, but we don't need it
                          let payload = await conv.user._verifyProfile(client, CLIENT_ID); // <<-- HERE
                          if ( payload.email ) {
                          conv.ask(`Got your email: ${payload.email}`);
                          } else {
                          conv.ask(`Got profile but not authorized to get your email...`)
                          }
                          } else {
                          conv.ask(`No access to user data. Never mind...`)
                          }
                          agent.add(conv);
                          }





                          share|improve this answer













                          TL;DR



                          const { OAuth2Client } = require('google-auth-library');
                          const CLIENT_ID = '<your own actions client id>.apps.googleusercontent.com';
                          const client = new OAuth2Client(CLIENT_ID);
                          ...
                          // Then, on intent fulfillment method:
                          let conv = agent.conv( ); // Get Actions on Google library conversation object
                          let payload = await conv.user._verifyProfile(client, CLIENT_ID); // payload.email


                          Longer story:



                          Thanks to @RezaNasiri's link to Using a Google API Client Library, I ended up searching where in actions-on-google source code google-auth-library was used.



                          I found out that google Conversation object has an User object, which includes a _verifyProfile method. It's supposed to be hidden, though, so be careful when using this with a different library version.



                          So, if using dialogflow-fulfillment webhook client:



                          const { WebhookClient } = require('dialogflow-fulfillment');


                          You need to add google-auth-library:



                          const { OAuth2Client } = require('google-auth-library');
                          const CLIENT_ID = '<your own client id>.apps.googleusercontent.com';
                          const client = new OAuth2Client(CLIENT_ID);


                          Then you can verify and decode the token like this. Here, signInGetData is the fulfillment method for the actions.intent.SIGN_IN intent:



                          async function signInGetData(agent) {
                          let ctx = agent.context.get('actions_intent_sign_in');
                          let signin = ctx.parameters.SIGN_IN;
                          let conv = agent.conv( ); // Get Actions on Google library conversation object

                          if (signin.status === 'OK') {
                          // let idToken = conv.user.profile.token; // here's the token, but we don't need it
                          let payload = await conv.user._verifyProfile(client, CLIENT_ID); // <<-- HERE
                          if ( payload.email ) {
                          conv.ask(`Got your email: ${payload.email}`);
                          } else {
                          conv.ask(`Got profile but not authorized to get your email...`)
                          }
                          } else {
                          conv.ask(`No access to user data. Never mind...`)
                          }
                          agent.add(conv);
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 25 '18 at 12:58









                          maganapmaganap

                          522410




                          522410






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53461422%2fgoogle-sign-in-how-to-easily-decode-token-when-using-dialogflow-fulfillment-lib%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              To store a contact into the json file from server.js file using a class in NodeJS

                              Redirect URL with Chrome Remote Debugging Android Devices

                              Dieringhausen