Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from qgis.core import (
  QgsApplication,
  QgsRasterLayer,
  QgsAuthMethodConfig,
  QgsDataSourceUri,
  QgsPkiBundle,
  QgsMessageLog,
)

from qgis.gui import (
    QgsAuthAuthoritiesEditor,
    QgsAuthConfigEditor,
    QgsAuthConfigSelect,
    QgsAuthSettingsWidget,
)

from qgis.PyQt.QtWidgets import (
    QWidget,
    QTabWidget,
)

from qgis.PyQt.QtNetwork import QSslCertificate

14. Infrastructure d’authentification

14.1. Introduction

Les infrastructures d’authentification de la référence utilisatieur peuvent être lu dans le manuel d’utilisateur le paragraphe « Aperçu du Système d’authentification .

Ce chapitre décrit les les bonnes pratiques de développement pour l’utilisation du système d’authentification.

Dans QGIS Desktop, le système d’authentification est régulièrement utilisé par les fournisseurs de données lorsqu’une accréditation est nécessaire pour l’acquisition de certaines ressources, par exemple, lorsqu’une couche nécessite une connexion à une base Postgres.

Il existe aussi quelques widgets de la bibliothèque graphique de QGIS que les développeur de plugin peuvent utiliser pour intégrer facilement le système d’authentification dans leur code :

Le code source tests code est un bon exemple d’infrastructure authentification.

Avertissement

Due to the security constraints that were taken into account during the authentication infrastructure design, only a selected subset of the internal methods are exposed to Python.

14.2. Glossaire

Voici quelques définitions des principaux éléments étudiés dans ce chapitre.

Mot de passe principal

Mot de passe permettant l’accès et le décryptage des informations stockées dans la base de données d’authentification de QGIS.

Base de données d’authentification

Une base de donnée sqlite qgis-auth.db cryptée des Mot de passe principal où les Configuration d’authentification sont stockées. Par exemple vos noms d’utilisateurs et mots de passe, vos certificats et clés personnelles et plus généralement toutes vos méthodes d’authentification

Base de données d’authentification

Base de données d’authentification

Configuration de l’authentification

Un ensemble de données d’authentification dépendant de la Méthode d’Authentification. Par exemple, une méthode basique d’authentification enregistre le couple Nom d’utilisateur / Mot de passe.

Authentication Config

Configuration de l’authentification

Méthode d’authentification

Une méthode pour s’authentifier. Chaque méthode a son propre protocole utilisé pour accorder le statut “authentifié”. Chaque méthode est mise à disposition comme une librairie chargée dynamiquement pendant la phase d’initialisation de l’infrastructure d’authentification de QGIS.

14.3. QgsAuthManager le point d’entrée

The QgsAuthManager singleton is the entry point to use the credentials stored in the QGIS encrypted Authentication DB, i.e. the qgis-auth.db file under the active user profile folder.

This class takes care of the user interaction: by asking to set a master password or by transparently using it to access encrypted stored information.

14.3.1. Init the manager and set the master password

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
authMgr = QgsApplication.authManager()

# check if QgsAuthManager has already been 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.authenticationDatabasePath():
    # 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")

14.3.2. Populate authdb with a new Authentication Configuration entry

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 the QGIS API or GUI, but it might be useful to manually set it to a known value in case the configuration must be shared (with different credentials) between multiple users within an organization.

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
authMgr = QgsApplication.authManager()
# set alice PKI data
config = QgsAuthMethodConfig()
config.setName("alice")
config.setMethod("PKI-Paths")
config.setUri("https://example.com")
config.setConfig("certpath", "path/to/alice-cert.pem" )
config.setConfig("keypath", "path/to/alice-key.pem" )
# check if method parameters are correctly set
assert config.isValid()

# register alice data in authdb returning the ``authcfg`` of the stored
# configuration
authMgr.storeAuthenticationConfig(config)
newAuthCfgId = config.id()
assert newAuthCfgId

14.3.2.1. Available Authentication methods

