уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Примерно год назад я делал небольшой обзор компонента от TMS для работы с Dropbox. Тогда компонент этот был, мягко говоря, «сыроват» и было решено для своих нужд использовать аналогичный компонент от Astonsoft, который на тот момент работал стабильнее и, в принципе, его возможностей вполне хватало. Вполне вероятно, что за год TMS Software улучшило работу своего компонента — я не проверял. Однако оба эти компонента являются платными и не всякий любитель Delphi «потянет» такую сумму на покупку одного компонента. Умолчим про возможности скачать эти и другие компоненты бесплатно. Просто представим, что нам для работы над неким небольшим коммерческим проектом потребовалась очень и очень ограниченная часть возможностей API Dropbox и покупать ради этого компонент — лишние финансовые траты (мы и так вложились «по самое не хочу» в покупку Delphi XE6). Сейчас у нас самая последняя версия Delphi в которой имеется замечательная библиотека REST Client Library с помощью которой можно реализовать работу практически с любым онлайн-сервисом с минимумом затрат (например, с сетью ВКонтакте). Но, как оказалось, не всё так гладко при авторизации по OAuth 2.0 в Dropbox. Рассмотрим работу REST Client Library на двух примерах.

Первый пример — авторизация по OAuth 2.0 в сервисах Google.

В принципе, этот пример я уже приводил, когда только-только знакомился с библиотекой REST Client Library в Delphi XE5.

Создаем в Delphi XE6 новый проект, бросаем на форму компонент OAuth2Authenticator с вкладки «REST Client», делаем двойной клик по компоненту и в открывшемся задаем такие значения параметров:

  • Authorization-Endpointhttps://accounts.google.com/o/oauth2/auth
  • Token-Endpointhttps://accounts.google.com/o/oauth2/token
  • Redirctioon-Endpointurn:ietf:wg:oauth:2.0:oob
  • Client-ID: значение Client ID вашего проекта
  • Client-Secret: значение Client Secret вашего проекта
  • Access-Scopehttps://www.googleapis.com/auth/drive
  • Response-Type: code

(естественно, что перед этим надо создать новое приложение в консоли Google). Должно получиться вот так:

restlib_11

Таким образом, мы пытаемся получить доступ к сервису Google.Диск. Жмем кнопочку «Authorize», в открывшемся окне залогиниваемся в Google, даем разрешение на доступ и в итоге компонент из REST Client Library прекрасно получает и Access Token и Refresh Token о чем свидетельствует следующий скрин:

restlib_12

Как видите — всё элементарно и просто. Теперь можем бросать на форму компоненты RESTClient, RESTRequest, RESTResponse и работать с API.

Теперь попробуем реализовать тоже самое, но только с Dropbox.

Второй пример — авторизация по OAuth 2.0 в Dropbox.

На данный момент Dropbox поддерживает авторизацию как по OAuth 1.0, так и по OAuth 2.0, что не может не радовать. Пробуем авторизоваться по OAuth 2.0. В документации сказано, что можно авторизоваться и без получения промежуточного параметра Code для чего в консоли управления приложением необходимо разрешить использование «implicit grant«:

dropbox

Ок. Всё включили, Redirect URI задали. Теперь в компоненте OAuth2Authenticator нам необходимо задать такие значения параметров:

  • Authorization-Endpointhttps://www.dropbox.com/1/oauth2/authorize
  • Token-Endpointhttps://api.dropbox.com/1/oauth2/token
  • Redirctioon-Endpoint: http://localhost
  • Client-ID: значение App Key вашего проекта
  • Client-Secret: значение App Secret вашего проекта
  • Access-Scope: не задаем
  • Response-Typetoken

Проверяем. Жмем кнопку «Authorize» и нас ожидаемо просят ввести свой логин и пароль в Dropbox:

dopbox2

Логинимся, в следующем окне разрешаем доступ к своим данным в Dropbox…и вместо Access Token получаем вот такую «картину маслом»:

dropbox3

Итог — ключа доступа нет, дальнейшая работа с компонентами невозможна. Как быть? Давайте разбираться.

Авторизация по OAuth 2.0. в Dropbox без REST Client Library.

