Amazon Alexa Skills authenticated by Azure Active Directory and backed by an Azure Function


This post is provided by Premier Field Engineer, Nathan Vanderby, who walks us through how to write an Alexa skill using Azure Functions.


Most people have heard of the Amazon Echo and the skills that provide it functions. Amazon makes it really easy to create these skills using an AWS Lambda function. These can also be backed using a REST API app or even an Azure Function. Below we will give some instructions for how to leverage Azure Functions with Azure AD for authentication. The steps below are almost identical to how you would configure a generic backend API with authentication except that the Azure Function needs to manually verify the JWT token instead of leveraging the [Authorize] attribute.

Step-by-step tutorial

Step 1: Create an Azure Subscription

If you haven't already signed up for Azure you can do so here. We will use Azure AD for app registration and Azure Functions for the backend. Azure Functions creates a storage account and App. Service resources with it. The cost of doing a proof of concept should be minimal given the app registrations are free, we won't be using the storage account and Azure Functions give 400,000 GB-s free each month.

Step 2: Create your Azure Function

We will start off by using the Azure Functions new project template in Visual Studio. This tutorial focuses on C#, but it is also possible to develop Azure Functions on any platform.

Make sure your project is at least on .NET Framework 4.6.1. This is due to the Alexa.Net NuGet package we will use to deserialize the Alexa JSON to classes. This will require us to use the Azure Function 2.x runtime version.

Once your project is created add a new Azure Function item to it.

Set the trigger type to Http trigger and the access rights to Anonymous.

This will give us a default Run method that is attributed such that the Azure function name is what you specified in the wizard (Alexa in this case). It also sets up anonymous authorization with get and post REST methods. The inputs to the method is an HttpRequestMessage and a TraceWriter.

Add the Alexa.NET NuGet Package (https://github.com/timheuer/alexa-skills-dotnet) to the project so we can easily deserialize the JSON into classes.

Now we can add some code. First modify the method signature. We can remove the get REST API and we can leverage the [FromBody] attribute to easily deserialize the JSON into a SkillRequest. Then add some code to respond to a skill request. The code below simply looks for a first name and responds with "Hello [FirstName]".

[FunctionName("Alexa")]
public static async Task<SkillResponse> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]
    [FromBody]SkillRequest request, TraceWriter log)
{
    SkillResponse response = null;
    PlainTextOutputSpeech outputSpeech = new PlainTextOutputSpeech();
    string firstName = (request.Request as IntentRequest)?.Intent.Slots.FirstOrDefault(s => s.Key == "FirstName").Value?.Value;
    outputSpeech.Text = "Hello " + firstName;
    response = ResponseBuilder.Tell(outputSpeech);
    return response;
} 

This code will work as an unauthenticated backend for an Alexa skill. Lets publish it and test it, then circle back to add authentication.

Step 3: Publish to Azure

To push the code to Azure simply right click on the project and select Publish. Walk through the wizard to create a new Azure Function or select from one that has been already created.

Once the Azure function is created we need to change the runtime version to V2. Go to portal.azure.com and navigate to the function you are using. From the Overview pane select Function app settings.

Inside the app settings change the Runtime version to be at least 2.0, currently this is the beta. This is only required since we are leveraging a NuGet that is build for .NET Standard 1.6. If you write your own library or use a different one that is compatible with .NET Framework 4.5 this is not necessary.

Now you should be able to return to Visual Studio and publish your function to Azure. Once your publish is successful you will want to go back to Azure, select that function and copy its URL for use in configuring the Alexa skill.

Step 4: Configure the Alexa Skill

Now that we have our code in Azure we need to configure the Alexa skill. Navigate to Amazon's developer page for Alexa, you will have to create an account. Under Alexa Skills Kit click Get Started.

Then select Add a New Skill from the upper right corner.

Skill Information

In the Skill Information screen select Custom Interaction Model, give the skill a name and an invocation name that people will use when talking to an Echo. Click Save then Next to move onto the Interaction Model.

Interaction Model

Under Intent Schema fill in this JSON:

{
"intents" :
[
	{
		"intent" : "Tutorial",
		"slots" :
		[
			{
				"name" : "FirstName",
				"type" : "AMAZON.DE_FIRST_NAME"
			}
		]
	},
	{
		"intent" : "AMAZON.HelpIntent"
	},
	{
		"intent" : "AMAZON.StopIntent"
	}
]
}

The intent here is so Alexa knows that when we talk to "Tutorial" it should also expect a parameter called FirstName. If you look back at the code in the API Post method you will see how we can read the FirstName slot from the Tutorial intent on the request.

Leave Custom Slot Types blank.

Under Sample Utterances add Tutorial Can you greet {FirstName}
Notice how this sample utterance uses both the intent and the FirstName slot.

Click Save then Next to move onto Configuration.

Configuration

Select HTTPS for the endpoint. Under the Default text box enter the URL you copied earlier for your function.

