Evgenii Legotckoi
Evgenii LegotckoiJan. 26, 2017, 12:07 p.m.

Connecting your Qt application to Google services using OAuth 2.0

With the release of Qt 5.8, the QtNetworkAuth module has been added as a technology pending. It's focused on helping developers with their authentication frenzy. Currently OAuth1 and OAuth2 are supported. More authorization methods will be included in the future.

This post focuses on Qt's OAuth2 support. This shows how to use Google Authorization in the app. Your application will be able to show a typical login window like a web application (Note: Browser or WebView required).

The IETF defines OAuth 2.0 as:

OAuth 2.0 authorization framework allows third party applications to gain limited access to HTTP services, either by the resource owner to organize interaction between the resource owner and the HTTP service, or allow third party applications to gain their own access.

OAuth authorization is also a requirement for using the Google API and for the user to access information stored in Google services such as Gmail, Drive, Youtube, Maps, and others.


Registering your new project

Before you start writing code, you need to register a new project with the service provider. This step is required because you will be prompting for client credentials to identify your application. The following steps are based on the Google API Console, but are similar for other providers.

Create a new project

To start registering a project, access the Google API Console , then click “Create Project”.

The “New Project” dialog will appear. Type in the name of your project and click the "Create" button. You are now ready to manage your new project.

Your application has been registered, the control panel has been updated and you can set various options from this window.

Creation of credentials

You can get credentials to identify the application. Go to the "Credentials" section and click the "Create credentials" button. You must choose which credentials you need. Select "OAuth client ID".

In the next window, you can set up a "consent screen" with your email address, product name, home page, product logo,... Fill it in with your details and click the "Save" button.

Go back to the “Create client ID” screen and select “Application type”. Various options are available here, you need to select “Web application”. Enter its name.

Under "Restrictions" there is an important field: "Authorized redirect URIs".

If the user chooses to let your application process their data, then the application accepts an "access token" that will be used for authorization requests. "access token" can be accepted in several ways, but the usual way is for your web server to accept the request with "access token". In a web application, the server path is sufficient for processing. In a desktop application, you need to fake the path using a local browser.

Add the Access URI in your browser, including the port if you are using a port other than 80. When the application is launched, the main HTTP server will receive information from the browser.

In most cases, you will need to use a URI similar to: "http://localhost:8080/cb".

Note: The "/cb" path is required in the current QOAuthHttpServerReplyHandler implementation.

Note: You can set up different URIs. This example assumes a single URI.

We complete the process by clicking on the "Create" button and you will see the new identity in the list of permissions with "Edit", "Delete" and "Download" buttons on the right. Click the download button and... And finally, you will get a ready-made JSON file for parsing!

In the screenshot above, you can see some of the new URIs and client_id and client_secret. There is no need to use a JSON file, you can hardcode this information directly into the application.

Write wrapper code for Google API

Part of the class definition has been omitted here to show the relevant code.

Create a QOAuth2AuthorizationCodeFlow object in your code:

auto google = new QOAuth2AuthorizationCodeFlow;

Setting the scope permissions required for your application. This scope defines the permissions of the application. It can be a single string or a list of strings separated by a character defined by the service provider. (Google uses space as a delimiter).

NOTE: scopes vary by vendor. For a list of scopes supported by the Google API, click here .

Let's use the scope from which we will access the user's email:

google->setScope("email");

Connect the authorizeWithBrowser signal to the QDesktopServices::openUrl function to open an external browser and complete authorization.

connect(google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl);

Parse the downloaded JSON to get the settings and required information. document is an object of class QJsonDocument from the downloaded file.

const auto object = document.object();
const auto settingsObject = object["web"].toObject();
const QUrl authUri(settingsObject["auth_uri"].toString());
const auto clientId = settingsObject["client_id"].toString();
const QUrl tokenUri(settingsObject["token_uri"].toString());
const auto clientSecret(settingsObject["client_secret"].toString());
const auto redirectUris = settingsObject["redirect_uris"].toArray();
const QUrl redirectUri(redirectUris[0].toString()); // Get the first URI
const auto port = static_cast<quint16>(redirectUri.port()); // Get the port

After parsing the file, set up the google. object

google->setAuthorizationUrl(authUri);
google->setClientIdentifier(clientId);
google->setAccessTokenUrl(tokenUri);
google->setClientIdentifierSharedKey(clientSecret);

Create and assign a QOAuthHttpServerReplyHandler as the response handler of the QOAuth2AuthorizationCodeFlow object. A response handler is an object that processes responses from the server and receives tokens as a result of the authorization process.

auto replyHandler = new QOAuthHttpServerReplyHandler(port, this);
google->setReplyHandler(replyHandler);

The grant function will start the authorization process.

google->grant();

If everything is fine, then you should receive a QOAuth2AuthorizationCodeFlow::granted signal and start sending authorization requests.

You can try to send a request using https://www.googleapis.com/plus/v1/people/me

auto reply = google->get(QUrl("https://www.googleapis.com/plus/v1/people/me"));

This will give you QNetworkReply and when signal QNetworkReply::finished will be called so you can read the data.

Источник Qt Blog

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

KL
  • Jan. 27, 2017, 2:39 p.m.

При помощи данного класса можно получить доступ к google.com/webmaster?

Evgenii Legotckoi
  • Jan. 28, 2017, 6:33 a.m.

Да. Можно. У Google есть соответствующее API. Поищите в гугле по запросу Google Search Console OAuth API

TheGringerEye
  • April 20, 2017, 7:48 p.m.

Пытаюсь прикрутить к облаку яндекса и пока без успешно, кто-то пробовал с яндекс апи работать под этим классом?

Evgenii Legotckoi
  • April 21, 2017, 7:08 a.m.

