Alexa Web API for Games - Skill Manifest - alexa

I enabled Alexa Web API for Games under Interface on Alexa Skill.
When I get the Skill Manifest, I clearly see
{
"type": "ALEXA_PRESENTATION_HTML"
}
But when I ran the Test in Simulator I don't see the below in Request
...
"device": {
"deviceId": "amzn1.ask.device.XXXX",
"supportedInterfaces": {
**"Alexa.Presentation.HTML": {
"runtime": {
"maxVersion": "1.0"
}**
}
}
},
Am I missing something.

This is because the simulator does not support Alexa.Presentation.HTML
You will get this request when you try your skill on an Echo show device or FireTv.

Related

Which token from Google's Social Login API should you use for securing back-end data in a public-facing ReactJS app?

I am using the Google Sign-In API documented here: https://developers.google.com/identity/sign-in/web/sign-in to let users sign-in to a ReactJS app.
When control is back to the app, I see this json coming from the api:
{
"Ba": "999888988999898999999",
"wc": {
"token_type": "Bearer",
"access_token": "ya99.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_Gt9hSnCbfgLfXXJpV9oGnJypUrN5cwrS8YBBHctEMLumSPhLDMmGEauaiHoTAWsdDTEY9OEaaAK9AeQa58pUp9SjiElHGMiU8UXT8cOpXyUMIXhXydHaMkXj",
"scope": "email profile openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
"login_hint": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYpasAM9f89UaNK9wHcHDJrcH-KAPpI99eCwn8CdOE5YFBtCJQDCqaaI9pLyaaRqA",
"expires_in": 9599,
"id_token": "eyJhbGciOiJSUaI9NiIsImtpaCI8IjNkaDajYTJhODFkYaJmaWE9YaM9NDI9MaFlN9UyOTakMmQ9NWI9NDYiLCJ9eXAiOiJKV9QifQ.eyJpc9MiOiJhY9NvdW59cy5nb99nbGUuY99tIiwiYXpwIjoiMjk9NTg9MTA9NTQ9LXRlNWR9bnY9c9BhcHAaNac9dGpraWptNWp9cjBmNjBnLmFwcHMua99va9xldXNlcmNvbnRlbnQuY99tIiwiYXVkIjoiMjk9NTg9MTA9NTQ9LXRlNWR9bnY9c9BhcHAaNac9dGpraWptNWp9cjBmNjBnLmFwcHMua99va9xldXNlcmNvbnRlbnQuY99tIiwic9ViIjoiMTEaNag9Mjg9MDIxNjQ9MjIyMTI5IiwiaW9haWwiOiJ9aXN9dXNlcjMxN9hAa99haWwuY99tIiwiaW9haWxfdmVyaWapaWQiOnRydWUsImF9X9hhc9giOiJuV9h5b9tTRFFXMFFMVkJOWlaNTja9IiwibmFtaSI8IlRlc9QgVXNlciIsInBpY9R9cmUiOiJodHRwcaovL9xoMy5nb99nbGV9c9VyY99udGVudC5jb99vYS9BQVRYQUp9dlo5alNuRGtKakkwS99iM9FmdTJfR9haMXFjLVhkSVltc9tyOD9aOTYtYyIsImdpdmVuX95hbWUiOiJUaXN9IiwiamFtaWx5X95hbWUiOiJVc9VyIiwibG9jYWxlIjoiaW9iLCJpYXQiOjE9NDY9MTA9MaUsImV9cCI8MTY9NjUxNDIaNSwianRpIjoiYTkwN9JjNTljNDUyNjljaDJmYTE5OGYyNGYwY9E9NjIyM9VjaTgaYiJ9.HYIamlf98xyo9ah9WennYB8ob8N9JaOxs8drmA8PdOy89emO8R_UVn9_F9YmKsBicMYMmUeis-9_hBijayOahDXQuEhu8gm8AsAhdq5GfP89hfb9G9h9UyPEdMWb9y9w-q9EayXsArDp9A9yT8AGGaRpF5i-tNmtwL8mlDJaFyh9UuIMlyCpYjhyD9lbCvGcVI9dbogcMkal-PnxY9S58Uw8SFsyOLJqWk9bTmQNqjQrwbBooWav99IxcDXjnJixmp9naTxBqAv5J9mEpFwQKbKSbbcNraJQLJvuacVEAVCR9ueOVOXlbOehj8b8SRlB89rrjgjmrqb9LdsMit8kew",
"session_state": {
"extraQueryParams": {
"authuser": "9"
}
},
"first_issued_at": 9898599895889,
"expires_at": 9898599999889,
"idpId": "google"
},
"Du": {
"FW": "999888988999898999999",
"tf": "Test User",
"VX": "Test",
"iW": "User",
"eN": "https://lh9.googleusercontent.com/a/AATXAJxva9fSnDkJjI9K_b9Afu9_Gha9qc-XdIYmsKr8=s98-c",
"tv": "xxxxxxxxxxxx#gmail.com"
},
"googleId": "999888988999898999999",
"tokenObj": {
"token_type": "Bearer",
"access_token": "ya99.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_Gt9hSnCbfgLfXXJpV9oGnJypUrN5cwrS8YBBHctEMLumSPhLDMmGEauaiHoTAWsdDTEY9OEaaAK9AeQa58pUp9SjiElHGMiU8UXT8cOpXyUMIXhXydHaMkXj",
"scope": "email profile openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
"login_hint": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYpasAM9f89UaNK9wHcHDJrcH-KAPpI99eCwn8CdOE5YFBtCJQDCqaaI9pLyaaRqA",
"expires_in": 9599,
"id_token": "eyJhbGciOiJSUaI9NiIsImtpaCI8IjNkaDajYTJhODFkYaJmaWE9YaM9NDI9MaFlN9UyOTakMmQ9NWI9NDYiLCJ9eXAiOiJKV9QifQ.eyJpc9MiOiJhY9NvdW59cy5nb99nbGUuY99tIiwiYXpwIjoiMjk9NTg9MTA9NTQ9LXRlNWR9bnY9c9BhcHAaNac9dGpraWptNWp9cjBmNjBnLmFwcHMua99va9xldXNlcmNvbnRlbnQuY99tIiwiYXVkIjoiMjk9NTg9MTA9NTQ9LXRlNWR9bnY9c9BhcHAaNac9dGpraWptNWp9cjBmNjBnLmFwcHMua99va9xldXNlcmNvbnRlbnQuY99tIiwic9ViIjoiMTEaNag9Mjg9MDIxNjQ9MjIyMTI5IiwiaW9haWwiOiJ9aXN9dXNlcjMxN9hAa99haWwuY99tIiwiaW9haWxfdmVyaWapaWQiOnRydWUsImF9X9hhc9giOiJuV9h5b9tTRFFXMFFMVkJOWlaNTja9IiwibmFtaSI8IlRlc9QgVXNlciIsInBpY9R9cmUiOiJodHRwcaovL9xoMy5nb99nbGV9c9VyY99udGVudC5jb99vYS9BQVRYQUp9dlo5alNuRGtKakkwS99iM9FmdTJfR9haMXFjLVhkSVltc9tyOD9aOTYtYyIsImdpdmVuX95hbWUiOiJUaXN9IiwiamFtaWx5X95hbWUiOiJVc9VyIiwibG9jYWxlIjoiaW9iLCJpYXQiOjE9NDY9MTA9MaUsImV9cCI8MTY9NjUxNDIaNSwianRpIjoiYTkwN9JjNTljNDUyNjljaDJmYTE5OGYyNGYwY9E9NjIyM9VjaTgaYiJ9.HYIamlf98xyo9ah9WennYB8ob8N9JaOxs8drmA8PdOy89emO8R_UVn9_F9YmKsBicMYMmUeis-9_hBijayOahDXQuEhu8gm8AsAhdq5GfP89hfb9G9h9UyPEdMWb9y9w-q9EayXsArDp9A9yT8AGGaRpF5i-tNmtwL8mlDJaFyh9UuIMlyCpYjhyD9lbCvGcVI9dbogcMkal-PnxY9S58Uw8SFsyOLJqWk9bTmQNqjQrwbBooWav99IxcDXjnJixmp9naTxBqAv5J9mEpFwQKbKSbbcNraJQLJvuacVEAVCR9ueOVOXlbOehj8b8SRlB89rrjgjmrqb9LdsMit8kew",
"session_state": {
"extraQueryParams": {
"authuser": "9"
}
},
"first_issued_at": 9898599895889,
"expires_at": 9898599999889,
"idpId": "google"
},
"tokenId": "eyJhbGciOiJSUaI9NiIsImtpaCI8IjNkaDajYTJhODFkYaJmaWE9YaM9NDI9MaFlN9UyOTakMmQ9NWI9NDYiLCJ9eXAiOiJKV9QifQ.eyJpc9MiOiJhY9NvdW59cy5nb99nbGUuY99tIiwiYXpwIjoiMjk9NTg9MTA9NTQ9LXRlNWR9bnY9c9BhcHAaNac9dGpraWptNWp9cjBmNjBnLmFwcHMua99va9xldXNlcmNvbnRlbnQbnQuY99tIiwic9ViIjoiMTEaNag9Mjg9MDIxNjQ9MjIyMTI5IiwiaW9haWwiOiJ9aXN9dXNlcjMxN9hAa99haWwuY99tIiwiaW9haWxfdmVyaWapaWQiOnRydWUsImF9X9hhc9giOiJuV9h5b9tTRFFXMFFMVkJOWlaNTja9IiwibmFtaSI8IlRlc9QgVXNlciIsInBpY9R9cmUiOiJodHRwcaovL9xoMy5nb99nbGV9c9VyY99udGVudC5jb99vYS9BQVRYQUp9dlo5alNuRGtKakkwS99iM9FmdTJfR9haMXFjLVhkSVltc9tyOD9aOTYtYyIsImdpdmVuX95hbWUiOiJUaXN9IiwiamFtaWx5X95hbWUiOiJVc9VyIiwibG9jYWxlIjoiaW9iLCJpYXQiOjE9NDY9MTA9MaUsImV9cCI8MTY9NjUxNDIaNSwianRpIjoiYTkwN9JjNTljNDUyNjljaDJmYTE5OGYyNGYwY9E9NjIyM9VjaTgaYiJ9.HYIamlf98xyo9ah9WennYB8ob8N9JaOxs8drmA8PdOy89emO8R_UVn9_F9YmKsBicMYMmUeis-9_hBijayOahDXQuEhu8gm8AsAhdq5GfP89hfb9G9h9UyPEdMWb9y9w-q9EayXsArDp9A9yT8AGGaRpF5i-tNmtwL8mlDJaFyh9UuIMlyCpYjhyD9lbCvGcVI9dbogcMkal-PnxY9S58Uw8SFsyOLJqWk9bTmQNqjQrwbBooWav99IxcDXjnJixmp9naTxBqAv5J9mEpFwQKbKSbbcNraJQLJvuacVEAVCR9ueOVOXlbOehj8b8SRlB89rrjgjmrqb9LdsMit8kew",
"accessToken": "ya99.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_Gt9hSnCbfgLfXXJpV9oGnJypUrN5cwrS8YBBHctEMLumSPhLDMmGEauaiHoTAWsdDTEY9OEaaAK9AeQa58pUp9SjiElHGMiU8UXT8cOpXyUMIXhXydHaMkXj",
"profileObj": {
"googleId": "999888988999898999999",
"imageUrl": "https://lh9.googleusercontent.com/a/AAXXXXXXXI9K_b9Afu9_Gha9qc-XdIYmsKr8=s98-c",
"email": "xxxxxxxxxxxx#gmail.com",
"name": "Test User",
"givenName": "Test",
"familyName": "User"
}
}
Now I want to store some data associated with the logged-in user, for example, their site preferences, and associate it to their social login.
If this was a regular non-social user with just an ID and Password, I would use a secret derived from the ID & password to authenticate the user to a custom back-end API when storing and retrieving the data. This way an attacker hacking the ReactJS app cannot retrieve information associated with a different user.
However with this social login, there is no password. What should I use instead from the Google Response to secure the call to the back-end?
I presume I need a token which is generated by Google, and is permanent as well as unique to both the user and my web app. Unless I'm doing something completely wrong and what I need is for the back-end API to talk to Google directly. How is this supposed to work?
WHAT HAVE I TRIED SO FAR
I have placed a console.log() call after the Google API call, which let me inspect the json returned as per the above. Then I realized the json is not self-explanatory at all, and this is not something I can solve by trial-and-error. Also, I checked the documentation and discovered that it says nothing about this scenario.