In the Account Linking section select No. We will come back to this later.

SSL Certificate

In this section select My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority and click next.

Test

In this page take note of the URL you are sending an Alexa request to and simply type in an utterance such as Tutorial can you greet Nate. You should get a service response.

Now that our skill is working we need to add authentication to it.

Step 5: Configure Azure Active Directory

There will be two different application registrations we need to create. The first one is for the backend Azure function and the second one is for the Alexa service to acquire an authentication token that has delegated permissions to the backend app registration.

Backend App Registration

Go to the Azure portal and find the Azure Active Directory service. Then click on App registrations and New application registration

 

Give your registration and name, select Web app/API as its type and give it a sign-on URL. This URL doesn't matter for this tutorial.

Now that the app registration is created select All settings then Properties. Note the App ID URI value. We will need this value later on in the C# code and the Alexa account linking configuration.

Lastly, make note of the Keys property. We will have to come back here later to generate a key as a part of the Alexa account linking configuration.

Frontend App Registration

Create another app registration in AAD and call it AlexaFrontEnd. It's type will be Native and the RedirectURI will be https://pitangui.amazon.com/api/skill/link/{lookuplater}. We will find out the last part of the RedirectURI after we create an Alexa skill in a later step.

After the app registration is complete we need to give it delegate permissions into our API. This allows user access to our backend API if they get their token from the front end (Alexa service) app. This is required since the users are not directly calling our API from a web browser.

Inside the newly created FrontEnd registration navigate to the app registration settings and select Required permissions.

Select Add and start typing in AlexaBackendAPI. Select the app registration we created earlier.

That’s it for now. We’ll come back to both app registrations later to update the Redirect URI (front end) and get a Client Secret (AKA Key) from the backend API as a part of configuring the account linking in the Alexa skill configuration.

Step 6: Adding Authentication in the Code

There are a few posts out there for performing token authentication without leveraging ASP.NET middleware. One of the most helpful and relavant to Azure Functions comes from Boris Wilhelms. I have leveraged his code sample below.

Create a class called Security and copy from the code below. This code is definitely sample code and not production ready. The two main variables to set are the ISSUER and AUDIENCE. The GUID for the issuer is your AAD directory ID that you can get from the properties section of the Azure AD resource. The audience value comes from the App ID URI. The code below also requires 2 additional NuGet packages. The first is System.IdentityModel.Tokens.Jwt v5.1.4 or lower. The second is Microsoft.IdentityModel.Protocols.OpenIdConnect v2.1.4 or lower. At the time of writing this if you use versions 5.1.5 or 2.1.5 respectively a runtime error occurs when Azure tries to load the function.

public static class Security
{
	private static readonly string ISSUER = "https://sts.windows.net/XXXXXXXX-XXXX-XXXX-aec1-f1f2a290f738/";
	private static readonly string AUDIENCE = "https://AlexaToAzure.onmicrosoft.com/AlexaBackendAPI";
	private static readonly IConfigurationManager<OpenIdConnectConfiguration> _configurationManager;

	static Security()
	{
		HttpDocumentRetriever documentRetriever = new HttpDocumentRetriever();
		documentRetriever.RequireHttps = ISSUER.StartsWith("https://");

		_configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
			$"{ISSUER}/.well-known/openid-configuration",
			new OpenIdConnectConfigurationRetriever(),
			documentRetriever);
	}

	public static async Task<ClaimsPrincipal> ValidateTokenAsync(string value)
	{
		var config = await _configurationManager.GetConfigurationAsync(CancellationToken.None);
		var issuer = ISSUER;
		var audience = AUDIENCE;

		var validationParameter = new TokenValidationParameters()
		{
			RequireSignedTokens = true,
			ValidAudience = audience,
			ValidateAudience = true,
			ValidIssuer = issuer,
			ValidateIssuer = true,
			ValidateIssuerSigningKey = true,
			ValidateLifetime = true,
			IssuerSigningKeys = config.SigningKeys
		};

		ClaimsPrincipal result = null;
		var tries = 0;

		while (result == null && tries <= 1)
		{
			try
			{
				var handler = new JwtSecurityTokenHandler();
				result = handler.ValidateToken(value, validationParameter, out var token);
			}
			catch (SecurityTokenSignatureKeyNotFoundException)
			{
				// This exception is thrown if the signature key of the JWT could not be found.
				// This could be the case when the issuer changed its signing keys, so we trigger a 
				// refresh and retry validation.
				_configurationManager.RequestRefresh();
				tries++;
			}
			catch (SecurityTokenException)
			{
				return null;
			}
		}

		return result;
	}
}