Для начала я решил проверить что вообще происходит в тот момент, когда я разрешаю доступ к моим данным. Так как для работы с OAuth 2.0. нам не требуется составлять и шифровать всякие хитрые параметры как это было в OAuth 1.0, то для такой проверки нам требуется совсем немного компонентов, а именно:

  1. Webbrowser для отображения страниц
  2. Memo — для ведения лога работы программы

Бросаем эти компоненты на форму так как вам угодно и читаем документацию по OAuth 2.0 в Dropbox. Прежде всего нам необходимо составить правильный URL. Для того, чтобы сразу получать Access Token наш URL должен иметь вот такую форму:

https://www.dropbox.com/1/oauth2/authorize?response_type=token&client_id=%s&redirect_uri=%s

где client_id — это App Key приложения, а redirect_uri — это заданный нами Redirect URI в Консоли приложения.

Далее из той же документации следует, что если пользователь перейдет в браузере по этому URL, залогинится в сервисе и даст добро на доступ к данным, то в итоге пользователя перенаправят по URL вот такого содержания:

[REDIRECT_URI]#access_token=ABCDEFG&token_type=bearer&uid=12345&state=[STATE]

Здесь как раз и содержится то, что нам надо — Access Token. Проверим, как работает этот простой алгоритм авторизации на практике. Задаем несколько констант и пишем такой код на OnShow формы (если не нравится OnShow — пишите где нравится):

const
  AppKey='какой-то ключ';
  RedirectURI = 'http://localhost';
  AuthURL = 'https://www.dropbox.com/1/oauth2/authorize?response_type=token&client_id=%s&redirect_uri=%s';
 
procedure TForm1.FormShow(Sender: TObject);
var URL: string;
begin
  URL:=Format(AuthURL,[AppKey,RedirectURI]);
  WebBrowser1.Navigate2(URL);
end;

Теперь, чтобы отслеживать куда нас перенаправляют зададим обработчик события OnBeforeNavigate2 у TWebBrowser:

procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
begin
  Memo1.Lines.Add(URL)
end;

Запускаем приложение и смотрим что в итоге происходит. А происходит следующее: обработчик срабатывает дважды. Первый раз, как и полагается, перед тем как открыть страницу по URL, который мы сами же и создаем. Здесь все в порядке. Второй раз обработчик срабатывает после того как мы разрешаем доступ к данным в Dropbox, НО вместо ожидаемого перенаправления на http://localhost#что-то-там нас кидает на вот такой замечательный URL:

https://www.dropbox.com/1/oauth2/authorize_submit

и именно на этом месте и появляется Error 404 и компонент REST Client Library, естественно, к такому повороту не готов. Как бороться с таким поведением сервиса Dropbox? Решение оказалось довольно простым. Создаем у WebBrowser обработчик события OnNavigationError и пешем там всего одну строку:

procedure TForm1.WebBrowser1NavigateError(ASender: TObject;
  const pDisp: IDispatch; const URL, Frame, StatusCode: OleVariant;
  var Cancel: WordBool);
begin
 Cancel:=True;
end;

После чего можно смело отлавливать в событии OnNavigateComplete2 URL, содержащий токен доступа. Вот как он будет выглядеть в нашей программе:
dropbox4Принципиальная проблема решена, а теперь несколько слов непосредственно о REST Client Library. Первое:

Для FMX при использовании REST Client Library ничего менять в работе WebBrowser не требуется

Может показаться удивительным, но факт — в мобильном приложении авторизация прошла без проблем. Получал доступ к Dropbox точно также, как и при работе с ВКонтакте — Access Token получен.

Что касается версии для VCL. Форма авторизации находится в модуле REST.Authenticator.OAuth.WebForm.Win. Необходимо самостоятельно определить обработчик события OnNavigateError у Browser так как показано выше, а искать Access Token как и всегда в обработчике события OnAfterRedirect формы авторизации.

Собственно на этом вопрос самостоятельной авторизации по OAuth 2  в Dropbox можно считать закрытым. Теперь можно спокойно авторизовываться и работать с API.

Книжная полка

Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
12 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Arreay
Arreay
09/08/2014 05:34

