Skip to content

Commit

Permalink
[o2] Allow users to set a custom HTTP header to use when sending the
Browse files Browse the repository at this point in the history
retrieved token during requests

Some services do not use the default HTTP "Authorization" header
for specifying the token, and require a custom header instead
(e.g. AGOL services must use "X-Esri-Authorization" instead)
  • Loading branch information
nyalldawson committed Nov 26, 2020
1 parent 74edcbe commit 8a0973b
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 197 deletions.
12 changes: 12 additions & 0 deletions src/auth/oauth2/qgsauthoauth2config.cpp
Expand Up @@ -50,6 +50,7 @@ QgsAuthOAuth2Config::QgsAuthOAuth2Config( QObject *parent )
connect( this, &QgsAuthOAuth2Config::accessMethodChanged, this, &QgsAuthOAuth2Config::configChanged );
connect( this, &QgsAuthOAuth2Config::requestTimeoutChanged, this, &QgsAuthOAuth2Config::configChanged );
connect( this, &QgsAuthOAuth2Config::queryPairsChanged, this, &QgsAuthOAuth2Config::configChanged );
connect( this, &QgsAuthOAuth2Config::customHeaderChanged, this, &QgsAuthOAuth2Config::configChanged );

// always recheck validity on any change
// this, in turn, may emit validityChanged( bool )
Expand Down Expand Up @@ -211,6 +212,14 @@ void QgsAuthOAuth2Config::setAccessMethod( QgsAuthOAuth2Config::AccessMethod val
emit accessMethodChanged( mAccessMethod );
}

void QgsAuthOAuth2Config::setCustomHeader( const QString &header )
{
QString preval( mCustomHeader );
mCustomHeader = header;
if ( preval != header )
emit customHeaderChanged( mCustomHeader );
}

void QgsAuthOAuth2Config::setRequestTimeout( int value )
{
int preval( mRequestTimeout );
Expand Down Expand Up @@ -248,6 +257,7 @@ void QgsAuthOAuth2Config::setToDefaults()
setApiKey( QString() );
setPersistToken( false );
setAccessMethod( QgsAuthOAuth2Config::Header );
setCustomHeader( QString() );
setRequestTimeout( 30 ); // in seconds
setQueryPairs( QVariantMap() );
}
Expand All @@ -272,6 +282,7 @@ bool QgsAuthOAuth2Config::operator==( const QgsAuthOAuth2Config &other ) const
&& other.apiKey() == this->apiKey()
&& other.persistToken() == this->persistToken()
&& other.accessMethod() == this->accessMethod()
&& other.customHeader() == this->customHeader()
&& other.requestTimeout() == this->requestTimeout()
&& other.queryPairs() == this->queryPairs() );
}
Expand Down Expand Up @@ -406,6 +417,7 @@ QVariantMap QgsAuthOAuth2Config::mappedProperties() const
vmap.insert( QStringLiteral( "redirectUrl" ), this->redirectUrl() );
vmap.insert( QStringLiteral( "refreshTokenUrl" ), this->refreshTokenUrl() );
vmap.insert( QStringLiteral( "accessMethod" ), static_cast<int>( this->accessMethod() ) );
vmap.insert( QStringLiteral( "customHeader" ), this->customHeader() );
vmap.insert( QStringLiteral( "requestTimeout" ), this->requestTimeout() );
vmap.insert( QStringLiteral( "requestUrl" ), this->requestUrl() );
vmap.insert( QStringLiteral( "scope" ), this->scope() );
Expand Down
29 changes: 29 additions & 0 deletions src/auth/oauth2/qgsauthoauth2config.h
Expand Up @@ -55,6 +55,7 @@ class QgsAuthOAuth2Config : public QObject
Q_PROPERTY( AccessMethod accessMethod READ accessMethod WRITE setAccessMethod NOTIFY accessMethodChanged )
Q_PROPERTY( int requestTimeout READ requestTimeout WRITE setRequestTimeout NOTIFY requestTimeoutChanged )
Q_PROPERTY( QVariantMap queryPairs READ queryPairs WRITE setQueryPairs NOTIFY queryPairsChanged )
Q_PROPERTY( QString customHeader READ customHeader WRITE setCustomHeader NOTIFY customHeaderChanged )