Лично я не пробовал работать с Яндекс API, не возникало такой нужды.

TheGringerEye
  • April 24, 2017, 3:36 a.m.

Жаль, а то проблемы возникли, по гайду с гуглом у меня всё чётко, а при работе с яндексом почему-то не работает, а в дебаг пишет мол 404, хотя я лично своими руками в браузере через аякс запрос постом нормально получаю токен, а класс чёт не хочет.

Evgenii Legotckoi
  • April 24, 2017, 3:39 a.m.

Возможно, стоит Wireshark`ом запросы посмотреть. В чём отличие идёт аякс запроса от запроса из библиотеки. Возможно, что не хватает какой-нибудь заголовочной информации.

TheGringerEye
  • April 24, 2017, 5:08 a.m.

А с DropBox работали?

Evgenii Legotckoi
  • April 24, 2017, 9:38 a.m.

Нет

TheGringerEye
  • April 24, 2017, 9:50 a.m.

Пробовал играться с шарком, либо я криво смотрел, либо почему-то POST запросы на oauth.yandex.ru не летят, хотя должны постом лететь, я и исходники QOAuth2AuthorizationCodeFlow ковырял на предмет метода отправки, вроде бы везде POST, но в браузере GET открывается, ничего не понятно.

Evgenii Legotckoi
  • April 24, 2017, 10:44 a.m.

У меня пока мыслей на этот счёт нет ((

D
  • March 9, 2018, 2:56 a.m.

Спасибо за статью.
Я правильно понял, что в консольных программах использовать данный способ авторизации не получится? (QDesktopServices требует QtGui.) Или QtNetworkAuth можно и по-другому использовать?

Evgenii Legotckoi
  • March 9, 2018, 3:03 a.m.

Вы можете написать консольную программу и использовать библиотеки QtGui. Я, например, использовал QImage и другие классы из QtGui в одной консольной программе. В этом нет никакой проблемы. Создаёте консольное приложение и подключаете в pro файле gui модуль.

D
  • March 9, 2018, 3:10 a.m.

Ну в общем-то, да. Тащить только дополнительные зависимости в код придётся.

D
  • March 9, 2018, 3:14 a.m.

Меня, в общем-то, авторизация в гугле заинтересовала, поскольку я пытаюсь в свой редактор контактов добавить импорт адресных книг с сетевых ресурсов. (Нет, сам он не консольный, а вполне себе оконный, просто на той же кодовой базе у меня есть и  простой конвертор с интерфейсом командной строки.) Загрузка с ресурсов вроде ownCloud/Nextcloud у меня уже работает через CardDAV, но в случае с гуглом всё сложнее именно из-за авторизации...

Evgenii Legotckoi
  • March 9, 2018, 3:19 a.m.

Зависимости... здесь вопрос в том, что "Вам шашечки или ехать?".

Если Вы хотите реализовать рабочий прототип приложения, то я бы на вашем месте и не думал о том, что будет на пару библиотек больше в коде, тем более, что это библиотеки из самого Qt, а не третьесторонние непонятно откуда. А когда заработает, то можно посмотреть исходники Qt, может тот метод состоит всего-то из пары, тройки строчек, которые можно скопипастить и почистить. Тогда и библиотека не понадобится в дальнейшем.
D
  • March 17, 2018, 9:32 p.m.

Интересный результат получается. В Qt 5.8 получаю в браузере сформированное окно авторизации. А в новейшей Qt 5.10 - ошибку 400 с текстом "The redirect URI in the request, http://localhost:8080/, does not match the ones authorized for the OAuth client". Да, именно с таким URI, без /cb на конце, хотя он у меня всюду вбит. Исходные данные одинаковы. Что-то поломали...

Evgenii Legotckoi
  • March 18, 2018, 8:43 a.m.

Мне кажется, что в Qt 5.10 много чего поломали... Вот на форуме некоторые обсуждения идут и создаётся впечатление, что много чего испортили даже в том же QML.

D
  • March 22, 2018, 4:41 a.m.

Кажется, начало что-то получаться. :)
Как я понял, пример проверочного вызова в конце статьи не совсем правильный (заглянул в английский оригинал - там то же самое). Токен сам к запросу не добавляется, его надо добавить вручную. Например, приведённый запрос для гуглоплюса у меня сработал в следующей редакции:

    QNetworkReply* reply = google->get(QUrl(
         QString("https://www.googleapis.com/plus/v1/people/me?access_token=%1")
             .arg(google->token())));
Ну и Google+ API при этом, конечно же, надо разрешить в настройках аккаунта (автор этот момент не раскрыл).

a
  • March 24, 2022, 2:49 p.m.

Добрый вечер. Интересует возможность получения email адреса, указанного при авторизации данным методом. Результат выводик как на скриншоте, но хочется увидеть конкретный адрес. Буду благодарен за любую помощь

Comments

Only authorized users can post comments.
Please, Log in or Sign up
г
  • ги
  • April 24, 2024, 1:51 a.m.

C++ - Test 005. Structures and Classes

  • Result:41points,
  • Rating points-8
l
  • laei
  • April 23, 2024, 7:19 p.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:10points,
  • Rating points-10
l
  • laei
  • April 23, 2024, 7:17 p.m.

C++ - Тест 003. Условия и циклы

  • Result:50points,
  • Rating points-4
Last comments
k
kmssrFeb. 9, 2024, 5:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 9:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 7:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 8:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
G
GarApril 22, 2024, 3:46 p.m.
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil AcademicsApril 20, 2024, 5:45 p.m.
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasovApril 14, 2024, 4:41 p.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел ДорофеевApril 14, 2024, 12:35 p.m.
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrexApril 4, 2024, 2:47 p.m.
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Follow us in social networks