Alexa, get skill from LaunchRequest Intent - alexa

I got 3 skills in my account, eg SkillA, SkillB and SkillC.
I am using an endpoint url to listen to these skills, and my server is common for all the 3 skills. So if I try to invoke a skill by saying open SkillA it invokes LaunchRequest. Same is the case with other 2 skills.
So how would I be able to know which Skill's LaunchRequest was invoked.
My server is ruby with Ralyxa Gem.

For every skill there is a unique Skill ID known as applicationId. Making use of this applicationId from the request JSON you can easily determine from which skill the request came in.
You can find this applicationId under application object in every request from Alexa to your backend.
{
"version": "1.0",
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.xxxx-xxxx-xxxx-xxxx-xxxxxxx",
"application": {
"applicationId": "amzn1.ask.skill.xxxx-xxxx-xxxx-xxxx-xxxx"
},
"user": {
"userId": "amzn1.ask.account.xxxxxxxxxxxxxx"
}
},
...
You can also view the Skill ID from Alexa developers console where your Alexa Skills are listed.

Related

How to query for the list of members and their basic profiles, including Teams user IDs?

Is there an end-to-end sample provided to query for the list of members and their basic profiles, including Teams user IDs and Azure Active Directory (Azure AD)?
I am following https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/get-teams-context?tabs=json and microsoft graph Postman collection, however it seems too complex for me to understand.
I need to fetch all the userId under for my MS Team
The document you are following is indeed used to get the information you need, including Teams user IDs and Azure Active Directory (Azure AD).
I'm not sure where you don't quite understand. But it's strongly suggested to firstly learn about Bot Framework Rest API reference.
You should pay attention to how to get the Base URI (serviceUrl). After that, you could issue a GET request on /conversations/{teamId}/members/, using the value of as the endpoint: serviceUrl.
Like this:
GET https://{serviceUrl}/v3/conversations/{teamId}/members/
Authorization: Bearer {access token}
Content-Type: application/json
For details about how to obtain an access token for your bot, see Authenticate requests from your bot to the Bot Connector service.
Now you have the request endpoint and headers. You could test the Rest API in Postman.
Below are the commands I used to fetch Team user IDs
Step 1: Request an access token from the Azure AD v2 account login
service
Step 2: Obtain TenantID
Step 3: Get User Access Token
https://login.microsoftonline.com/{{TenantID}}/oauth2/v2.0/token
Step 4: Call My Joined Team, get ID
https://graph.microsoft.com/v1.0/me/joinedTeams
Step 5: Findchannels of a team
https://graph.microsoft.com/v1.0/teams/{{TeamId}}/channels
Step 6:
Find all the user profile using following
https://{{serviceUrl}}/v3/conversations/{{channelid}}/members/
The best way to get teams user details is by fetching roster details.
You can also use Graph API for getting members of a team/group. But this API provides basic details of user. like
[
{
"#odata.type": "#microsoft.graph.user",
"id": "xxxxxxx-95ea-xxxxxxxxx",
"businessPhones": [
"xxxxxxxxxxxxx"
],
"displayName": "Vivek",
"givenName": "Vivek",
"jobTitle": "xxxxxxxx",
"mail": "xxxxxxxx#microsoft.com",
"mobilePhone": "xxxxxxxxxxx",
"officeLocation": "LINCOLN xxxxxxxxx",
"preferredLanguage": null,
"surname": "Shah",
"userPrincipalName": "xxxxxxxx#microsoft.com"
},
]

How to use ARM templates to deploy a roleAssignment for an App Registration Service Principal?