Alexa skill is giving 'There was a problem with the requested skill's response', can we change this message to custom message?

I am new to Alexa skill, and I am developing an Alexa skill, in my case there are scenario when I don't want to wait for http response to back and if my lambda timeouts due to delay in response from Http can I give a custom message in place of 'There was a problem with the requested skill's response'. My code is :
'ProtectArmIntent': function() {
if(checkAccessToken(this.event.session.user.accessToken)){
var data = {
mode: HUB_MODE.ARM,
regId: "null"
}
callAPI("post", API_COMMANDS.HUB_MODE, data, this.event.session.user.accessToken)
.then((body) => {
if(body.response.status === "SUCCESS"){
this.emit(':tell', messages.ARM.SUCCESSFUL);
} else {
this.emit(':tell', messages.ARM.FAILED);
}
})
.catch((err) => {
this.emit('SessionEndedRequest');
//errorHandler.call(this, err, messages.ARM.FAILED);
});
} else {
this.emit('LinkAccount');
}
},
and alexa simulator request:
"request": {
"type": "SessionEndedRequest",
"requestId": "amzn1.echo-api.request.67e1612e-f8a4-43f5-ab28-175ba7d7941f",
"timestamp": "2019-11-13T21:13:11Z",
"locale": "en-GB",
"reason": "ERROR",
"error": {
"type": "INVALID_RESPONSE",
"message": "An exception occurred while dispatching the request to the skill."
}
}
I know the issue is because lambda timeout as delay in the HTTP response, so can I give some customize message like Your command is accepted and it will be executed in some time.
Please please help, Thanks in advance
Making your own timer function might help. Set your timer lower than the lambda timeout and send your response at the end of the timer which will of course not lead to a lambda timeout error.This answer might help.

