How to create a login page using Qt oauth?

梦想的初衷 提交于 2020-06-09 04:40:49

问题


I've been looking around on the web on how to create an authentication page when my Qt desktop app opens. I already built the app; that is pretty small and only composed of a MainWindow called from main.cpp.

Now I'd like to add an authentication page when the user opens the app. I created a Google API (following the instruction from this link: http://blog.qt.io/blog/2017/01/25/connecting-qt-application-google-services-using-oauth-2-0/); but it is really incomplete. And looking on the web, I wasn't able to find a single link that gives a working example where: - The user runs the app and gets asked for his username and password; - And if it doesn't exist yet, he can create one.

All I've found is incomplete piece of code like the link I shared above; or tutorial that shows how to create a login page with hard-coded passwords and usernames (this is not what I want, I want people to be able to add themselves dynamically based of the Google API).

So please, if someone has a little piece of code where the user gets asked for their username and password, with the code managing the request to the API, that would be great!


EDIT: Adding my code

I'm adding the code of my class GoogleGateway (inspired from what I found here: How to set redirect_uri using QOAuth2AuthorizationCodeFlow and QOAuthHttpServerReplyHandler)

GoogleGateway.h:

#ifndef GOOGLEGATEWAY_H
#define GOOGLEGATEWAY_H

#include <QObject>

class GoogleGateway : public QObject
{
    Q_OBJECT

public:
    GoogleGateway();
};

#endif // GOOGLEGATEWAY_H

GoogleGateway.cpp:

#include "googlegateway.h"
#include <QApplication>
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include <QFile>
#include <QUrl>
#include <QOAuth2AuthorizationCodeFlow>
#include <QOAuthHttpServerReplyHandler>
#include <QDesktopServices>

GoogleGateway::GoogleGateway() :
    QObject(){

auto google = new QOAuth2AuthorizationCodeFlow;
google->setScope("email");

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

QString val;
QFile file;
file.setFileName("/.../auth.json");
file.open(QIODevice::ReadOnly | QIODevice::Text);
val = file.readAll();
file.close();

QJsonDocument document = QJsonDocument::fromJson(val.toUtf8());
QJsonObject 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());
const auto port = static_cast<quint16>(redirectUri.port());

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

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

google->grant();

}

Now, what do I need to do in my MainWindow.cpp to prompt a login page that will use the class GoogleGateway? Does the class GoogleGateway look good as it is? Or do I need to modify something?

Also, I created an instance of the class GoogleGateway in my MainWindow constructor. And When I run the code, it opens a web tab in my Chrome but throws the Error 400 saying "Error: redirect_uri_mismatch". What does that mean?

Thanks for your help.


回答1:


So, the article from Qt blog is almost complete. You just need to connect granted signal and make needed requests after that.

Note about /cb path in redirect_uri in Qt blog is not valid anymore(article came about a year ago).

NOTE: The path “/cb” is mandatory in the current QOAuthHttpServerReplyHandler implementation.

So if you see access error from google after running your code, just copy-paste redirect_uri from there into GoogleConsole Authorized redirect URIs of your configured client. http://localhost:8080/ <- don't forget slash at the end

P.S.: Don't forget to dowload json file with credentials from console again.

Also if you want to call any Google APIs after authorization, you need to enable them in GoogleConsole for your project. To test the code just enable Google+ API

That's it. Here is the complete and working code. (Tested on Linux and Qt 5.10, Don't have Windows at the moment, can't test it there)

googlegateway.h

#ifndef GOOGLEGATEWAY_H
#define GOOGLEGATEWAY_H

#include <QObject>
#include <QOAuth2AuthorizationCodeFlow>
#include <QNetworkReply>

class GoogleGateway : public QObject
{
    Q_OBJECT
public:
    explicit GoogleGateway(QObject *parent = nullptr);

private:
    QOAuth2AuthorizationCodeFlow * google;
};

#endif // GOOGLEGATEWAY_H

googlegateway.cpp

#include "googlegateway.h"
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QString>
#include <QFile>
#include <QDir>
#include <QUrl>
#include <QOAuthHttpServerReplyHandler>
#include <QDesktopServices>


GoogleGateway::GoogleGateway(QObject *parent) : QObject(parent)
{
    this->google = new QOAuth2AuthorizationCodeFlow(this);
    this->google->setScope("email");

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

    QByteArray val;
    QFile file;
    file.setFileName(QDir::toNativeSeparators("/full/path/client_secret_XXXXXXX.apps.googleusercontent.com.json"));
    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        val = file.readAll();
        file.close();
    }


    QJsonDocument document = QJsonDocument::fromJson(val);
    QJsonObject 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());
    const auto port = static_cast<quint16>(redirectUri.port());

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

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

    connect(this->google, &QOAuth2AuthorizationCodeFlow::granted, [=](){
        qDebug() << __FUNCTION__ << __LINE__ << "Access Granted!";
        auto reply = this->google->get(QUrl("https://www.googleapis.com/plus/v1/people/me"));
        connect(reply, &QNetworkReply::finished, [reply](){
            qDebug() << "REQUEST FINISHED. Error? " << (reply->error() != QNetworkReply::NoError);
            qDebug() << reply->readAll();
        });
    });
}


来源:https://stackoverflow.com/questions/48453550/how-to-create-a-login-page-using-qt-oauth

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!