In my current project I'm working with pre-created App Registration Service Principals in Azure AD. I'm using an ARM template to create a StorageV2 account plus some blob containers, then create a roleAssignment giving Storage Blob Contributor rights to one of the Service Principals. The relevant section of the ARM template is at the end of this post.
What I've found is that if I take the ObjectId of a regular AD user, such as myself or my colleague, and set that as PrincipalId, the script runs correctly. However, I can't get this to work with a Service Principal.
If I use the Service Principal's ObjectId, then I get the following error:
Deployment failed. Correlation ID: 40e0c146-165a-47c0-b022-ac04781d8194. {
"error": {
"code": "PrincipalTypeNotSupported",
"message": "Principals of type Application cannot validly be used in role assignments."
}
}
Having spotted some suggestions for Azure Powershell users that I should use Application (Client) Id instead, I tried that, but get the following error (Guids redacted):
Deployment failed. Correlation ID: 5c725a51-230a-4d85-bb61-b2f4cdf849ff. {
"error": {
"code": "PrincipalNotFound",
"message": "Principal 9f****30 does not exist in the directory db****75."
}
}
So the ObjectId it can find but not use, and the ClientId it can't find.
I have found that if I use Azure Powershell and use the New-AzureRmRoleAssignment command, I can reproduce the PrincipalTypeNotSupported error by providing the Service Principal's ObjectId to the -ObjectId switch. However, that command also has a -ServicePrincipalName switch as an alternative, and if I give that the Service Principal's ClientId, it works!
Is there any equivalent of -ServicePrincipalName for the ARM templates, and if not, is there any other way to achieve this? I can use Azure Powershell as a workaround, but it's messier than I'd like.
If this is a feature gap, where's the best place to report it?
Relevant section of ARM template follows:
"resources": [
{
"name": "[variables('storageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"location": "[resourceGroup().location]",
"apiVersion": "2018-07-01",
"sku": {
"name": "[parameters('storageAccountSku')]"
},
"dependsOn": [],
"tags": {
"displayName": "Storage Account"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot",
"supportsHttpsTrafficOnly": true,
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Deny"
}
},
"resources": [
{
"type": "blobServices/containers",
"name": "[concat('default/', variables('myBlobContainerName'))]",
"apiVersion": "2018-07-01",
"dependsOn": [
"[variables('storageAccountName')]"
],
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"name": "[variables('myRoleAssignmentGuid')]",
"apiVersion": "2018-07-01",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
"principalId": "[variables('myPrincipalId')]"
},
"dependsOn": [
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), '/blobServices/default/containers/', variables('myBlobContainerName'))]"
]
}
]
}
]
}
]
Finally solved this one thanks in part to the pointers from #4c74356b41.
When an Application Registration object is created, an identically named object is also created under Enterprise Applications. This has the same ApplicationId, but a different ObjectId, and it's the ObjectId of this Enterprise Application object that our ARM script needs.
You can find this object in the portal by going to the Application Registration entry, then clicking on the link after Managed application in...
Screenshot of App Registration with Link
Once you're on the corresponding Enterprise Application object, you can get the ObjectId from Properties, and use this the value for principalId in the ARM template.
At the time of writing, the Microsoft Documentation is a bit vague on this, with the terms Application and Service Principal seemingly overloaded. This article says that when you register an application you get an Application object and a Service Principal object, but doesn't use the phrase Enterprise Application once, or refer to App Registration objects per se, so it's unclear which is which.
I'm assuming Application == Application Registration and Service Principal == Enterprise Application. This SO post would seem to suggest this is the case, as would the solution above.

Can Alexa Smart Home Discovery be triggered programmatically?

Is it possible to programmatically trigger an Alexa smart home “discovery”?
I’m working on a custom skill that can be used to add and configure devices in an associated smart home skill. Using the custom skill, the user can add and edit device names recognized by the smart home skill.
This works fine, but as expected requires the user to perform "discover new devices" before the smart home skill will pick up the changes.
Is there a way that the custom skill could trigger a new discovery on the smart home skill to pick up the new device info?
I'd rather not have the custom skill tell the user “Ok, now go open the Alexa app, go to smart home, and select discovery".
There is a workaround for your problem. If you see how Alexa.Discovery works you have to make a request to the endpoint. If you have the access to the endpoint you can send the request and get the new devices int the response from the endpoint.
Discovery Request :
{
"directive": {
"header": {
"namespace": "Alexa.Discovery",
"name": "Discover",
"payloadVersion": "3",
"messageId": "1bd5d003-31b9-476f-ad03-71d471922820"
},
"payload": {
"scope": {
"type": "BearerToken",
"token": "access-token-from-skill"
}
}
}
}

Role/Group based Authorization using ADAL.js and ASP.NET Web API