How to show the current playing item (song) in player or queue screen in alexa app

I am able to send the songs to amazon echo devices and the song is playing. I am not understanding what i have to send to show the song in the player or queue screen in alexa app as it is coming to other music apps like saavn, spotify etc. Please let me know if there are any link or info regarding this.
]1
Check out Amazon's AudioPlayer Interface Reference. It gives a pretty comprehensive guide on how to make the audio interface work. Essentially, it boils down to adding another directive to the list of directives you're returning in your response JSON. For me, this will automatically come up with the audio player screen.
A basic version of the audio directive looks like the following:
{
"type": "AudioPlayer.Play",
"playBehavior": "ENQUEUE",
"audioItem": {
"stream": {
"token": "Audio Playback",
"url": "http://www.audio.com/this/is/the/url/to/the/audio",
"offsetInMilliseconds": 0
}
}
}
ENQUEUE adds the specified stream to the end of the current stream queue. The offsetInMilliseconds key sets how far into the stream (in milliseconds) playback should begin.
When you nest this into the larger response JSON, it takes on the form of following:
{
"version": "1.0",
"sessionAttributes": {},
"response": {
"outputSpeech": {},
"card": {},
"reprompt": {},
"directives": [
{
"type": "AudioPlayer.Play",
"playBehavior": "ENQUEUE",
"audioItem": {
"stream": {
"token": "Audio Playback",
"url": "http://www.audio.com/this/is/the/url/to/the/audio",
"offsetInMilliseconds": 0
}
}
}
],
"shouldEndSession": true
}
}
There are a handful of other options to include in your audio directive. These can be found in the link I mentioned above.
I find it most beneficial to make a function where you can pass in given values to create the AudioPlayer directive JSON. For example, in python, this may look like the following:
def build_audio_directive(play_behavior, token, url, offset)
return {
"type": "AudioPlayer.Play",
"playBehavior": play_behavior,
"audioItem": {
"stream": {
"token": token,
"url": url,
"offsetInMilliseconds": offset
}
}
}
There are multiple ways to build up the response, but I find this way is the easiest for me to visualize.

