Skip to content
Permalink
Browse files

OAuth2: avoid constant token refreshing if the expiration delay is < …

…2 minutes

Currently we refresh the token 2 minutes befores its theoretical expiration.
But if using default Keycloack configuration, the refresh delay is 60 seconds.
Which means we refresh the token for every network request. So for such short
delays, only refresh when the remaining validity time is below 10% of the
initial expiration delay.

(cherry picked from commit a8af06f)
  • Loading branch information
rouault authored and nyalldawson committed Nov 20, 2020
1 parent 33d079e commit d7c1ccbea204de0ada3f9c6cb66f67aabc423b66
Showing with 27 additions and 1 deletion.
  1. +10 −1 src/auth/oauth2/qgsauthoauth2method.cpp
  2. +6 −0 src/auth/oauth2/qgso2.cpp
  3. +11 −0 src/auth/oauth2/qgso2.h
@@ -28,6 +28,8 @@
#include "qgsmessagelog.h"
#include "qgssettings.h"

#include <algorithm>

#include <QDateTime>
#include <QInputDialog>
#include <QDesktopServices>
@@ -139,7 +141,10 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const
if ( o2->expires() > 0 ) // QStringLiteral("").toInt() result for tokens with no expiration
{
int cursecs = static_cast<int>( QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000 );
expired = ( ( o2->expires() - cursecs ) < 120 ); // try refresh with expired or two minutes to go
const int lExpirationDelay = o2->expirationDelay();
// try refresh with expired or two minutes to go (or a fraction of the initial expiration delay if it is short)
const int refreshThreshold = lExpirationDelay > 0 ? std::min( 120, std::max( 2, lExpirationDelay / 10 ) ) : 120;
expired = ( ( o2->expires() - cursecs ) < refreshThreshold );
}

if ( expired )
@@ -160,6 +165,8 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const
o2->refreshSynchronous();

// refresh result should set o2 to (un)linked
if ( o2->linked() )
o2->computeExpirationDelay();
}
}
}
@@ -226,6 +233,8 @@ bool QgsAuthOAuth2Method::updateNetworkRequest( QNetworkRequest &request, const
QgsMessageLog::logMessage( msg, AUTH_METHOD_KEY, Qgis::MessageLevel::Warning );
return false;
}

o2->computeExpirationDelay();
}

if ( o2->token().isEmpty() )
@@ -431,3 +431,9 @@ void QgsO2::refreshSynchronous()
emit refreshFinished( blockingRequest.reply().error() );
}
}

void QgsO2::computeExpirationDelay()
{
const int lExpires = expires();
mExpirationDelay = lExpires > 0 ? lExpires - static_cast<int>( QDateTime::currentMSecsSinceEpoch() / 1000 ) : 0;
}
@@ -61,6 +61,16 @@ class QgsO2: public O2
//! Refresh token in a synchronous way
void refreshSynchronous();

/**
* Compute expiration delay from current timestamp and expires()
* Should only be called just after a refresh / link event. */
void computeExpirationDelay();

/** Returns expiration delay.
* May be 0 if it is unknown
*/
int expirationDelay() const { return mExpirationDelay; }

public slots:

//! Clear all properties
@@ -104,6 +114,7 @@ class QgsO2: public O2
QString state_;
QgsAuthOAuth2Config *mOAuth2Config;
bool mIsLocalHost = false;
int mExpirationDelay = 0;

static QString O2_OAUTH2_STATE;
};

0 comments on commit d7c1ccb

Please sign in to comment.
You can’t perform that action at this time.