Postman 请求 Amazon Alexa Smart Home Skill LWA 时客户端身份验证失败

Client authentication failed in Postman request for Amazon Alexa Smart Home Skill LWA

我指的是 Amazon documentation 是为了客户身份验证。目前,我正在使用 LWA。

我遵循的步骤:

  1. 我在“构建”>“权限”页面中从 Alexa 开发人员控制台启用了发送 Alexa 事件权限。

  2. 我从 c​​loudwatch 日志中的请求中获取了授权代码,该请求是在我使用 Alexa 配套应用程序登录时发送的。

示例:-

    {
     "directive": {
         "header": {
             "messageId": "Example",
             "name": "AcceptGrant",
             "namespace": "Alexa.Authorization",
             "payloadVersion": "3"
         },
         "payload": {
            "grant": {
                "code": "Example2",
                "type": "OAuth2.AuthorizationCode"
            },
            "grantee": {
                "token": "Example3",
                "type": "BearerToken"
            }
         }
      }
    }
  1. 在 Alexa Developer 控制台上构建的权限页面给了我客户端 ID 和客户端密码,我用它们向 https://api.amazon.com/auth/o2/token 发出 post 请求。

示例:-

 POST /auth/o2/token HTTP/l.l
 Host: api.amazon.com
 Content-Type: application/x-www-form-urlencoded;charset=UTF-8 
 grant_type=authorization_code&code=&client_id=&client_secret=

我在上面的例子中传递了代码client_id和client_secret,并向这个URLhttps://api.amazon.com/auth/o2/token[=16发出了post请求=]

  1. 我尝试使用 x-www-form-urlencoded;charset=UTF-8 以及 JSON 作为 Content-Type。

我按照上述文档中给出的步骤进行操作,但仍卡在错误 ( 401 Unauthorized ) 中:

{
    "error_description": "The request has an invalid grant parameter : code",
    "error": "invalid_grant"
}

我尝试使用 Python 代码和 Postman 来实现它。以上述相同的错误场景结束。

这是一个示例代码,可以帮助您和其他希望将事件发送到 alexa 网关的人。

const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-1'});

// Create the DynamoDB service object
const ddb = new AWS.DynamoDB({ apiVersion: 'latest' });
const doc = new AWS.DynamoDB.DocumentClient({
            convertEmptyValues: true,
            service: ddb
        });        

// Using 'request' for http POST and GET request.
// https://www.npmjs.com/package/requests
// npm install --save requests 
const r = require('request');

//Handle Authorization. Call this method from your lambda handler whenever you get Alexa.Authorization message. You will get this message only when you select permission to 
//send events in your Smart Home Skill.
//Access to Event gateway allows you to enable Proactive Device Discovery and 
//Proactive State Reporting in your skill
//More information on Alexa.Authorization can be found on https://developer.amazon.com/docs/device-apis/alexa-authorization.html
function handleAuthorization(request, context, user) {  

    //Even when you are using your own authentication, the url below will still
    //point to amazon OAuth token url. The token you obtain here has to be stored
    //separately for this user. Whenever sending an event to alexa event gateway you will
    //require this token.
    //URL below is for EU server. Look at following documentation link to identify correct url
    //for your system.
    //https://developer.amazon.com/docs/smarthome/send-events-to-the-alexa-event-gateway.html
    var url = "https://api.amazon.com/auth/o2/token";
    var body = {
        grant_type : 'authorization_code',
        code : request.directive.payload.grant.code,
        client_id : 'your client id from permissions page on developer portal where you enable alexa events. This is id different than one you specify in account linking settings',
        client_secret : 'client secret from permissions page'
    }

    //https://developer.amazon.com/docs/smarthome/authenticate-a-customer-permissions.html
    r.post({
      url:     url,
      form :  body
    }, function(error, response, b){    
        if (error) { return console.log(error); }
        var body = JSON.parse(b);
        var params = {
          TableName: 'Devices',
          Item: {
            'id' : user,
            'auth_token' : body.access_token,
            'refresh_token' : body.refresh_token
          }
        }
        log("DEBUG:", "Authorization Body", JSON.stringify(body));
        log("DEBUG:", "Authorization Response", JSON.stringify(response));
        log("DEBUG:", "Database Params", JSON.stringify(params));

        // Call DynamoDB to add the item to the table
        var putObjectPromise = doc.put(params).promise();
        //Store auth_token and refresh_token in database. We will need these
        //while sending events to event gateway.
        //Send a success response.
        putObjectPromise.then(function(data) {
            var response = {
              event: {
                header: {
                  messageId: request.directive.header.messageId,
                  namespace: "Alexa.Authorization",
                  name: "AcceptGrant.Response",
                  payloadVersion: "3"
                },
                "payload": {
                }
              }
            };

            context.succeed(response);
        }).catch(function(err) {
            //TODO - Add a Authorization error response JSON here.      
            console.log(err);
        });                         
    });                   
}