Решил попробовать, действительно есть данная проблема с компонентом, НО, если запустить веб сервер на http://localhost (80 порт) то всё работает отлично, то есть вместо «Redirctioon-Endpoint: http://localhost«, установить любой работающий сервер (только https!), компонент отлично отрабатывает, очевидно в мобильном приложении что то висело на 80 порту.

Николай Воронов

А как авторизироватся в Dropbox без использования WebBrowser — все данные вводить в стандартных формах
Использую Lazarus+Synapse

Андрей
Андрей
24/08/2015 18:25

На планшете с андроидом, обратил внимание, что некоторые проги при необходимости обращении к гуглодиску — для авторизации показывают самопальные окна для ввода пароля\логина от гугла — и это довольно неудобно.
А вот некоторые проги умеют показывать окошко в котором показаны текущие зарегистрированные на планшете эккаунты гугла — и ты выбираешь нужный — жмешь подтверждение от гугла — и всё, прога дальше уже имеет доступ к файлам на гуглодиске.
Как вот такое реализовать, доступ к гуглодиску используя уже зарегенный эккаунт от гугла на планшете? В какую сторону смотреть?

Ruslan
Ruslan
18/02/2017 01:19

Откровенный бред эта OAuth 2.0, так как браузер сам по себе не божественная вещь и всё, что в него может ввести юзер можно и достать. Сама идея в основе гнилая

Андрей Григорьев

Здравствуйте
Подскажите, где найти похожие статьи по работе с REST library и Dropbox api
Или здесь объясните, пожалуйста
С этой проблемой вожусь уже месяц, кучу форумов и статей облазил — не получилось все равно
успешно получил токен доступа
Вот пытаюсь составить запрос на скачивание файла (из корневой папки дропбокса)

RESTRequest1.Method := TRestRequestMethod.rmPOST;
RESTClient1.BaseURL := ‘https://content.dropboxapi.com/2/files/download’;
RESTRequest1.Params.AddHeader(‘Authorization’,’Bearer ‘ + OAuth2Authenticator1.AccessToken);
RESTRequest1.Params.AddHeader(‘Dropbox-API-Arg’,'{«path»: «/MyFile.dat»}’);
RESTRequest1.Params.AddItem(‘path’,’/MyFile.dat’,pkGETorPOST,[poDoNotEncode]);
RESTRequest1.Execute;
local_filename := ExtractFilePath(ParamStr(0)) + ‘MyFile.dat’;
SomeStream := tmemorystream.Create;
try
SomeStream.WriteData(RESTResponse1.RawBytes,
length(RESTResponse1.RawBytes));
SomeStream.SaveToFile(local_filename);
finally
SomeStream.Free;
end;

в документации сказано запрос составлять так
https://www.dropbox.com/developers/documentation/http/documentation#files-download

И вроде ничего не упустил
Но выскакивает исключение 400 плохой реквест

Что не так?

Анонимно
24/03/2018 04:36

Здравствуйте
та же задача… 2 день мучаюсь. скиньте если решение найдено.

Igor Ievlev
Igor Ievlev
15/10/2020 11:43

Vlad, идея обойти ограничения TOAuth2Authenticator и вручную подготовить URL с параметрами для TWebBrowser мне понравилась. Я попробовал также сделать для аутентификации на сервере ЕСИА. Но URL получается слишком большой. Из-за client_secret содержащего подпись, длина URL больше чем 2083 символа. TWebBrowser такие URL обрезает. Я использую Delphi 10.4.1. На сегодня это последняя версия. Не понимаю, как обойти это ограничение в 2083 символа в URL.

Igor Ievlev
Igor Ievlev
16/10/2020 17:41
Ответить на  Vlad

Подпись, формируемую при помощи КриптоПРО вряд ли можно укоротить. Только одна она, без других параметров в URL, переведённая в base64 занимает более 3800 символов. На стороне сервера ЕСИА её ожидают именно такую. Полагаю, что IE для этого не подходит. А именно он подразумевается в Delphi в качестве движка к TWebBrowser. Я думаю попробовать пойти другим путём. Написать web-приложение на IntraWeb. Там не будет привязки к IE. А в других браузерах нет таких жестких ограничений.