如何签署http请求https://api.x.com's oauth 1.0a流?

问题描述 投票:0回答:0
/oauth/request_token

端点收到状态401错误。我正在使用

Https://api.x.com
进行三步验证的三步过程中的第一步。 import crypto from 'crypto'; import axios from 'axios'; import { NextResponse } from 'next/server'; const X_CLIENT_ID = process.env.X_CLIENT_ID as string; const X_CLIENT_SECRET = process.env.X_CLIENT_SECRET as string; const X_CALLBACK_URL = process.env.X_CALLBACK_URL as string; if (!X_CLIENT_ID || !X_CLIENT_SECRET || !X_CALLBACK_URL) { throw 'Missing env vars'; } const BASE_URL = 'https://api.x.com/oauth/request_token'; export async function GET() { try { const params = createSignedRequestParams(); const authorizationHeader = `Oauth oauth_callback="${params.oauth_callback}",oauth_consumer_key="${params.oauth_consumer_key}",oauth_nonce="${params.oauth_nonce}",oauth_signature="${params.oauth_signature}",oauth_signature_method="${params.oauth_signature_method}",oauth_timestamp="${params.oauth_timestamp}",oauth_version="${params.oauth_version}"` const response = await axios.post(BASE_URL, null, { headers: { 'User-Agent': 'Cutcosts', 'Host': 'api.x.com', 'Accept': '*/*', 'Authorization': authorizationHeader } }); console.log(response); return NextResponse.json({ success: true }) } catch (error: any) { console.log(JSON.stringify(error, null, 2)); return NextResponse.json({ message: 'Internal server error' }, { status: 500 }); } } function enc(str: string) { return encodeURIComponent(str); } function createSignedRequestParams() { // RFC 5849 Section 3.4.1 // Encoding method is only necessary for custom methods const method = 'POST'; // Params const params: Record<string, string> = { 'oauth_callback': X_CALLBACK_URL, 'oauth_consumer_key': X_CLIENT_ID, // "API Key" in X Developer Portal, per https://docs.x.com/resources/fundamentals/authentication/oauth-1-0a/obtaining-user-access-tokens#overview-of-the-process 'oauth_nonce': Math.random().toString(36).substring(2) + Math.random().toString(36).substring(2), 'oauth_signature_method': 'HMAC-SHA1', 'oauth_timestamp': String(Math.floor(Date.now() / 1000)), 'oauth_version': '1.0' }; // Encode params const encodedParams: Record<string, string> = {}; Object.keys(params).forEach((key) => { encodedParams[key] = enc(params[key]); }); // Normalize encoded params const normalizedParams = Object.keys(encodedParams).sort().map(key => `${key}=${encodedParams[key]}`).join('&'); // The example in RFC 5849 Section 3.4.1.1 shows one ampersand after POST, and one after base URL // the rest of the ampersands and equal signs in params are encoded // Encode normalize params const encodedNormalizedParams = normalizedParams; // enc(normalizedParams); // Encode base url const encodedBaseUrl = enc(BASE_URL); // Construct base string // https://docs.x.com/resources/fundamentals/authentication/oauth-1-0a/creating-a-signature#creating-the-signature-base-string const baseString = method + '&' + encodedBaseUrl + '&' + enc(encodedNormalizedParams); console.log('Example:', 'POST&https%3A%2F%2Fapi.x.com%2F1.1%2Fstatuses%2Fupdate.json&include\_entities%3Dtrue%26oauth\_consumer\_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth\_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth\_signature\_method%3DHMAC-SHA1%26oauth\_timestamp%3D1318622958%26oauth\_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521'); console.log('Actual:', baseString); // Construct encoded signature // X_CLIENT_SECRET is "API Secret" in X Developer Portal, per https://docs.x.com/resources/fundamentals/authentication/oauth-1-0a/obtaining-user-access-tokens#overview-of-the-process const signingKey = enc(X_CLIENT_SECRET) + '&'; const signature = crypto.createHmac('sha1', signingKey) .update(baseString) .digest('base64'); const encodedSignature = enc(signature); // Update params to include encoded signature encodedParams.oauth_signature = encodedSignature; return encodedParams; } touble尝试的尝试:

在授权标题中“ oauth”之后编码整个字符串的尝试。 (状态400)
tried在base64(状态400)中不编码签名后不编码签名。
tried将oauth_callback参数放在邮局中而不是授权标题(状态401)
trimed在签名创建期间不编码归一化参数(状态401)

允许X开发人员门户网站中的回调URI匹配邮政请求中的回调URI

确认oauth_consumer_key值与x开发人员portal

中的客户端ID值匹配

允许在POST请求签名过程中使用的值与X DeveloperPortal

的客户端秘密匹配

使用“ API密钥”和“ API秘密”进行OAuth_Consumer_key和签名秘密而不是客户ID和客户端秘密(从DOCS [dot] x [dot] com/com/resources/resources/fundeathical/authentication/oauth-1-0a/获得-user-access-tokens#概述的概述,这实际上对于OAuth 1.0A流是正确的,但是我仍然会收到一个状态401)

我还能解决什么?

我有签名步骤正确吗? (CreateHmac,Update,Digest)

XAPI认为授权标题中的“ oauth”字符串是对病例敏感的,因此我必须确保我有“ oauth”而不是“ oauth”才能获得200个好的响应。

javascript http twitter oauth-1.0a
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.