User reference of the Authentication infrastructure can be read in the User Manual in the Authentication System Overview paragraph.
This chapter describes the best practices to use the Authentication system from a developer perspective.
Warning
Authentication system API is more than the classes and methods exposed here, but it’s strongly suggested to use the ones described here and exposed in the following snippets for two main reasons
Most of the following snippets are derived from the code of Geoserver Explorer plugin and its tests. This is the first plugin that used Authentication infrastructure. The plugin code and its tests can be found at this link. Other good code reference can be read from the authentication infrastructure tests code
Here are some definition of the most common objects treated in this chapter.
The QgsAuthManager singleton is the entry point to use the credentials stored in the QGIS encrypted Authentication DB:
<user home>/.qgis2/qgis-auth.db
This class takes care of the user interaction: by asking to set master password or by transparently using it to access crypted stored info.
The following snippet gives an example to set master password to open the access to the authentication settings. Code comments are important to understand the snippet.
authMgr = QgsAuthManager.instance()
# check if QgsAuthManager has been already initialized... a side effect
# of the QgsAuthManager.init() is that AuthDbPath is set.
# QgsAuthManager.init() is executed during QGis application init and hence
# you do not normally need to call it directly.
if authMgr.authenticationDbPath():
# already initilised => we are inside a QGIS app.
if authMgr.masterPasswordIsSet():
msg = 'Authentication master password not recognized'
assert authMgr.masterPasswordSame( "your master password" ), msg
else:
msg = 'Master password could not be set'
# The verify parameter check if the hash of the password was
# already saved in the authentication db
assert authMgr.setMasterPassword( "your master password",
verify=True), msg
else:
# outside qgis, e.g. in a testing environment => setup env var before
# db init
os.environ['QGIS_AUTH_DB_DIR_PATH'] = "/path/where/located/qgis-auth.db"
msg = 'Master password could not be set'
assert authMgr.setMasterPassword("your master password", True), msg
authMgr.init( "/path/where/located/qgis-auth.db" )
Any stored credential is a Authentication Configuration instance of the QgsAuthMethodConfig class accessed using a unique string like the following one:
authcfg = 'fm1s770'
that string is generated automatically when creating an entry using QGIS API or GUI.
QgsAuthMethodConfig is the base class for any Authentication Method. Any Authentication Method sets a configuration hash map where authentication informations will be stored. Hereafter an useful snippet to store PKI-path credentials for an hypothetic alice user:
authMgr = QgsAuthManager.instance()
# set alice PKI data
p_config = QgsAuthMethodConfig()
p_config.setName("alice")
p_config.setMethod("PKI-Paths")
p_config.setUri("http://example.com")
p_config.setConfig("certpath", "path/to/alice-cert.pem" ))
p_config.setConfig("keypath", "path/to/alice-key.pem" ))
# check if method parameters are correctly set
assert p_config.isValid()
# register alice data in authdb returning the ``authcfg`` of the stored
# configuration
authMgr.storeAuthenticationConfig(p_config)
newAuthCfgId = p_config.id()
assert (newAuthCfgId)
Authentication Methods are loaded dynamically during authentication manager init. The list of Authentication method can vary with QGIS evolution, but the original list of available methods is:
The above strings are that identify authentication methods in the QGIS authentication system. In Development section is described how to create a new c++ Authentication Method.
authMgr = QgsAuthManager.instance()
# add authorities
cacerts = QSslCertificate.fromPath( "/path/to/ca_chains.pem" )
assert cacerts is not None
# store CA
authMgr.storeCertAuthorities(cacerts)
# and rebuild CA caches
authMgr.rebuildCaCertsCache()
authMgr.rebuildTrustedCaCertsCache()
Warning
Due to QT4/OpenSSL interface limitation, updated cached CA are exposed to OpenSsl only almost a minute later. Hope this will be solved in QT5 authentication infrastructure.
A convenience class to pack PKI bundles composed on SslCert, SslKey and CA chain is the QgsPkiBundle class. Hereafter a snippet to get password protected:
# add alice cert in case of key with pwd
boundle = QgsPkiBundle.fromPemPaths( "/path/to/alice-cert.pem",
"/path/to/alice-key_w-pass.pem",
"unlock_pwd",
"list_of_CAs_to_bundle" )
assert boundle is not None
assert boundle.isValid()
Refer to QgsPkiBundle class documentation to extract cert/key/CAs from the bundle.
We can remove an entry from Authentication Database using it’s authcfg identifier with the following snippet:
authMgr = QgsAuthManager.instance()
authMgr.removeAuthenticationConfig( "authCfg_Id_to_remove" )
The best way to use an Authentication Config stored in the Authentication DB is referring it with the unique identifier authcfg. Expanding, means convert it from an identifier to a complete set of credentials. The best practice to use stored Authentication Configs, is to leave it managed automatically by the Authentication manager. The common use of a stored configuration is to connect to an authentication enabled service like a WMS or WFS or to a DB connection.
Note
Take into account that not all QGIS data providers are integrated with the Authentication infrastructure. Each authentication method, derived from the base class QgsAuthMethod and support a different set of Providers. For example Identity-Cert method supports the following list of providers:
In [19]: authM = QgsAuthManager.instance()
In [20]: authM.authMethod("Identity-Cert").supportedDataProviders()
Out[20]: [u'ows', u'wfs', u'wcs', u'wms', u'postgres']
For example, to access a WMS service using stored credentials identified with authcfg = 'fm1s770', we just have to use the authcfg in the data source URL like in the following snippet:
authCfg = 'fm1s770'
quri = QgsDataSourceURI()
quri.setParam("layers", 'usa:states')
quri.setParam("styles", '')
quri.setParam("format", 'image/png')
quri.setParam("crs", 'EPSG:4326')
quri.setParam("dpiMode", '7')
quri.setParam("featureCount", '10')
quri.setParam("authcfg", authCfg) # <---- here my authCfg url parameter
quri.setParam("contextualWMSLegend", '0')
quri.setParam("url", 'https://my_auth_enabled_server_ip/wms')
rlayer = QgsRasterLayer(quri.encodedUri(), 'states', 'wms')
In the upper case, the wms provider will take care to expand authcfg URI parameter with credential just before setting the HTTP connection.
Warning
Developer would have to leave authcfg expansion to the QgsAuthManager, in this way he will be sure that expansion is not done too early.
Usually an URI string, build using QgsDataSourceURI class, is used to set QGIS data source in the following way:
rlayer = QgsRasterLayer( quri.uri(False), 'states', 'wms')
Note
The False parameter is important to avoid URI complete expansion of the authcfg id present in the URI.
Other example can be read directly in the QGIS tests upstream as in test_authmanager_pki_ows or test_authmanager_pki_postgres.
Many third party plugins are using httplib2 to create HTTP connections instead of integrating with QgsNetworkAccessManager and its related Authentication Infrastructure integration. To facilitate this integration an helper python function has been created called NetworkAccessManager. Its code can be found here.
This helper class can be used as in the following snippet:
http = NetworkAccessManager(authid="my_authCfg", exception_class=My_FailedRequestError)
try:
response, content = http.request( "my_rest_url" )
except My_FailedRequestError, e:
# Handle exception
pass
In this paragraph are listed the available GUIs useful to integrate authentication infrastructure in custom interfaces.
If it’s necessary to select a Authentication Configuration from the set stored in the Authentication DB it is available in the GUI class QgsAuthConfigSelect
and can be used as in the following snippet:
# create the instance of the QgsAuthConfigSelect GUI hierarchically linked to
# the widget referred with `parent`
gui = QgsAuthConfigSelect( parent, "postgres" )
# add the above created gui in a new tab of the interface where the
# GUI has to be integrated
tabGui.insertTab( 1, gui, "Configurations" )
The above example is get from the QGIS source code The second parameter of the GUI constructor refers to data provider type. The parameter is used to restrict the compatible Authentication Methods with the specified provider.
The complete GUI used to manage credentials, authorities and to access to Authentication utilities is managed by the class QgsAuthEditorWidgets
and can be used as in the following snippet:
# create the instance of the QgsAuthEditorWidgets GUI hierarchically linked to
# the widget referred with `parent`
gui = QgsAuthConfigSelect( parent )
gui.show()
an integrated example can be found in the related test
A GUI used to manage only authorities is managed by the class QgsAuthAuthoritiesEditor
and can be used as in the following snippet:
# create the instance of the QgsAuthAuthoritiesEditor GUI hierarchically
# linked to the widget referred with `parent`
gui = QgsAuthAuthoritiesEditor( parent )
gui.show()