Problems with Azure application manifest trying to authenticate with office-js-helpers in an Outlook web add-in

I'm using office-js-helpers in order to get an OAuth token in my Outlook web add-in so I can use it for OAuthCredentials with the EWS Managed API (code for that is in an Azure App Service using the ASP.NET Web API).
I have configured my app's application registration in my test Office 365 tenant (e.g. mytenant.onmicrosoft.com, which is NOT the same Azure subscription hosting the web app - if that matters) as a Native app with oauth2AllowImplicitFlow set to true. I used a Native app type instead of a Web/API app to bypass an unexpected error indicating my app requires admin consent - even though no application permissions were requested - but that's another story (perhaps I must use Native anyway - not 100% sure).
I made sure that the Redirect URI (aka reply URL) in the app registration points to the same page as the Outlook add-in (e.g. https://mywebapp.azurewebsites.net/MessageRead.html).
Here is my app manifest:
{
"appId": "a11aaa11-1a5c-484a-b1d6-86c298e8f250",
"appRoles": [],
"availableToOtherTenants": true,
"displayName": "My App",
"errorUrl": null,
"groupMembershipClaims": null,
"optionalClaims": null,
"acceptMappedClaims": null,
"homepage": "https://myapp.azurewebsites.net/MessageRead.html",
"identifierUris": [],
"keyCredentials": [],
"knownClientApplications": [],
"logoutUrl": null,
"oauth2AllowImplicitFlow": true,
"oauth2AllowUrlPathMatching": false,
"oauth2Permissions": [],
"oauth2RequiredPostResponse": false,
"objectId": "a11aaa11-99a1-4044-a950-937b484deb8e",
"passwordCredentials": [],
"publicClient": true,
"supportsConvergence": null,
"replyUrls": [
"https://myapp.azurewebsites.net/MessageRead.html"
],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6",
"type": "Scope"
},
{
"id": "a42657d6-7f20-40e3-b6f0-cee03008a62a",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000002-0000-0ff1-ce00-000000000000",
"resourceAccess": [
{
"id": "2e83d72d-8895-4b66-9eea-abb43449ab8b",
"type": "Scope"
},
{
"id": "ab4f2b77-0b06-4fc1-a9de-02113fc2ab7c",
"type": "Scope"
},
{
"id": "5eb43c10-865a-4259-960a-83946678f8dd",
"type": "Scope"
},
{
"id": "3b5f3d61-589b-4a3c-a359-5dd4b5ee5bd5",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null
}
I also made sure to add the authority URLs to my add-in's manifest:
<AppDomains>
<AppDomain>https://login.windows.net</AppDomain>
<AppDomain>https://login.microsoftonline.com</AppDomain>
</AppDomains>
This is the code I'm using in the add-in for the authentication with office-js-helpers:
// The Office initialize function must be run each time a new page is loaded.
Office.initialize = function(reason) {
$(document).ready(function () {
// Determine if we are running inside of an authentication dialog
// If so then just terminate the running function
if (OfficeHelpers.Authenticator.isAuthDialog()) {
// Adding code here isn't guaranteed to run as we need to close the dialog
// Currently we have no realistic way of determining when the dialog is completely
// closed.
return;
}
// Create a new instance of Authenticator
var authenticator = new OfficeHelpers.Authenticator();
authenticator.endpoints.registerAzureADAuth('a11aaa11-1a5c-484a-b1d6-86c298e8f250', 'mytenant.onmicrosoft.com');
// Add event handler to the button
$('#login').click(function () {
$('#token', window.parent.document).text('Authenticating...');
authenticator.authenticate('AzureAD', true)
.then(function (token) {
// Consume and store the acess token
$('#token', window.parent.document).text(prettify(token));
authToken = token.access_token;
})
.catch(function (error) {
// Handle the error
$('#token', window.parent.document).text(prettify(error));
});
});
});
};
Now the code in the add-in can properly sign in the user and ask for the required permissions, but after clicking the Accept button on the application authorization step the following error is returned:
AADSTS50011: The reply address 'https://mywebapp.azurewebsites.net' does not match the reply addresses configured for the application: 'a11aaa11-1a5c-484a-b1d6-86c298e8f250'. More details: not specified
The error now returns every time I click the Login button (the user is no longer prompted to sign in). It never did retrieve the token. The full auth URL is:
https://login.windows.net/mydomain.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=a11aaa11-484a-b1d6-86c298e8f250&redirect_uri=https%3A%2F%2Fmywebapp.azurewebsites.net&resource=https%3A%2F%2Fgraph.microsoft.com&state=982599964&nonce=3994725115
What am I doing wrong? Could the issue actually be because the host name of the web app (the redirect URI) does not match the domain of the Azure AD tenant hosting the app registration? If so, how can I grant permissions to Exchange Online from my Azure subscription hosting the web app which does not have Office 365 or Exchange Online? Would I have to add an Azure subscription to my test Office 365 tenant so that it can also host a web application??
From your app manifest, I found that you used https://myapp.azurewebsites.net/MessageRead.html as one of the replyUrls.
And below is the url that you are using to get consent from user.
https://login.windows.net/mydomain.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=a11aaa11-484a-b1d6-86c298e8f250&redirect_uri=https%3A%2F%2Fmywebapp.azurewebsites.net&resource=https%3A%2F%2Fgraph.microsoft.com&state=982599964&nonce=3994725115.
If you observe above url, you mentioned redirect_uri as https://myapp.azurewebsites.net. But redirect_uri should match with at least one of the replyUrls you mentioned in the app manifest.
Try to replace https://myapp.azurewebsites.net with https://myapp.azurewebsites.net/MessageRead.html in authorization url.
I have updated them in below url, if you want you can directly try below url.
https://login.windows.net/mydomain.onmicrosoft.com/oauth2/authorize?response_type=token&client_id=a11aaa11-484a-b1d6-86c298e8f250&redirect_uri=https%3A%2F%2Fmywebapp.azurewebsites.net%2FMessageRead.html&resource=https%3A%2F%2Fgraph.microsoft.com&state=982599964&nonce=3994725115

How do I handle 'Yes'/'No' responses from the user in Custom Skill?

I am trying to build an alexa custom skill. I am facing an issue where I am trying to get Yes/No responses from the user for a question which the skill asks the user.
Alexa: Would you like to know the rules of the game?
User: <Can respond either Yes or No>
Based on the user response I would like to perform a specific action.
Here is my intent schema:
{
"intents": [
{
"intent": "AMAZON.StopIntent"
},
{
"intent": "AMAZON.CancelIntent"
},
{
"intent": "AMAZON.HelpIntent"
},
{
"intent": "StartGame"
},
{
"intent": "GetRules"
}
]
}
Here are my sample utterances:
StartGame Begin the game
StartGame Start the game
GetRules What are the rules
GetRules Get the rules
GetRules Tell me the rules
GetRules Tell me the rules again
The question the skill asks the user is below:
Welcome to the game. Would you like me to tell you the rules?
Whenever I say "Yes", the StartGame intent is what is being triggered. (Same is the case for "No"). Alexa picks the intent as StartGame always. What is the best way to invoke "GetRules" intent. I want the user to just say Yes/No and not say "Get the rules".
Please let me know if this has been already answered/more information is needed.
You need to use AMAZON.YesIntent and AMAZON.NoIntent.
You can read about them here:.
Standard Built-in Intents.
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/built-in-intent-ref/standard-intents
Please add below code in interaction model.
{
"name": "AMAZON.NoIntent",
"samples": []
},
{
"name": "AMAZON.YesIntent",
"samples": []
}
And provide your business logic for yes/no in your lambda.
'AMAZON.YesIntent': function () {
//business code
},
'AMAZON.NoIntent': function () {
//business code
}

Resources