No se han encontrado resultados
This second installment in our Login with Amazon (LWA) integration series is about integrating LWA with Amazon Web Services (AWS) using Amazon Cognito.
Amazon Cognito is AWS's solution to managing user identities in the apps you build with AWS underpinnings. To quote their FAQ: "Developers can use Cognito Identity to add sign-up and sign-in to their apps and to enable their users to securely access their app’s resources. Cognito also enables developers to sync data across devices, platforms, and applications."
One of the great parts of Cognito is that instead of requiring your users to create a new ID/Password combination for your app, they can use their login credentials from popular sites and apps… like Amazon.com.
Some of you may be asking "but aren't Amazon.com and AWS the same thing?" They actually have separate user account databases because they focus on different market segments. This may be an oversimplification, but you could say your Amazon.com account is for buying a smart toaster while your AWS account is for setting up the infrastructure to administer a network of smart toasters.
If you haven't watched the video of my talk "Can you roll your own virtual assistant," check it out. It's got knock-knock jokes and a puppet show.
This will be a written guide to the process I used to integrate LWA with Cognito, minus the audio stuff so we can keep it from being an hour-long read.
It uses the AWS SDK for JavaScript, but AWS has SDKs for a number of languages that can help in a similar way. Even if you're not a JavaScript developer, you may get some value out of walking through the process here.
Go to the Amazon developer site and log in, then click "Apps & Services" and select "Login with Amazon" from the menu below that.
If you don't already have a security profile you want to use, click the "Create a New Security Profile" button and complete the form resulting from that.
After you save it and you're back at the list of security profiles, click the gear symbol on the right-side of the table and select "Security Profile" to manage your profile.
Copy your Security Profile ID and Client ID from the next screen. You'll need them later.
Go to the web settings tab and set your origin, which is the domain and subdomain the user will be coming from when they're sent to Amazon to login and authorize your app to access their profile. Since I was running from within a JavaScript-based mobile app, to get a free and simple HTTPS origin, I created a Github Pages page that I could open in Cordova's InAppBrowser.
The origin only needs an authorized domain (with the appropriate subdomain if necessary), so YiddishNinja.github.io was good enough, even though the page you would open was in a subdirectory.
The code you would add in there is pretty simple:
window.location.href =
https://www.amazon.com/ap/oa?client_id=[YourLwAClientID]&scope=profile&response_type=token&state=[optionalUniqueID]&redirect_uri=[YourRedirectURL]
Login with Amazon is a REST API, so while using our JavaScript SDK for placing the button and making it functional, you can rig up the redirect yourself.
Quick bit of vocabulary for the uninitiated: the single-step Implicit grant we use here will only work for certain scopes and only gives you an access token that's good for an hour (as of this writing). The two-step Authorization grant is more secure, but would require a server-side component to complete the login. To keep this short and easy, I'm using an Implicit grant.
While later sections of this piece will not dive into using Lex, we'll go through the process of setting up Cognito based on the Lex functionality I used.
First, go to Cognito from your AWS console.
Then choose to "Manage Federated Identities."
This will launch a wizard to set up a new identity pool. Name it, don't approve unauthorized access, and enable Login with Amazon by selecting the Amazon tab in the "Authentication providers" section and pasting the Security Profile ID you copied a few steps ago into the Amazon App ID box.
Create the pool.
In the next step, you'll create a new IAM (Identity and Access Management) role that will help you assign the correct and necessary permissions to the customers who use your app with their Amazon.com logins.
You may need to click the down-arrow next to "View Details" to show the details and make your page look like the one above. Then you can allow the creation.
The next screen will offer you some sample code and SDK downloads. Ignore those for now. Instead click "Dashboard" in the navigation links in the upper left.
Click the "Edit identity pool" link in the upper right. Copy your Identity Pool ID. You'll need it later.
Now click the "Services" dropdown at the top of your screen and select "IAM," which may be in your History section, but also under the "Security, Identity, and Compliance" section.
Click "Roles" in the Sidebar, then click on the auth role for your pool on the next screen.
On the following screen, you'll click the "Attach Policy" button to attach some policies to the role.
On the policy attaching screen, you can search for different policy elements. Since we were using Lex in the original demo app, I chose "AmazonLexRunBotsOnly" since we were using a pre-built bot and not building it programmatically at runtime.
Attach the policy. Obviously, if you were doing more with the bot, you'd attach more policies than just " AmazonLexRunBotsOnly," but we're keeping this simple. I don't know if 15 screen-caps to demonstrate the steps so far still qualifies as "simple," but let's just go with it.
We're also not going to go into the creation of a Lex Bot because the Lex team has done that extensively and we're already closing in on 1,000 words.
Next let's go to the AWS SDK Builder for JavaScript. This is a wonderful tool because it lets you build a much smaller JavaScript file, building in components for just the AWS services you need, keeping memory overhead low and diminishing load times.
You'll need the CognitoIdentity and LexRuntime components. The image shows Polly as well, but that's optional. Polly handles all the responses to the utterances you pass to Lex without needing to invoke it directly. The primary use for adding Polly would be to say things on demand. For example, if Lex asks "Is that correct" and sends back a "ConfirmIntent" dialogState to your app, that might trigger a timeout that says "Please answer the question: Is that correct?" if a response isn't received by the app within 60 seconds. The first "Is that correct" would come from the LexRuntime response, but the second one would go through Polly since your app is initiating that speect, not Lex.
We're going to assume you've got some familiarity with building both websites and Cordova apps. First you'll need to install the InAppBrowser plugin and the Whitelist plugin for Cordova. You'll also need to whitelist Cognito's remote URL by adding a line to your app manifest.
<access origin="https://cognito-identity.us-east-1.amazonaws.com/"
/>
First, we'll set up an object with some constants.
1. var diyvaENV = {};
2. diyvaENV.LWA_CLIENT = "[your security profile's client id]";
3. diyvaENV.LWA_PROXY = "https://yiddishninja.github.io/LWA-proxy/index.html";
4. diyvaENV.LWA_PROXY_RETURN = "https://yiddishninja.github.io/LWA-proxy/signin.html";
Second, we need to handle the login to get our Login with Amazon credentials. The following code is tied to our Login with Amazon button, which shows if the customer is not logged into the app.
It pops open an inAppBrowser and directs it to your HTTPS page (like I created on Github) with the JavaScript to redirect the user to a Login with Amazon login. Each time the inAppBrowser stops loading a page, we check if the browser has been redirected to the completion URL. If so, we close the inAppBrowser and process the data Login with Amazon appended to the redirect URL as a URI fragment.
1. //set up handling of the LWA login button
2. var lwaButton = document.getElementById("lwa_button");
3. lwaButton.addEventListener('click', function () {
4. //open InAppBrowser to handle LWA web login
5. var ref = cordova.InAppBrowser.open(diyvaENV.LWA_PROXY + "?state=" +
device.platform, '_blank');
//add handling of return from LWA
7. ref.addEventListener('loadstop', function (e) {
8. //check loaded URL for completion, process login
and pass hash
9. if (e.url.includes(diyvaENV.LWA_PROXY_RETURN)) {
10. logincomplete = true;
11. ref.close();
12. if
(e.url.includes(diyvaENV.LWA_PROXY_RETURN)) {
13. handleReturnedHash(e.url);
14. }
15. }
16. });
The "handleReturnedHash()" function breaks up the information in the URI fragment returned after the customer logs in, stores the important data in local storage, and returns false if there were any errors in the processing.
1. function handleReturnedHash(hashVal) {
2. document.getElementById("welcome").style.display =
"none";
3. var fragment = hashVal.split("#");
4. if (fragment.length < 2) {
5. return false;
6. }
7. var valarray = fragment[1].split('&');
8. var vals = [];
9. valarray.forEach(function (valpair, index, array) {
10. var subvals = valpair.split('=');
11. vals[subvals[0]] = subvals[1];
12. });
13. if (!("access_token" in vals)) {
14. return false;
15. }
16. window.localStorage.setItem("loggedIn", "true");
17. window.localStorage.setItem("LWALoginTime",
Math.floor(Date.now() / 1000).toString());
18. window.localStorage.setItem("LWAToken",
vals["access_token"]);
19. window.localStorage.setItem("LWATTL",
vals["expires_in"]);
20. window.location.href = "index.html";
21. }
As you would with any website, you'll have loaded the AWS JavaScript SDK files when the main page of your Cordova app loaded. Now you can get your Lex API credentials via Cognito and return them.
1. // Set up identity pool
2. creds = new AWS.CognitoIdentityCredentials({
3. IdentityPoolId: [your pool ID]'
4. });
5.
6. creds.params.Logins = {};
7. creds.params.Logins['www.amazon.com'] =
decodeURI(window.localStorage.getItem("LWAToken"));
8.
9. // Explicity expire credentials so they are refreshed
10. // on the next request.
11. creds.expired = true;
12.
13. AWS.config.update({
14. region: 'us-east-1',
15. credentials: creds
16. });
17.
18. // trade the token
19. creds.get(function (err,data) {
20. lex = new AWS.LexRuntime({ apiVersion: '2016-11-28'
});
21. if (err) {
22. console.log("we have an error");
23. console.dir(err);
24. }
25. });
Now, with a parameters object that specifies the necessary data (bot, content, etc.) you can post audio from your app to Lex very simply.
1. lex.postContent(params, function (err, data) {…});
So, there you have it. In 47 lines of code (less if you use less whitespace and commenting than I do), you can process a customer's login with Login with Amazon, get an access token, and trade it to Cognito to get an access token for Lex, creating the back-end underpinnings to add voice recognition and response to your Apache Cordova app.
Hope you found this useful. If you have questions, comments, or corrections, please tweet at me via @YiddishNinja or at our team via @LoginWithAmazon. You can also post in the Amazon developer forums or tag something LoginWithAmazon on Stack Overflow and we'll take a look.