Authentication Method libraries are loaded dynamically during authentication manager init. Available authentication methods are:

  1. Basic User and password authentication

  2. Esri-Token ESRI token based authentication

  3. Identity-Cert Identity certificate authentication

  4. OAuth2 OAuth2 authentication

  5. PKI-Paths PKI paths authentication

  6. PKI-PKCS#12 PKI PKCS#12 authentication

14.3.2.2. Populate Authorities

1
2
3
4
5
6
7
8
9
authMgr = QgsApplication.authManager()
# 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()

14.3.2.3. Manage PKI bundles with QgsPkiBundle

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:

1
2
3
4
5
6
7
8
9
# add alice cert in case of key with pwd
caBundlesList = []  # List of CA bundles
bundle = QgsPkiBundle.fromPemPaths( "/path/to/alice-cert.pem",
                                     "/path/to/alice-key_w-pass.pem",
                                     "unlock_pwd",
                                     caBundlesList )
assert bundle is not None
# You can check bundle validity by calling:
# bundle.isValid()

Refer to QgsPkiBundle class documentation to extract cert/key/CAs from the bundle.

14.3.3. Remove an entry from authdb

We can remove an entry from Authentication Database using it’s authcfg identifier with the following snippet:

authMgr = QgsApplication.authManager()
authMgr.removeAuthenticationConfig( "authCfg_Id_to_remove" )

14.3.4. Leave authcfg expansion to QgsAuthManager

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 the certIdentity () method supports the following list of providers:

authM = QgsApplication.authManager()
print(authM.authMethod("Identity-Cert").supportedDataProviders())

Sample output:

['ows', 'wfs', 'wcs', 'wms', '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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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(str(quri.encodedUri(), "utf-8"), '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.

Avertissement

The 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, built using the QgsDataSourceURI class, is used to set a data source in the following way:

authCfg = 'fm1s770'
quri = QgsDataSourceUri("my WMS uri here")
quri.setParam("authcfg", authCfg)
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.

14.4. Adapt plugins to use Authentication infrastructure

Many third party plugins are using httplib2 or other Python networking libraries to manage HTTP connections instead of integrating with QgsNetworkAccessManager and its related Authentication Infrastructure integration.

To facilitate this integration a 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:

1
2
3
4
5
6
http = NetworkAccessManager(authid="my_authCfg", exception_class=My_FailedRequestError)
try:
  response, content = http.request( "my_rest_url" )
except My_FailedRequestError, e:
  # Handle exception
  pass

14.5. Authentication GUIs

Ce paragraphe liste les fenêtres utiles à l’intégration d’une infrastructure d’authentification dans des interfaces personnalisées.

14.5.1. Fenêtre de sélection des identifiants

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.

../../_images/QgsAuthConfigSelect.png

and can be used as in the following snippet:

1
2
3
4
5
6
7
8
# create the instance of the QgsAuthConfigSelect GUI hierarchically linked to
# the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthConfigSelect( parent, "postgres" )
# add the above created gui in a new tab of the interface where the
# GUI has to be integrated
tabGui = QTabWidget()
tabGui.insertTab( 1, gui, "Configurations" )

The above example is taken 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.

14.5.2. Authentication Editor GUI

The complete GUI used to manage credentials, authorities and to access to Authentication utilities is managed by the QgsAuthEditorWidgets class.

../../_images/QgsAuthEditorWidgets.png

and can be used as in the following snippet:

1
2
3
4
5
# create the instance of the QgsAuthEditorWidgets GUI hierarchically linked to
# the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthConfigSelect( parent )
gui.show()

An integrated example can be found in the related test.

14.5.3. Authorities Editor GUI

A GUI used to manage only authorities is managed by the QgsAuthAuthoritiesEditor class.

../../_images/QgsAuthAuthoritiesEditor.png

and can be used as in the following snippet:

1
2
3
4
5
# create the instance of the QgsAuthAuthoritiesEditor GUI hierarchically
#  linked to the widget referred with `parent`
parent = QWidget()  # Your GUI parent widget
gui = QgsAuthAuthoritiesEditor( parent )
gui.show()