Delphi TOAuth1Authenticator как установить Realm

Попытка использовать/вызвать рестлет NetSuite с аутентификацией на основе токенов с использованием Delphi RESTClient. У меня есть рабочий запрос Postman, который проверяет все необходимые параметры авторизации. Один отсутствующий параметр — область — при добавлении в код изменяет сообщение об ошибке, возвращаемое со стороны NetSuite, но все равно не приводит к успешному вызову.

procedure TForm1.OAuth1Authenticator1Authenticate(ARequest: TCustomRESTRequest;
    var ADone: Boolean);
begin
  // XXXXXXX_RP is a NetSuite account number and environment 
  ARequest.AddAuthParameter('realm','XXXXXX_RP',pkQUERY);  
end;

Если область не добавлена ​​(приведенный выше код закомментирован), возвращаемое оставшееся содержимое:

error code: USER_ERROR
error message: header is not NLAuth scheme [ OAuth oauth_consumer_key="fe8da7b31dccbd47e90e5dd5e641fe7b0cbff032a951b4058618c207caf569f8", oauth_nonce="c98fa9de2c601f45bdc8d5c640f1b3cf", oauth_signature_method="HMAC-SHA1", oauth_signature="PfCQE3A4DicTtCfpBEPmbSOmqNg%3D", oauth_timestamp="1568639138", oauth_token="a8190ba34e223f25b32cdb4837d9e1973b8fd6208804e93306f4618ccdb6d648", oauth_version="1.0" ]

С добавлением области я все еще получаю:

error code: INVALID_LOGIN_ATTEMPT
error message: Invalid login attempt.

Кто-нибудь успешно звонил в рестлеты NetSuite с помощью Delphi RESTClient?

Обновление: похоже, он не поддерживает использование необязательного параметра области. При добавлении вручную он добавляется в список нормализованных параметров для подписи, когда этого не должно быть. Я изменил TOAuth1SignatureMethod_HMAC_SHA1.BuildSignature в REST.Authenticator.OAuth, чтобы пропустить этот параметр (просто добавил блок if Lparam.Name <> 'realm' then begin .. end; вокруг некоторого кода), но все равно не удалось успешно выполнить запрос к NetSuite. Сделал это после прочтения https://oauth.net/core/1.0/ раздела 9.1.1. Нормализация параметров запроса:

Параметры запроса собираются, сортируются и объединяются в нормализованную строку:

  • Параметры в заголовке авторизации HTTP OAuth за исключением параметра области.
  • Параметры в теле запроса HTTP POST (с типом содержимого application/x-www-form-urlencoded).
  • Параметры HTTP GET добавляются к URL-адресам в части запроса (как определено в разделе 3 [RFC3986]).

person Brian    schedule 16.09.2019    source источник


Ответы (1)


В итоге вручную собрал запрос с помощью Indy. Копия части, которая собирает заголовок AUTH, приведена ниже вместе с кодом, выполняющим тестовый запрос с использованием Indy IdHTTP. Примечание: номер учетной записи Netsuite и идентификаторы/секреты предназначены только для демонстрации.

procedure TForm1.Button1Click(Sender: TObject);
Const
  NETSUITE_ACCOUNT_ID = '4000000_RP';
  BASE_URL = 'https://4000000-rp.restlets.api.netsuite.com/app/site/hosting/restlet.nl';
  HTTP_METHOD = 'POST';
  SCRIPT_ID = '331';
  SCRIPT_DEPLOYMENT_ID = 'customdeploy_salesorderimport';
  OAUTH_VERSION = '1.0';
  TOKEN_ID = 'a8190ba34e223f25b3267843437d9e1973b8fd6208804e93306f4618ccdb6d648';
  TOKEN_SECRET = 'ecb5321eaf832714828ede7f920320b942ad6b2d4221da3b12496f389d68e1c4';
  CONSUMER_KEY = 'fe8da7c2cbd47e90e5dd5e6415fe7b0cbff2032a5951b4058618c07c7af569f8';
  CONSUMER_SECRET = '848cae6150a651ecbc6975656f4b92ca08d7c27c829185cf98e7a0a30c24dbc2';
Var
  OAUTH_NONCE,TIME_STAMP,STRING2SIGN : string;
  oauth_signature, oauth, BaseURL : string;
  JSONValue : TJsonValue;
begin
  OAUTH_NONCE :=  THashMD5.GetHashString(IntToStr(DateTimeToUnix(TTimeZone.Local.ToUniversalTime(Now))) + IntToStr(Random(MAXINT)));
  TIME_STAMP := IntToStr(DateTimeToUnix(TTimeZone.Local.ToUniversalTime(Now)));

  // These are in alphabetical order - required by signing
  STRING2SIGN := '';
  STRING2SIGN := STRING2SIGN + 'deploy=' + SCRIPT_DEPLOYMENT_ID + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_consumer_key=' + CONSUMER_KEY + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_nonce=' + OAUTH_NONCE + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_signature_method=' + 'HMAC-SHA256' + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_timestamp=' + TIME_STAMP + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_token=' + TOKEN_ID + '&';
  STRING2SIGN := STRING2SIGN + 'oauth_version=' + OAUTH_VERSION + '&';
  STRING2SIGN := STRING2SIGN + 'script=' + SCRIPT_ID;
  STRING2SIGN := URIEncode(STRING2SIGN);
  STRING2SIGN := HTTP_METHOD + '&' + URIEncode(BASE_URL) + '&' + STRING2SIGN;
  oauth_signature := URIEncode(TNetEncoding.Base64.EncodeBytesToString(THashSHA2.GetHMACAsBytes(STRING2SIGN, CONSUMER_SECRET + '&' + TOKEN_SECRET)));

  oauth :='OAuth oauth_signature="' + oauth_signature + '",';
  oauth := oauth + 'oauth_version="' + OAUTH_VERSION + '",';
  oauth := oauth + 'oauth_nonce="' + OAUTH_NONCE + '",';
  oauth := oauth + 'oauth_signature_method="HMAC-SHA256",';
  oauth := oauth + 'oauth_consumer_key="' + CONSUMER_KEY + '",';
  oauth := oauth + 'oauth_token="' + TOKEN_ID + '",';
  oauth := oauth + 'oauth_timestamp="' + TIME_STAMP + '",';
  oauth := oauth + 'realm="' + NETSUITE_ACCOUNT_ID + '"';

  BaseURL := BASE_URL + '?script=' + SCRIPT_ID + '&deploy=' + SCRIPT_DEPLOYMENT_ID;

  IdHTTP1.Request.CustomHeaders.FoldLines := false;
  IdHTTP1.Request.Accept := 'application/json, text/javascript, */*; q=0.01';
  IdHTTP1.Request.ContentType := 'application/json';
  IdHTTP1.Request.CustomHeaders.Values['Authorization'] := oauth;
try
  memo1.Text := idhttp1.Post(BaseURL,'C:\Users\bevans\Documents\Json.txt');
  JSONValue :=  TJSonObject.ParseJSONValue(memo1.Text);
  SynEdit1.Text := JSonValue.Format;
finally
  JSonValue.Free;
end;

Примечание. Код обновлен для использования SHA256 вместо SHA1 для подписи OAUTH. Компания NetSuite разослала уведомление, что они потребуют этого в выпуске NetSuite 2021.2.

person Brian    schedule 23.09.2019