在 Trello API OAuth 中访问令牌时获取无效签名

Getting Invalid Signature when accessing tokens in Trello API OAuth

我正在尝试在 PHP 中实现 trello api 的包装器。我在 OAuth 流程的最后一步得到 "Invalid signature",我必须从 trello api 获取访问令牌。 仅通过这条消息,我无法调试我做错了什么。

基本上我所做的是...

  1. 发送获取请求令牌的请求 (https://trello.com/1/OAuthGetRequestToken)。这很顺利。我得到了两个参数 oauth_tokenoauth_token_secret 作为响应。
  2. 然后我打开了 trello 授权页面 url (https://trello.com/1/OAuthAuthorizeToken),其中包含步骤 1 中的参数 oauth_token、应用程序名称和 return url本地主机。这也很顺利。 Trello 使用参数 oauth_tokenoauth_verifier.
  3. 重定向到 localhost/callback
  4. 在回调中,我终于发送了获取访问令牌的请求 (https://trello.com/1/OAuthGetAccessToken)。我从第 1 步添加了 oauth_token & oauth_token_secret,从第 2 步添加了 oauth_verifier,并使用 HMAC-SHA1 方法添加了签名。当我收到消息 "Invalid signature"!!!
  5. 的 500 内部错误时,这就出错了

有人知道哪里出了问题吗?

这是我在回调中使用的代码。

$nonce = md5(mt_rand());
$timestamp = time();

$oauth_signature_base = 'GET&'.
    rawurlencode('https://trello.com/1/OAuthGetAccessToken').'&'.
    rawurlencode(implode('&', [
        'oauth_consumer_key='.rawurlencode('CONSUMER_KEY_HERE'),
        'oauth_nonce='.rawurlencode($nonce),
        'oauth_signature_method='.rawurlencode('HMAC-SHA1'),
        'oauth_timestamp='.rawurlencode($timestamp),
        'oauth_token='.rawurlencode('OAUTH_TOKEN_HERE'),
        'oauth_token_secret='.rawurlencode('OAUTH_TOKEN_SECRET_HERE'),
        'oauth_verifier='.rawurlencode('OAUTH_VERIFIER_HERE'),
        'oauth_version='.rawurlencode('1.0')
        ]));

$signature = base64_encode(hash_hmac('sha1', $oauth_signature_base, 'CONSUMER_SECRET_HERE&', true));

$params = [
    'oauth_consumer_key='.rawurlencode('CONSUMER_KEY_HERE'),
    'oauth_nonce='.rawurlencode($nonce),
    'oauth_signature_method='.rawurlencode('HMAC-SHA1'),
    'oauth_timestamp='.rawurlencode($timestamp),
    'oauth_token='.rawurlencode('OAUTH_TOKEN_HERE'),
    'oauth_token_secret='.rawurlencode('OAUTH_TOKEN_SECRET_HERE'),
    'oauth_verifier='.rawurlencode('OAUTH_VERIFIER_HERE'),
    'oauth_version='.rawurlencode('1.0'),
    'oauth_signature='.rawurlencode($signature)
];
file_get_contents(sprintf('%s?%s', 'https://trello.com/1/OAuthGetAccessToken', implode('&', $params)));

oauth 令牌机密不应包含在 URL 参数中,无论是在生成基本字符串时还是在发送实际请求时。令牌秘密仅用作散列密钥的一部分。请参阅下面的修改代码:

$nonce = md5(mt_rand());
$timestamp = time();

$oauth_signature_base = 'GET&'.
rawurlencode('https://trello.com/1/OAuthGetAccessToken').'&'.
rawurlencode(implode('&', [
    'oauth_consumer_key='.rawurlencode('CONSUMER_KEY_HERE'),
    'oauth_nonce='.rawurlencode($nonce),
    'oauth_signature_method='.rawurlencode('HMAC-SHA1'),
    'oauth_timestamp='.rawurlencode($timestamp),
    'oauth_token='.rawurlencode('OAUTH_TOKEN_HERE'),
    'oauth_verifier='.rawurlencode('OAUTH_VERIFIER_HERE'),
    'oauth_version='.rawurlencode('1.0')
    ]));

//token secret should be (singly) URL encoded if not already
$signature = base64_encode(hash_hmac('sha1', $oauth_signature_base, 'CONSUMER_SECRET_HERE&TOKEN_SECRET_HERE', true));

$params = [
'oauth_consumer_key='.rawurlencode('CONSUMER_KEY_HERE'),
'oauth_nonce='.rawurlencode($nonce),
'oauth_signature_method='.rawurlencode('HMAC-SHA1'),
'oauth_timestamp='.rawurlencode($timestamp),
'oauth_token='.rawurlencode('OAUTH_TOKEN_HERE'),
'oauth_verifier='.rawurlencode('OAUTH_VERIFIER_HERE'),
'oauth_version='.rawurlencode('1.0'),
'oauth_signature='.rawurlencode($signature)
];
file_get_contents(sprintf('%s?%s', 'https://trello.com/1/OAuthGetAccessToken', implode('&', $params)));