【问题标题】:How to construct OAuth authorization header for RESTlet?如何为 RESTlet 构建 OAuth 授权标头?
【发布时间】:2019-09-21 10:44:07
【问题描述】:

我无法创建 OAuth 授权标头。我不断收到 INVALID_LOGIN_ATTEMPT,但我找不到我做错了什么。

我已按照 here 的指示创建授权标头。

我的完整工作流程:

  • 创建 hello world SuiteScript 2.0 restlet
  • 上传到我的 NetSuite 帐户
  • 创建集成记录
  • 创建部署
  • 创建具有权限的角色:
    • 访问令牌管理 - 完整
    • 使用访问令牌登录 - 完整
    • 用户访问令牌 - 完整
    • Web 服务 - 完整
  • 从上一步创建用户并分配角色
  • 创建集成并启用基于令牌的身份验证
  • 发出新的访问令牌

RESTlet URL 是从部署详细信息中复制/粘贴的,并且 帐户 ID 是从 Setup / Integration / Web Services Preferences 中提取的

这是我的虚拟客户:

const https = require('https');
const crypto = require('crypto');

function generateNonce() {
   return crypto.randomBytes(16).toString("hex");
}

const NETSUITE_ACCOUNT_ID = 'tstdrv00000000';
const BASE_URL = `https://${NETSUITE_ACCOUNT_ID}.restlets.api.netsuite.com/app/site/hosting/restlet.nl`;
const HTTP_METHOD = 'GET';
const SCRIPT_ID = '546';
const SCRIPT_DEPLOYMENT_ID = '1';
const OAUTH_VERSION = '1.0';
const TOKEN_ID = "0";
const TOKEN_SECRET = "0";
const CONSUMER_KEY = "0";
const CONSUMER_SECRET = "0";
const OAUTH_NONCE = generateNonce();
const TIMESTAMP = Date.now();

function createSignature() {
    const key = `${CONSUMER_SECRET}&${TOKEN_SECRET}`;
    const data = `deploy=${SCRIPT_DEPLOYMENT_ID}&oauth_consumer_key=${CONSUMER_KEY}&oauth_nonce=${OAUTH_NONCE}&oauth_signature_method=HMAC-SHA256&oauth_timestamp=${TIMESTAMP}&oauth_token=${TOKEN_ID}&oauth_version=${OAUTH_VERSION}&script=${SCRIPT_ID}`;

    const payload = `${HTTP_METHOD}&${encodeURIComponent(BASE_URL)}&${encodeURIComponent(data)}`;

    const hmac = crypto.createHmac('sha256', key);
    const digest = hmac.update(payload).digest('hex');
    const signature = new Buffer(digest).toString('base64');
    return signature;
}

let OAuth = `OAuth oauth_signature="${createSignature()}", oauth_version="1.0", oauth_nonce="${OAUTH_NONCE}", oauth_signature_method="HMAC-SHA256", oauth_consumer_key="${CONSUMER_KEY}", oauth_token="${TOKEN_ID}", oauth_timestamp="${TIMESTAMP}", realm="${NETSUITE_ACCOUNT_ID}"`;

const request = new Promise((resolve, reject) => {
    const responsePayload = [];
    const request = https.get(
        `${BASE_URL}?script=${SCRIPT_ID}&deploy=${SCRIPT_DEPLOYMENT_ID}`,
        {
            headers: {
                "Content-Type": "application/json",
                "Authorization": OAuth
            },
        },
        (response) => {
            console.log("statusCode: ", response.statusCode);
            console.log("headers: ", response.headers);
            response.setEncoding('utf8');
            response.on('data', chunk => {
                responsePayload.push(chunk);
            });
            response.on('end', () => {
                try {
                    resolve(JSON.parse(responsePayload.join()));
                } catch (error) {
                    resolve(responsePayload);
                }
            });
        }
    );
    request.on('error', error => {
        reject(error);
    });
    request.end();
});

request
    .then((response => console.log("OK", response)))
    .catch(e => console.error("Error", e));

【问题讨论】:

  • 我刚刚注意到您正在使用 HMAC-SHA256,您应该使用 HMAC-SHA1

标签: node.js netsuite suitescript2.0


【解决方案1】:

我用过这个包:https://www.npmjs.com/package/oauth-1.0a

var oauth = new OAuth({   
   "hash_function" : function(base_string, key) {
       return crypto.createHmac('sha1', key).update(base_string).digest('base64');
   },
   "consumer" : { "key" : CONSUMER_KEY, "secret" : CONSUMER_SECRET },
   "signature_method" : "HMAC-SHA1"
});

const oauthToken = { "key" : OAUTH_TOKEN, "secret" : OAUTH_TOKEN_SECRET },
    request = { "url" : url, "method' : method };

let headers = oauth.toHeader(oauth.authorize(request, oauthToken));
headers.Authorization += `,realm=${REALM}`;

【讨论】:

    【解决方案2】:

    INVALID_LOGIN_ATTEMPT

    此错误表明 OAuth 标头中存在问题。当 OAuth 标头中的 nonce、consumer key、token 或签名无效时,可以返回。

    我认为您的签名不正确。它应该在您的可变负载上具有与您的 xhr 请求相同的 url/参数来生成签名:

    const payload = '${HTTP_METHOD}&${BASE_URL}?script=${SCRIPT_ID}&deploy=${SCRIPT_DEPLOYMENT_ID}&${encodeURIComponent(data)}';
    
    const request = new Promise((resolve, reject) => {
        const responsePayload = [];
        const request = https.get(
            '${BASE_URL}?script=${SCRIPT_ID}&deploy=${SCRIPT_DEPLOYMENT_ID}&${encodeURIComponent(data)}',
            {
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": OAuth
                },
            },
    ...
    

    【讨论】:

      猜你喜欢
      • 2012-06-19
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 2012-08-18
      • 1970-01-01
      相关资源
      最近更新 更多