Next we have to modify the Run method to call into this `ValidateTokenAsyn()`` with the Alexa requests access token.

SkillResponse response = null;
if (request?.Session?.User?.AccessToken != null)
{
	ClaimsPrincipal principal = await Security.ValidateTokenAsync(request.Session.User.AccessToken);
	if (principal != null)
	{
		PlainTextOutputSpeech outputSpeech = new PlainTextOutputSpeech();
		string firstName = (request.Request as IntentRequest)?.Intent.Slots.FirstOrDefault(s => s.Key == "FirstName").Value?.Value;
		outputSpeech.Text = "Hello " + firstName;
		response = ResponseBuilder.Tell(outputSpeech);
	}
}

return response;

Publish this new code to your Azure Function and navigate to the Amazon developer portal to configure the Alexa skill for account linking.

Step 7: Alexa Account Linking Configuration

Head back to your Alexa skill in the Amazon develop portal. Navigate to the Configuration section.

In the Account Linking box section select Yes. Enter the following information into the fields:

  • Authorization URL: https://login.windows.net/{TenantId (DirectoryId)}/oauth2/authorize?resource={App ID URI}
    The TenandId/DirectoryId is the GUID for your Azure AD. This can be found in the Properties section of the Azure AD resource.
     
    The App ID URI can be found in the Properties settings of the app registration for your backend. In this tutorial it is https://AlexaToAzure.onmicrosoft.com/AlexaBackendAPI This parameter is needed as it tells AAD which resource Alexa is requesting access to. This parameter also defines the audience property in the JWT token returned from AAD.

  • Client Id: This is the Application Id from the native (FrontEnd) app registration
     

  • Authorization Grant Type: Auth Code Grant

  • Access Token URI: https://login.windows.net/{TenantId (DirectoryId)}/oauth2/token This URI can be found in the Endpoints settings of the app registration blade. Copy the OAUTH 2.0 TOKEN ENDPOINT

  • Client Secret: This is effectively the password the Alexa service will use to allow account linking to your API backend. We will generate one now. Navigate to the Keys setting in the backend app registration.
    Give a key a description and a duration then click Save. The key will be generated on the save. This will be the one time this key is displayed, so copy it.

  • Client Authentication Scheme: HTTP Basic (Recommended)

In the end your Account Linking settings should look similar to this:

Before we move onto the next screen, notice the Redirect URIs in the account linking settings. Copy these URLs into the Redirect URLs setting for the native app (FrontEnd). This replaces the one we used earlier that had {lookuplater} in it.

Click Save then Next

Step 8: Link Accounts and Test

  1. Login to https://alexa.amazon.com

  2. Navigate to Skills -> Your Skills
  3. You should see our newly created skill. Click on it.
  4. Select SETTINGS
  5. Click on the Link Account button in the upper right corner
  6. You will be redirected to login to Azure Active Directory and then asked to accept the access being requested. Once you get through that result and if all goes well you should see:

Step 9: Testing

We have multiple options by which to test the Alexa Integration. We can use an actual device, the Amazon Developers Portal Test client or there is an Alexa Skill Testing Emulator. I'll go over the last two since they don’t require you to purchase anything.

Amazon Developer Portal

  1. In the Amazon Developer portal where we configured the Alexa skill Note: If you left this tab open from the prior instructions, you will have to refresh the page after perofrming the account linking
  2. Make sure you are under the Skill you are wanting to test

  3. Click on the test section
  4. In the Enter Utterance Section enter the following: Tutorial Can you greet {your name}
    • {your name} = your name or any name
    • This is derived in the Interaction Model section for the skill.
  5. Click the Ask AlexaToAzure button.
    • If all goes well you should see something that looks like:
    • If you get a 401: Unauthorized result, see some debugging tips below.

Alexa Skill Testing Tool (Emulator)

The Alexa emulator is a simulated version of using an Alexa device that is surfaced in a web page. You need to have a microphone and speaker to use this tool.

  1. Open browser and go to following URL: https://echosim.io/welcome?next=%2F

  2. Click on the Login with Amazon button.
    • Use your Amazon Developer account
  3. Once logged in your ready to test

Troubleshooting

  • F12 browser tool

    • If you need to look at the HTTP Request Response stream pressing F12 from Explorer, Edge, Chrome will open integrated developer tools.
  • JWT.IO - https://jwt.io/
    • This is a browser based tool where you can take your JWT token from the request and decode it and verify the signature
  • If account linking works and your still getting a 401 unauthorized response try the following:
    • Refresh the Amazon develop page and try again (this makes Amazon request a new token)
  • Enabling diagnostic logs, detailed error messages and leveraging live streaming of logs in the Azure portal for the web app is very useful for debugging

Sample Code

The companion source code for the Azure Function portion of this tutorial can be located on GitHub at https://github.com/vanderby/AlexaToAzureFunction


Premier Support for Developers provides strategic technology guidance, critical support coverage, and a range of essential services to help teams optimize development lifecycles and improve software quality.  Contact your Application Development Manager (ADM) or email us to learn more about what we can do for you.

Comments (0)

Skip to main content