meetpatelvgec
meetpatelvgec

Reputation: 69

How to use BearerToken received from Alexa Smart Home Skill Directive to identify the user email and profile using AWS Lambda with NodeJS?

Some Background: I am using Amazon Alexa smart home skill for controlling some IoT devices with AWS Lambda function written in NodeJS as the default endpoint. I have already linked the Alexa Skill with lambda function, created a Login With Amazon security profile, and enabled account linking for the alexa skill. For now, I have turned off the "Send Alexa Events" permission because that adds its own complexity in terms of responding the events. Currently I am in Beta Testing stage of my skill.

My use case: I have 3 different customers who have different name, different email IDs and different amazon accounts. All 3 customers have downloaded my Alexa skill in their alexa app and linked it to their amazon account. All those customers have 2 devices (light and fan) at their home, which are connected to my cloud. I have stored their device information against their email IDs on my cloud in a database as shown below:

  1. [email protected], Light -> ON, Fan -> OFF
  2. [email protected], Light -> OFF, Fan-> OFF
  3. [email protected], Light -> OFF, Fan -> OFF

Now let's say one of those customer, Jhonny, wants to turn on the light. So when Jhonny asks Alexa for turning on the light, my lambda function will receive below directive:

{
    "directive": {
        "header": {
            "namespace": "Alexa.PowerController",
            "name": "TurnOn",
            "payloadVersion": "3",
            "messageId": "003edc9f-68ad-4618-a982-f73fc37d25be",
            "correlationToken": "AAAAAAAAAQDaOl/vVaX+GlN2m9SvqFri/AEAAAAAAACdKWHpFqLjNmk4Y6DeNDRoGjdMODTZW6kkXKZoe3Ya289F45koL55JJmcv05BVBFceJH9FXOb/YJcwQH+xk4yx1KMa92zoBTl7jNayw8r4Pzfvd8oO486Fx3q3g35xAeNfNPbHalpV7ftYw86qXsurSfRkk2vgqWQu9CsYH013/fqY3ojnQySOIu31BAaiGWI4Pur4x/2zg3HOBKQkzguIMVmWxZP7de+VCoD5cqEQYOoE7ACQi6NAGPJHbS5cLY/2FBO163wLeDGoJZ8sfEcroQYpqGCkQ+KTLolZ2SDle2VvubB7Ntc0Rzpfg45dGFj6T2Mb8mP/PgxH+mfgTzjTUgTq9N6wfA/zAvXWnpCkC6/3nFUS3NzsYqaa+ff/Zm7smI645BJU6BJu19f6oRi4sjK+mqQLJDax9orIjrZ2Yd6ASq2Z31lZthgDFTyqe5b+JTP1Sp4j6S9uayIxyGj59eYxB1YMCxrm3clMJRKBphwiNrGewcGWZ2Qb2saB3Ctmy+fxPmasqFfbxnf4LYBib0VQrOpmvbRR8u3CT14ltCTubEA/iw2krMfqlM6xvzukFyRj++8oOfXNMGefGfe11GlcbDWXVDoJURbOjbaGGqks6jdZ0TOD/TxepHHnlBfWgHA9pfibikqBsB8NXvp"
        },
        "endpoint": {
            "scope": {
                "type": "BearerToken",
                "token": "Atza|IwEBIAdKRpKJ5emckzWUGPRR-O9_Pg2mWV0BDxgfUCJbcqNNWSb8zfl4ueaG8eu-1YZOyA3qTyJVnn9X9JtYOfzcJClEROo1bDoGMs_VEeA-7aTZK5RKMWIHIbz8BIdmt6Ncr6bF8WkZnhNjS4q-qim4ICRfatrIaD2C0KXykXNJnYco11aSR7tGkhcwKm27jjPoewap2k07BqMhmaaB2ie_-v_2ojbDWmKW95MuCeYMoZmYTmNh4o4A5YH_UlFO9atUTjr9oA4ROwL_3R02Yi_VYRf8iZJCF4FmxiXRGGMqwEMF1KNeV6zcUFAjBIvSORAOpSO6iRySn9lZeAazywrdCIYBc8LFnDtGQIeYdKXSW39qYFbfC-Hy3RCJwuVPQPzS9jX99pyYZ0q1ZuRRUg"
            },
            "endpointId": "Light",
            "cookie": {}
        },
        "payload": {}
    }
}

So in order to turn on the light at Jhonny's home, I must somehow use the BearerToken from Alexa directive to retrieve the email address or user ID of Jhonny from the Amazon OAuth provider service. Is that correct? Otherwise, I wouldn't know which entry to change in my database.

Now My Question is: How do I use this BearerToken to get the user ID and other information? I need some example code in NodeJS which I can implement in my Lambda Function for this purpose.

Upvotes: 0

Views: 807

Answers (1)

meetpatelvgec
meetpatelvgec

Reputation: 69

We can get the user profile by sending a HTTP GET request to the host using the bearer token. Below link gives a beautiful and very simple way to verify user profile by providing your bearer token, and provide the basic understanding.

https://reqbin.com/req/5k564bhv/get-request-bearer-token-authorization-header-example

