Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$request.getAccessToken() returns undefined in Google Conversational Actions #915

Closed
1 of 4 tasks
mig82 opened this issue Mar 29, 2021 · 9 comments
Closed
1 of 4 tasks

Comments

@mig82
Copy link

mig82 commented Mar 29, 2021

I'm submitting a...

  • Bug report
  • Feature request
  • Documentation issue or request
  • Other... Please describe:

Expected Behavior

In Google Conversational Actions...

const { GoogleAssistant } = require('jovo-platform-googleassistantconv')

after the user has successfully gone through the Account Linking Scene and linked their account, and returned to the ON_SIGN_IN handler, calling this.$request.getAccessToken() should return the access token.

Current Behavior

The function GoogleAction.$request.getAccessToken() is defined, yet it never returns the token, despite the account being linked.

console.log(`this.constructor: '${this.constructor.name}'`)
console.log(`typeof this.$request.getAccessToken: '${typeof this.$request.getAccessToken}'`)
console.log(`this.$request.getAccessToken(): '${this.$request.getAccessToken()}'`)

Error log

This is the output of the code above:

this.constructor: 'GoogleAction'
typeof this.$request.getAccessToken: 'function'
this.$request.getAccessToken(): 'undefined'

Your Environment

$ jovo -v

Jovo CLI Version: 3.2.1

Jovo packages of current project:
  jovo-core: 3.3.1
  jovo-db-filedb: 3.3.1
  jovo-framework: 3.3.1
  jovo-platform-alexa: 3.3.1
  jovo-platform-googleassistantconv: 3.3.2
  jovo-plugin-debugger: 3.3.2
@aswetlow
Copy link
Member

Hey @mig82

Could you provide the request JSON?

Thanks!

@mig82
Copy link
Author

mig82 commented Mar 31, 2021

Hi @aswetlow. What request are you referring to? the one coming back from the account linking scene? If so, this is it:

 >>>>> Request - 2021-03-31T18:03:53.170Z 
{
   "handler": {
      "name": "Jovo"
   },
   "intent": {
      "name": "",
      "params": {
         "AccountLinkingSlot": {
            "original": "",
            "resolved": "LINKED"
         }
      },
      "query": ""
   },
   "scene": {
      "name": "AccountLinkingScene_AccountLinking",
      "slotFillingStatus": "FINAL",
      "slots": {
         "AccountLinkingSlot": {
            "mode": "REQUIRED",
            "status": "SLOT_UNSPECIFIED",
            "updated": true,
            "value": "LINKED"
         }
      }
   },
   "session": {
      "id": "ABwppHHlsa*******-_**_**********************************************BWEHFg",
      "params": {
         "_JOVO_SESSION_": {
            "createdAt": "2021-03-31T18:02:46.367Z",
            "reprompts": {
               "NO_INPUT1": "<speak>Would you like to log in?</speak>"
            },
            "new": false
         },
         "AccountLinkingSlot": "LINKED",
         "_JOVO_STATE_": "OfferLogin.AwaitDecision"
      },
      "typeOverrides": [],
      "languageCode": ""
   },
   "user": {
      "locale": "en-US",
      "params": {
         "userId": "de21****-****-****-****-****6b84cf75"
      },
      "accountLinkingStatus": "LINKED",
      "verificationStatus": "VERIFIED",
      "packageEntitlements": [],
      "gaiamint": "",
      "permissions": [],
      "lastSeenTime": "2021-03-31T18:02:46Z"
   },
   "home": {
      "params": {}
   },
   "device": {
      "capabilities": [
         "SPEECH",
         "RICH_RESPONSE",
         "WEB_LINK",
         "LONG_FORM_AUDIO"
      ]
   }
}

@NLueg
Copy link
Contributor

NLueg commented Apr 1, 2021

I'm having the same Issue. I tried every getter for the access token without any success.
I managed to get the token with the following code:

export function getAccessToken(jovo: Jovo): string | undefined {
  if (jovo.$request && jovo.isAlexaSkill()) {
    return jovo.$request.getAccessToken();
  }

  // TODO: Temporary hack to receive the access-token
  if (jovo.isGoogleAction()) {
    const headers = jovo.$googleAction.$user.conversationalAction.$host.headers;
    const accessTokenWithBearer = headers['Authorization'] || headers['authorization'];
    return accessTokenWithBearer?.replace("Bearer ", "");
  }

  return undefined;
}

But I think that the problem is inside the ConversationalActionRequest. It seems to be expected, that the access token is inside the user but this is not the case for me too.

@aswetlow
Copy link
Member

aswetlow commented Apr 1, 2021

Oh yeah, I forgot about that one. Access tokens are located in the request headers now. Unfortunately, the ConversationalActionRequest class doesn't have access to the $host object (where we have access to the headers).

It's implemented for Sign In with Google in this.$googleAction.$user.getUserProfile(), but there's no helper method just for the token.

@NLueg provides a great workaround for now. I think we should move the $request.getAccessToken() from the request class to the Jovo class.

@NLueg
Copy link
Contributor

NLueg commented Apr 2, 2021

@aswetlow actually my workaround doesn't work if the action is hosted on Lambda and I don't really know why 😢
The headers are undefined when I try to get the access token. It works fine when I use jovo run.

Edit: It's because of the API-Gateway 🤦🏻 The gateway filters the headers so that lambda don't receives the headers.
Managed to modify the API-Gateway with this documentation: https://aws.amazon.com/de/premiumsupport/knowledge-center/custom-headers-api-gateway-lambda/.
I added this mapping template to Integration Requests:

{
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end
    #end  
  }
}

And this to the mapping template of the Integration Response:

$util.parseJson($input.json('$.body'))

Without it the lambda function won't receive the headers. It seems to be a general issue for the api gateway. If you want I could add this part to the documentation as a PR but I don't know if its relevant.

@aswetlow
Copy link
Member

We have a Conversational Action on Lambda (via API Gateway) and the headers are passed correctly.

How did you create the API gateway? From the Lambda configuration page or separately in the API gateway settings?

@NLueg
Copy link
Contributor

NLueg commented Apr 14, 2021

@aswetlow well, strange but okay. I created it exactly as described in the documentation as I didn't use the gateway before. But if it is working, then you can ignore it. I don't know what's different in my case.

@aswetlow
Copy link
Member

Could you log your headers object? Is just the bearer token missing or do you receive an empty object?

@aswetlow
Copy link
Member

aswetlow commented Jan 5, 2022

I close this issue due to inactivity.

@aswetlow aswetlow closed this as completed Jan 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants