Do not let user change it's login while using shibbolet

Fixes #915
This commit is contained in:
Olivier Goffart 2014-03-27 17:58:31 +01:00
parent 67f4d0c85b
commit d6525a979d
5 changed files with 154 additions and 7 deletions

View file

@ -125,7 +125,8 @@ if(TOKEN_AUTH_ONLY)
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
creds/shibboleth/shibbolethconfigfile.cpp
creds/shibboleth/authenticationdialog.cpp
creds/shibboleth/authenticationdialog.cpp
creds/shibboleth/shibbolethuserjob.cpp
)
endif()

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "shibbolethuserjob.h"
#include <account.h>
#include <json.h>
namespace Mirall {
ShibbolethUserJob::ShibbolethUserJob(Account* account, QObject* parent)
: AbstractNetworkJob(account, QLatin1String("ocs/v1.php/cloud/user"), parent)
{
setIgnoreCredentialFailure(true);
}
void ShibbolethUserJob::start()
{
QNetworkRequest req;
req.setRawHeader("OCS-APIREQUEST", "true");
QUrl url = Account::concatUrlPath(account()->url(), path());
url.setQuery("format=json");
setReply(davRequest("GET", url, req));
setupConnections(reply());
AbstractNetworkJob::start();
}
void ShibbolethUserJob::finished()
{
bool success = false;
QVariantMap json = QtJson::parse(QString::fromUtf8(reply()->readAll()), success).toMap();
// empty or invalid response
if (!success || json.isEmpty()) {
qDebug() << "cloud/user: invalid JSON!";
emit userFetched(QString());
return;
}
QString user = json.value("ocs").toMap().value("data").toMap().value("id").toString();
qDebug() << "cloud/user: " << json << "->" << user;
emit userFetched(user);
}
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#pragma once
#include <networkjobs.h>
namespace Mirall
{
/**
* @brief Fetch the user name of the shibboleth connection
*/
class ShibbolethUserJob : public AbstractNetworkJob {
Q_OBJECT
public:
explicit ShibbolethUserJob(Account *account, QObject* parent = 0);
void start();
signals:
// is always emitted when the job is finished. user is empty in case of error.
void userFetched(const QString &user);
// Another job need to be created
void tryAgain();
private slots:
virtual void finished();
};
} // ns Mirall

View file

@ -15,12 +15,15 @@
#include <QMutex>
#include <QSettings>
#include <QNetworkReply>
#include <QMessageBox>
#include <qdebug.h>
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethaccessmanager.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibboleth/shibbolethconfigfile.h"
#include "shibboleth/shibbolethuserjob.h"
#include "creds/credentialscommon.h"
#include "mirall/account.h"
@ -36,6 +39,8 @@ namespace Mirall
namespace
{
const char userC[] = "user";
int shibboleth_redirect_callback(CSYNC* csync_ctx,
const char* uri)
{
@ -157,10 +162,7 @@ QString ShibbolethCredentials::authType() const
QString ShibbolethCredentials::user() const
{
// ### TODO: If we had a way to extract the currently authenticated user
// somehow, we could return its id token (email) here (stored in REMOTE_USER)
// The server doesn't return it by default
return QString();
return _user;
}
QNetworkCookie ShibbolethCredentials::cookie() const
@ -197,6 +199,9 @@ bool ShibbolethCredentials::ready() const
void ShibbolethCredentials::fetch(Account *account)
{
if (_user.isEmpty()) {
_user = account->credentialSetting(QLatin1String(userC)).toString();
}
if (_ready) {
Q_EMIT fetched();
} else {
@ -226,6 +231,8 @@ void ShibbolethCredentials::persist(Account* account)
cfg.storeCookies(_otherCookies);
storeShibCookie(_shibCookie, account);
if (!_user.isEmpty())
account->setCredentialSetting(QLatin1String(userC), _user);
}
// only used by Application::slotLogout(). Use invalidateAndFetch for normal usage
@ -254,14 +261,49 @@ void ShibbolethCredentials::disposeBrowser()
void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& cookie, Account* account)
{
disposeBrowser();
_ready = true;
_stillValid = true;
_shibCookie = cookie;
storeShibCookie(_shibCookie, account);
Q_EMIT newCookie(_shibCookie);
// Now fetch the user...
// But we must first do a request to webdav so the session is enabled.
// (because for some reason we wan't access the API without that.. a bug in the server maybe?)
EntityExistsJob* job = new EntityExistsJob(account, account->davPath(), this);
connect(job, SIGNAL(exists(QNetworkReply*)), this, SLOT(slotFetchUser()));
job->setIgnoreCredentialFailure(true);
job->start();
}
void ShibbolethCredentials::slotFetchUser()
{
AbstractNetworkJob* oldjob = qobject_cast<AbstractNetworkJob*>(sender());
Q_ASSERT(oldjob);
ShibbolethUserJob *job = new ShibbolethUserJob(oldjob->account(), this);
connect(job, SIGNAL(userFetched(QString)), this, SLOT(slotUserFetched(QString)));
job->start();
}
void ShibbolethCredentials::slotUserFetched(const QString &user)
{
ShibbolethUserJob *job = qobject_cast<ShibbolethUserJob *>(sender());
Q_ASSERT(job);
if (_user.isEmpty()) {
_user = user;
} else if (user != _user) {
qDebug() << "Wrong user: " << user << "!=" << _user;
QMessageBox::warning(_browser, tr("Login Error"), tr("You must log with user %1").arg(_user));
invalidateToken(job->account());
showLoginWindow(job->account());
return;
}
_stillValid = true;
_ready = true;
Q_EMIT fetched();
}
void ShibbolethCredentials::slotBrowserHidden()
{
disposeBrowser();
@ -356,4 +398,5 @@ void ShibbolethCredentials::storeShibCookie(const QNetworkCookie &cookie, Accoun
job->start();
}
} // ns Mirall

View file

@ -64,6 +64,8 @@ private Q_SLOTS:
void slotReadJobDone(QKeychain::Job*);
void slotInvalidateAndFetchInvalidateDone(QKeychain::Job*);
void slotReplyFinished(QNetworkReply*);
void slotUserFetched(const QString& user);
void slotFetchUser();
Q_SIGNALS:
void newCookie(const QNetworkCookie& cookie);
@ -80,6 +82,7 @@ private:
bool _stillValid;
ShibbolethWebView* _browser;
QMap<QUrl, QList<QNetworkCookie> > _otherCookies;
QString _user;
};
} // ns Mirall