In case you are using Login With Amazon as your OAuth2.0 identity provider, then just mention following items on above link:

  • Host URL: https://api.amazon.com/user/profile
  • Select Authorization
  • Select Bearer Token
  • Copy the bearer token received from alexa directive and paste it in the box (it generally starts with Atza|xxxyyyzzz)
  • Click on Send
  • If you have entered correct host URL, path and bearer token, and if your bearer token has not already expired, then you should see 200 response code with user profile details such as user_id, name, email etc.
  • In case your bearer token has expired, you can simply ask Alexa to operate one of the devices, and obtain a new bearer token for verifying from the AWS CloudWatch logs.
  • Bearer Token usually expires in 3600 seconds.

Now to answer my original question, here is a simple code snippet of AWS Lambda using NodeJS which worked for me:

const https = require('https');

const handlerInput = {
    "directive": {
        "header": {
            "namespace": "Alexa.PowerController",
            "name": "TurnOn",
            "payloadVersion": "3",
            "messageId": "f8107929-cc45-4bfe-b7ae-eb9b61c09d5c",
            "correlationToken": "AAAAAAAAAQDaOl/vVaX+GlN2m9SvqFri/AEAAAAAAADsiP98Ew8DnuYv7JWgKtb4W/WFyycSA33aKocZD0AOnl5+PmKQuqgx2p/CT5Efln0lbORsb9jSB/zB9s3RLgO2dCG3B5/b6jzVzch98o3ULz61HgoAPz/ZsZIFWXyfqUhLrdwyggsnInsCOeUOHpRZ15VLJ6oEyW7zNE6MCfcH+SfPB2BMr7ex1wP3Ghz7fPNIwTeMhV/ZstF/mF7K74gH1psCLgGLzdc4YYtRtz7KxHCS3I8eUd2UQZ4NyCf9gVktphgTzXu6ezBp5qoexsmgkHQ0duK0zF2HoKvY8jhVD8MH2unJQLbcn5VQyMololRkQ3E1orZXy86t5Ls1ILC6qbtT1tKbeTqVChTBiCh5jczOuSW5mES+1fmhbBxx1HbE8OXhfSNcXcE2VAY49LTBafnUQ7NftkDTRRFJKgL+IIdBq283SgZNFWmJxwGBN5OXC5vKQGD1QzHUlhb91I9xQ1bmx9jKPP8tBj0ydkY/nD++34zQfxDObbX7cmVs4/4nTKNhm2o2RGZmVyMr6PzhvRzq777Vi+keJM+qXQxSRO0NzdSFWdBDBHCL46nAvwlOjNIvHsOoaODEVNK5HzT6a+H4PsbDazZgfXB4QFjIb9FvFZ6wmlGM1iOU/sN40ro3pQ12IE+Dn+tweemgRaRucn/mT0/E5IRgnliR"
        },
        "endpoint": {
            "scope": {
                "type": "BearerToken",
                "token": "Atza|IwEBINNVA3FmduJsc_iA2Jpo2hBfl2XKPCzujkVWgix2TychTLTuAbnchakWuNiNGnpimsAx2dwoJCoUbarJXRv5a1ECrYoVi-SnAt6xxVvxi4CX4zd13rCq1wddl90Lp71bJDq9qfvlS-d9KillCwRYh4BBY0GegU16hM4RC07nBMvra07Dfe_kq9PIzu4yOeSaLwobiEAhNex3Qyo4n0jW6iyB5YzKUe2UAu0pQZmkeNjRmhPVpy0L4Pv539O87yXBT7iQ8pkhZBKeZWcuFltCN2_v1SfhMNQbnLlt_CMFry-eQg0t9oSaweCJOvrAYVKmg0cd-gNd27ttqZkmD0rMGERmTNkij_rTQJ9iiQKjEW1Xx_7TWVniqda1Hp_o1wA5p4aT6BYQKkoFrRm4pSa3iUA"
            },
            "endpointId": "Light",
            "cookie": {}
        },
        "payload": {}
    }
};

exports.handler = async (event) => {
    // TODO implement
    const accessToken = handlerInput.directive.endpoint.scope.token;
    console.log(accessToken);
    const info = await getUserInfo(accessToken);
    console.log(`info: ${JSON.stringify(info)}`);
    const response = {
        user_ID: info.user_id,
        name: info.name,
        email: info.email,
    };
    return response;
};

async function getUserInfo(accessToken) {
    return new Promise((resolve, reject) => {
        const options = {
            "method": "GET",
            "hostname": "api.amazon.com",
            "path": "/user/profile",
            "headers": {
                "Authorization": `Bearer ${accessToken}`
            }
        };
        let req = https.request(options, (response) => {
            let returnData = '';

            response.on('data', (chunk) => {
                returnData += chunk;
            });

            response.on('end', () => {
                resolve(JSON.parse(returnData));
            });

            response.on("error", (error) => {
                reject(error);
            });
        });
        req.end();
    });
}

Make sure to replace the handlerInput in above code with the most recent copy. You can acquire it from AWS CloudWatch under Logs -> Log Groups.

Below YouTube video also has very useful information about overall process of creating the skill, account linking and identifying user through access token:

https://www.youtube.com/watch?v=NrBBM9XhzG0

Unfortunately, the video doesn't explain how to do it for smart home skill, though it's very similar.

Upvotes: 1

Related Questions