@@ -27,6 +27,7 @@ OAuth2Login::OAuth2Login(OAuth2Auth *auth, Site *site, NetworkManager *manager,
27
27
{
28
28
m_accessToken = m_settings->value (" auth/accessToken" ).toString ();
29
29
m_refreshToken = m_settings->value (" auth/refreshToken" ).toString ();
30
+ m_expires = m_settings->value (" auth/accessTokenExpiration" ).toDateTime ();
30
31
}
31
32
32
33
bool OAuth2Login::isTestable () const
@@ -200,8 +201,10 @@ void OAuth2Login::loginAuthorizationCode()
200
201
201
202
m_accessToken = flow->token ();
202
203
m_refreshToken = flow->refreshToken ();
204
+ m_expires = flow->expirationAt ();
203
205
m_settings->setValue (" auth/accessToken" , m_accessToken);
204
206
m_settings->setValue (" auth/refreshToken" , m_refreshToken);
207
+ m_settings->setValue (" auth/accessTokenExpiration" , m_expires);
205
208
206
209
emit loggedIn (Result::Success);
207
210
@@ -300,19 +303,30 @@ void OAuth2Login::basicRefresh()
300
303
301
304
void OAuth2Login::refresh (bool login)
302
305
{
303
- log (QStringLiteral (" [%1] Refreshing OAuth2 token..." ).arg (m_site->url ()), Logger::Info);
306
+ // Don't try to refresh while a refresh is already in progress
307
+ if (m_refreshing) {
308
+ if (login) {
309
+ m_refreshForLogin = true ;
310
+ }
311
+ return ;
312
+ }
304
313
305
- const QString consumerKey = m_settings->value (" auth/consumerKey" ).toString ();
306
- const QString consumerSecret = m_settings->value (" auth/consumerSecret" ).toString ();
314
+ log (QStringLiteral (" [%1] Refreshing OAuth2 token..." ).arg (m_site->url ()), Logger::Info);
307
315
316
+ // Without a refresh token, there's nothing to do
308
317
if (m_refreshToken.isEmpty ()) {
309
318
log (QStringLiteral (" [%1] Cannot refresh OAuth2 token without a refresh token" ).arg (m_site->url ()), Logger::Warning);
310
319
if (login) {
311
320
emit loggedIn (Result::Failure);
312
321
}
322
+ m_refreshing = false ;
313
323
return ;
314
324
}
315
325
326
+ // Set the refresh status and block other refresh requests until this one is completed
327
+ m_refreshing = true ;
328
+ m_refreshForLogin = login;
329
+
316
330
QNetworkRequest request (m_site->fixUrl (m_auth->tokenUrl ()));
317
331
m_site->setRequestHeaders (request);
318
332
@@ -326,6 +340,8 @@ void OAuth2Login::refresh(bool login)
326
340
data = jsonDoc.toJson ();
327
341
request.setHeader (QNetworkRequest::ContentTypeHeader, " application/json" );
328
342
} else {
343
+ const QString consumerKey = m_settings->value (" auth/consumerKey" ).toString ();
344
+ const QString consumerSecret = m_settings->value (" auth/consumerSecret" ).toString ();
329
345
const QList<QStrP> body {
330
346
{ " grant_type" , " refresh_token" },
331
347
{ " client_id" , consumerKey },
@@ -344,16 +360,16 @@ void OAuth2Login::refresh(bool login)
344
360
345
361
// Post request and wait for a reply
346
362
m_refreshReply = m_manager->post (request, data);
347
- if (login) {
348
- connect (m_refreshReply, &NetworkReply::finished, this , &OAuth2Login::refreshLoginFinished);
349
- } else {
350
- connect (m_refreshReply, &NetworkReply::finished, this , &OAuth2Login::refreshFinished);
351
- }
363
+ connect (m_refreshReply, &NetworkReply::finished, this , &OAuth2Login::refreshFinished);
352
364
}
353
365
354
- void OAuth2Login::refreshLoginFinished ()
366
+ void OAuth2Login::refreshFinished ()
355
367
{
356
368
const bool ok = readResponse (m_refreshReply);
369
+ m_refreshing = false ;
370
+ if (!m_refreshForLogin) {
371
+ return ;
372
+ }
357
373
if (!ok) {
358
374
if (m_auth->authType () == " refresh_token" ) {
359
375
log (QStringLiteral (" [%1] Refresh failed" ).arg (m_site->url ()), Logger::Warning);
@@ -366,15 +382,13 @@ void OAuth2Login::refreshLoginFinished()
366
382
m_settings->remove (" auth/accessToken" );
367
383
m_refreshToken.clear ();
368
384
m_settings->remove (" auth/refreshToken" );
385
+ m_expires = QDateTime ();
386
+ m_settings->remove (" auth/accessTokenExpiration" );
369
387
login ();
370
388
} else {
371
389
emit loggedIn (Result::Success);
372
390
}
373
391
}
374
- void OAuth2Login::refreshFinished ()
375
- {
376
- readResponse (m_refreshReply);
377
- }
378
392
379
393
bool OAuth2Login::readResponse (NetworkReply *reply)
380
394
{
@@ -441,6 +455,7 @@ bool OAuth2Login::readResponse(NetworkReply *reply)
441
455
const int expiresSecond = QDateTime::currentDateTime ().secsTo (m_expires);
442
456
QTimer::singleShot ((expiresSecond / 2 ) * 1000 , this , SIGNAL (basicRefresh ()));
443
457
log (QStringLiteral (" [%1] Token will expire at '%2'" ).arg (m_site->url (), m_expires.toString (" yyyy-MM-dd HH:mm:ss" )), Logger::Debug);
458
+ m_settings->setValue (" auth/accessTokenExpiration" , m_expires);
444
459
}
445
460
}
446
461
@@ -449,6 +464,11 @@ bool OAuth2Login::readResponse(NetworkReply *reply)
449
464
450
465
void OAuth2Login::complementRequest (QNetworkRequest *request) const
451
466
{
467
+ // Trigger a token refresh in the background if the token is expired
468
+ if (!m_refreshToken.isEmpty () && (!m_expires.isValid () || m_expires < QDateTime::currentDateTime ())) {
469
+ const_cast <OAuth2Login*>(this )->refresh (false );
470
+ }
471
+
452
472
if (!m_accessToken.isEmpty ()) {
453
473
request->setRawHeader (" Authorization" , " Bearer " + m_accessToken.toUtf8 ());
454
474
}
0 commit comments