public:

Expand Down Expand Up @@ -147,6 +148,15 @@ class QgsAuthOAuth2Config : public QObject
//! Access method
AccessMethod accessMethod() const { return mAccessMethod; }

/**
* Custom header for header access methods.
*
* If not set, the default HTTP Authorization header will be used.
*
* \since QGIS 3.18
*/
QString customHeader() const { return mCustomHeader; }

//! Request timeout
int requestTimeout() const { return mRequestTimeout; }

Expand Down Expand Up @@ -292,6 +302,16 @@ class QgsAuthOAuth2Config : public QObject
void setPersistToken( bool persist );
//! Set access method to \a value
void setAccessMethod( QgsAuthOAuth2Config::AccessMethod value );

/**
* Sets the custom \a header for header access methods.
*
* If \a header is empty, the default HTTP Authorization header will be used.
*
* \since QGIS 3.18
*/
void setCustomHeader( const QString &header );

//! Set request timeout to \a value
void setRequestTimeout( int value );
//! Set query pairs to \a pairs
Expand Down Expand Up @@ -344,6 +364,14 @@ class QgsAuthOAuth2Config : public QObject
void persistTokenChanged( bool );
//! Emitted when configuration access method has changed
void accessMethodChanged( QgsAuthOAuth2Config::AccessMethod );

/**
* Emitted when custom authorization header has changed.
*
* \since QGIS 3.18
*/
void customHeaderChanged( const QString & );

//! Emitted when configuration request timeout has changed
void requestTimeoutChanged( int );
//! Emitted when configuration query pair has changed
Expand Down Expand Up @@ -371,6 +399,7 @@ class QgsAuthOAuth2Config : public QObject
QString mApiKey;
bool mPersistToken = false;
AccessMethod mAccessMethod = AccessMethod::Header;
QString mCustomHeader;
int mRequestTimeout = 30 ; // in seconds
QVariantMap mQueryPairs;
bool mValid = false;
Expand Down
15 changes: 15 additions & 0 deletions src/auth/oauth2/qgsauthoauth2edit.cpp
Expand Up @@ -186,6 +186,8 @@ void QgsAuthOAuth2Edit::setupConnections()
connect( spnbxRequestTimeout, static_cast<void ( QSpinBox::* )( int )>( &QSpinBox::valueChanged ),
mOAuthConfigCustom.get(), &QgsAuthOAuth2Config::setRequestTimeout );

connect( mTokenHeaderLineEdit, &QLineEdit::textChanged, mOAuthConfigCustom.get(), &QgsAuthOAuth2Config::setCustomHeader );

connect( mOAuthConfigCustom.get(), &QgsAuthOAuth2Config::validityChanged, this, &QgsAuthOAuth2Edit::configValidityChanged );

if ( mParentName )
Expand Down Expand Up @@ -397,6 +399,7 @@ void QgsAuthOAuth2Edit::loadFromOAuthConfig( const QgsAuthOAuth2Config *config )
lePassword->setText( config->password() );
leScope->setText( config->scope() );
leApiKey->setText( config->apiKey() );
mTokenHeaderLineEdit->setText( config->customHeader() );

// advanced
chkbxTokenPersist->setChecked( config->persistToken() );
Expand Down Expand Up @@ -868,6 +871,18 @@ void QgsAuthOAuth2Edit::populateAccessMethods()
void QgsAuthOAuth2Edit::updateConfigAccessMethod( int indx )
{
mOAuthConfigCustom->setAccessMethod( static_cast<QgsAuthOAuth2Config::AccessMethod>( indx ) );
switch ( static_cast<QgsAuthOAuth2Config::AccessMethod>( indx ) )
{
case QgsAuthOAuth2Config::Header:
mTokenHeaderLineEdit->setVisible( true );
mTokenHeaderLabel->setVisible( true );
break;
case QgsAuthOAuth2Config::Form:
case QgsAuthOAuth2Config::Query:
mTokenHeaderLineEdit->setVisible( false );
mTokenHeaderLabel->setVisible( false );
break;
}
}

void QgsAuthOAuth2Edit::addQueryPairRow( const QString &key, const QString &val )
Expand Down

0 comments on commit 8a0973b

Please sign in to comment.