Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[oauth2] Fix token refresh timeout cancellation with singleshot timer
Also, avoid O2 library error by checking for refresh token and URL
  • Loading branch information
dakcarto committed Jun 6, 2019
1 parent ba8458d commit 14b27d5
Showing 1 changed file with 45 additions and 17 deletions.
62 changes: 45 additions & 17 deletions src/auth/oauth2/qgsauthoauth2method.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgso2.h"
#include "qgsauthoauth2config.h"
#include "qgsauthoauth2edit.h"
#include "qgsguiutils.h"
#include "qgsnetworkaccessmanager.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"
Expand Down Expand Up @@ -142,23 +143,50 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const

if ( expired )
{
msg = QStringLiteral( "Token expired, attempting refresh for authcfg %1" ).arg( authcfg );
QgsMessageLog::logMessage( msg, AUTH_METHOD_KEY, Qgis::MessageLevel::Info );

// Try to get a refresh token first
// go into local event loop and wait for a fired refresh-related slot
QEventLoop rloop( nullptr );
connect( o2, &QgsO2::refreshFinished, &rloop, &QEventLoop::quit );

// Asynchronously attempt the refresh
// TODO: This already has a timed reply setup in O2 base class (and in QgsNetworkAccessManager!)
// May need to address this or app crashes will occur!
o2->refresh();

// block request update until asynchronous linking loop is quit
rloop.exec( QEventLoop::ExcludeUserInputEvents );

// refresh result should set o2 to (un)linked
if ( o2->refreshToken().isEmpty() || o2->refreshTokenUrl().isEmpty() )
{
msg = QStringLiteral( "Token expired, but no refresh token or URL defined for authcfg %1" ).arg( authcfg );
QgsMessageLog::logMessage( msg, AUTH_METHOD_KEY, Qgis::MessageLevel::Info );
// clear any previous token session properties
o2->unlink();
}
else
{
msg = QStringLiteral( "Token expired, attempting refresh for authcfg %1" ).arg( authcfg );
QgsMessageLog::logMessage( msg, AUTH_METHOD_KEY, Qgis::MessageLevel::Info );

// Try to get a refresh token first
// go into local event loop and wait for a fired refresh-related slot
QEventLoop rloop( nullptr );
connect( o2, &QgsO2::refreshFinished, &rloop, &QEventLoop::quit );

// add singlshot timer to quit refresh after an alloted timeout
// this should keep the local event loop from blocking forever
QTimer r_timer( nullptr );
int r_reqtimeout = o2->oauth2config()->requestTimeout() * 1000;
r_timer.setInterval( r_reqtimeout );
r_timer.setSingleShot( true );
connect( &r_timer, &QTimer::timeout, &rloop, &QEventLoop::quit );
r_timer.start();

QgsTemporaryCursorOverride waitCursor( Qt::WaitCursor );

// Asynchronously attempt the refresh
// TODO: This already has a timed reply setup in O2 base class (and in QgsNetworkAccessManager!)
// May need to address this or app crashes will occur!
o2->refresh();

// block request update until asynchronous linking loop is quit
rloop.exec();
if ( r_timer.isActive() )
{
r_timer.stop();
}

waitCursor.release();

// refresh result should set o2 to (un)linked
}
}
}

Expand Down

0 comments on commit 14b27d5

Please sign in to comment.