What we are planning to achieve is a role-based security for a Front end Angular-2 and back-end ASP.NET Web API application. We are doing the authentication process with the help of ADAL.js and storing the token in the local storage. We have also implemented the approach shown here i.e. to call the Graphi API and get the user groups to stuff them into Claims.
My question is : Is there anyway, we can add role claims from server to the bearerToken which is residing in the local storage. Or is there any better way to approach this issue.
The code sample mentioned assign the role based on the group. If you have the Azure AD basic version, it support to assign the role to the users/groups directly.
My question is : Is there anyway, we can add role claims from server to the bearerToken which is residing in the local storage. Or is there any better way to approach this issue.
Yes, it is possible. To issue the role claims we need to assign the users to assign the roles to users or group first. Then when the user acquire the token, the Azure AD would issue the relative role claims in the token.
You can refer the code sample for using the role claim from here.
And you may also be interest in groups claim developing.
ok i was struggling with this for a while and i have figured it out i believe.
First,
In Azure AD, set up your WebApi app as application type to be Web App / API.
go to Manifest file and add your roles like
[
{
"allowedMemberTypes": [
"User"
],
"displayName": "Reviewer",
"id": "0238c2bb-9857-4d07-b760-a47ec621d57a",
"isEnabled": true,
"description": "Reviewer only have the ability to view tasks and their statuses.",
"value": "reviewer"
},
{
"allowedMemberTypes": [
"User"
],
"displayName": "Approver",
"id": "000018cb-19e3-4f89-bf99-5d7acf30773b",
"isEnabled": true,
"description": "Approvers have the ability to change the status of tasks.",
"value": "approver"
}
]
Then create the the Client app as Application type to be Native app and add required permissions to the service you added above.
In the SPA Angular app add something like this
var endPoints = {
// "https://localhost:44386/" is the API URL
// "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is the Service Application ID
"https://localhost:44386/": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
};
adalAuthenticationServiceProvider.init({
instance: "https://login.microsoftonline.com/",
// tenant is your tenant name (something like below)
tenant: "{NAME}.onmicrosoft.com",
// this is the Native app application ID (ClientID) you registered
clientId: "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
extraQueryParameter: "nux=1",
endpoints: endPoints
}, $httpProvider);
}
]);
Then, in your startup.cs you need to set up the Service App like the following:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
/* "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is the Service Application ID. (Same as you registered in the client app above)*/
ValidAudience = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
RoleClaimType = "roles"
},
/*enant is your tenant name (same as you registered in client app above)*/
Tenant = "{NAME}.onmicrosoft.com"
});
Finally you need to go to Azure active directory => Enterprise application => all applications => select your webAPI service => Users and groups => then assign users to the roles.
When this is all done when you log through your client app to authenticate and call the webapi, adal.js and ada-angular.js will put the proper bearer token that contains roles
Good to learn this approach.
Ted, thanks for sharing your solution !
For those who are not familiar with operating Azure AD manifest file. The following is a good resource.
https://thinkthencode.wordpress.com/2016/04/24/azure-ad-using-app-roles-for-authorization/
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"displayName": "Reviewer",
"id": "0238c2bb-9857-4d07-b760-a47ec621d57a",
"isEnabled": true,
"description": "Reviewer only have the ability to view tasks and their statuses.",
"value": "reviewer"
},
{
"allowedMemberTypes": [
"User"
],
"displayName": "Approver",
"id": "000018cb-19e3-4f89-bf99-5d7acf30773b",
"isEnabled": true,
"description": "Approvers have the ability to change the status of tasks.",
"value": "approver"
}
]

Retrieving Send-as settings from Gmail Account

I've been working on an application that uses the Gmail API, but I've kind of hit a roadblock.
I need user Send-As information, but it doesn't appear to be available in the Gmail API. In Google Apps Accounts, the EmailSettings API provides this functionality, but it is unavailable for free gmail accounts.
I suppose my question is: Is there any way to pull a list of Send-As or POP-configured accounts from a regular Gmail account?
Sadly, you can not retrieve them from the Gmail API or any other API I know of. Other 3rd party applications that use the feature of "aliasing" their mail advise their users to first create the alias in the regular Gmail application first, and then input it manually.
You could do that, and in the background send a mail to the user's own inbox with the given alias. If the alias exists, it will be the sender of the mail. If it was incorrect, it will fall back to the regular email address.
Edit
You can now get the sendAs settings from the Gmail API:
Request
GET https://www.googleapis.com/gmail/v1/users/me/settings/sendAs?access_token={access_token}
Response
{
"sendAs": [
{
"sendAsEmail": "primary#gmail.com",
"displayName": "",
"replyToAddress": "",
"signature": "",
"isPrimary": true,
"isDefault": true
},
{
"sendAsEmail": "secondary#gmail.com",
"displayName": "",
"replyToAddress": "",
"signature": "",
"isDefault": false,
"treatAsAlias": true,
"smtpMsa": {
"host": "host.com",
"port": 465,
"securityMode": "ssl"
},
"verificationStatus": "accepted"
}
]
}

Resources