Sur cette page

Présentation d’OAuth 2.0

La norme RFC 6749 – Cadre d'autorisation OAuth 2.0 – définit un protocole d'autorisation des services via une application tierce. OAuth 2.0 utilise des jetons pour dissocier le processus d'autorisation du service et des utilisateurs. Cette méthode est plus sûre, car le propriétaire du service n'a pas besoin de gérer les identifiants des utilisateurs. Elle remplace la norme RFC 5849 OAuth 1.0.

Le cadre OAuth 2.0 définit deux types de clients, publics ou confidentiels, ainsi que des flux d'autorisation tels que le flux de code d'autorisation, l'octroi implicite de code et plusieurs autres. Une application Qt classique est considérée comme une application native publique. Une application cliente publique est une application à laquelle on ne peut pas faire confiance pour conserver des informations sensibles, telles que des mots de passe, qui seraient intégrées dans le binaire livré.

La norme RFC 8252 « OAuth 2.0 pour les applications natives » définit plus en détail les bonnes pratiques pour les applications natives. Plus précisément, la RFC 8252 recommande le flux d’autorisation via le navigateur. Par conséquent, les classes ` QtNetworkAuth ` fournissent une implémentation concrète de ce flux.

Nouveauté de Qt 6.9, QtNetworkAuth prend en charge la norme RFC 8628 – OAuth 2.0 Device Authorization Grant. Ce flux est destiné aux appareils dont les capacités de saisie sont limitées ou peu pratiques. Dans ce flux, les autorisations s’effectuent via un appareil secondaire, tel qu’un smartphone, plutôt que directement sur l’appareil concerné. Il s’agit par exemple de téléviseurs, de consoles multimédias, d’interfaces homme-machine (IHM) et d’appareils IoT. L’utilisateur peut alors utiliser une application sur son smartphone pour autoriser l’appareil.

Le tableau suivant présente les deux flux OAuth 2.0 pris en charge par Qt Network Authorization:

AspectFlux de code d’autorisationFlux d'autorisation de l'appareil
Connexion réseauOuiOui
Interaction de l'utilisateurNavigateur / agent utilisateur sur le même appareilNavigateur / agent utilisateur sur un autre appareil
Gestion des redirections requiseOuiNon
Fonctionnalités de saisie sur l'appareilCapacités de saisie avancéesCapacités de saisie limitées ou inexistantes
CiblesApplications de bureau et mobilesTéléviseurs, consoles, interfaces homme-machine (IHM), appareils IoT

OAuth 2.0 nécessite l'utilisation d'un agent utilisateur, qui est généralement un navigateur. Pour plus d'informations, consultez la section « Prise en charge de OAuth 2.0 par les navigateurs » de Qt.

Classes OAuth 2.0

Qt Network Authorization fournit à la fois des classes OAuth 2.0 concrètes et abstraites. Les classes abstraites sont destinées à la mise en œuvre de flux personnalisés, tandis que les classes concrètes fournissent une implémentation concrète.

Pour consulter la liste des classes C++, reportez-vous à la page « QtNetworkAuth ».

Qt Network Authorization comporte deux classes abstraites permettant de mettre en œuvre les flux OAuth 2.0 :

Flux du code d’autorisation

Cette section présente une vue d’ensemble du flux de code d’autorisation tel que défini dans les RFC 6749 – Code d’autorisation et RFC 8252 – Demande d’autorisation depuis une application native pour les applications natives.

Prenons l'exemple de configuration suivant :

QOAuth2AuthorizationCodeFlow m_oauth;
QOAuthUriSchemeReplyHandler m_handler;

m_oauth.setAuthorizationUrl(QUrl(authorizationUrl));
m_oauth.setTokenUrl(QUrl(accessTokenUrl));
m_oauth.setClientIdentifier(clientIdentifier);
m_oauth.setRequestedScopeTokens({scope});

connect(&m_oauth, &QAbstractOAuth::authorizeWithBrowser, this, &QDesktopServices::openUrl);
connect(&m_oauth, &QAbstractOAuth::granted, this, [this]() {
    // Here we use QNetworkRequestFactory to store the access token
    m_api.setBearerToken(m_oauth.token().toLatin1());
    m_handler.close();
});

m_handler.setRedirectUrl(QUrl{"com.example.myqtapp://oauth2redirect"_L1});
m_oauth.setReplyHandler(&m_handler);

// Initiate the authorization
if (m_handler.listen()) {
    m_oauth.grant();
}

Étapes du flux d'autorisation

Le flux de code d'autorisation RFC 6749 comporte deux étapes principales : l'autorisation de la ressource (y compris toute authentification utilisateur nécessaire), suivie d'une demande de jeton d'accès. Ces étapes peuvent être suivies, de manière facultative, de l'utilisation du jeton d'accès et de son renouvellement. La figure suivante illustre ces étapes :

Processus d'autorisation simplifié dans une application Qt utilisant un serveur d'autorisation et un navigateur

  • Au cours de l’étape d’autorisation, l’utilisateur est authentifié et autorise l’accès aux ressources. Cela nécessite une interaction de l’utilisateur via son navigateur.
  • Une fois l'autorisation obtenue, le code d'autorisation reçu est utilisé pour demander un jeton d'accès et, éventuellement, un jeton de rafraîchissement.
  • Une fois le jeton d’accès obtenu, l’application l’utilise pour accéder aux ressources qui l’intéressent. Le jeton d’accès est inclus dans les requêtes de ressources, et il appartient au serveur de ressources de vérifier la validité du jeton. Il existe plusieurs façons d’inclure le jeton dans les requêtes utilisant des jetons « bearer ». L’inclusion du jeton dans l ’en-tête HTTP ` Authorization ` est sans doute la plus courante.
  • Actualisation du jeton d’accès. Les jetons d’accès expirent généralement assez rapidement, par exemple au bout d’une heure. Si l’application a reçu un jeton de rafraîchissement en plus du jeton d’accès, ce jeton de rafraîchissement peut être utilisé pour demander un nouveau jeton d’accès. Les applications peuvent conserver les jetons de rafraîchissement à durée de vie plus longue afin d’éviter de devoir passer par une nouvelle étape d’autorisation (et donc une nouvelle interaction avec le navigateur).

Détails et personnalisation

Les flux OAuth 2.0 sont dynamiques et la mise en œuvre des spécifications peut s’avérer délicate au premier abord. La figure ci-dessous illustre les principaux détails d’un flux de code d’autorisation réussi.

Détails du flux OAuth 2.0 illustrant les appels d'événements spécifiques

Par souci de clarté, la figure omet certains signaux, mais illustre dans l'ensemble les détails et les principaux points de personnalisation. Les points de personnalisation correspondent aux différents signaux et slots que l'application peut utiliser, ainsi qu'aux callbacks configurables à l'aide des méthodes QAbstractOAuth::setModifyParametersFunction() et QAbstractOAuth2::setNetworkRequestModifier().

Choix d’un gestionnaire de réponse

Le choix du gestionnaire à utiliser dépend de l'élément `redirect_uri`. L'adresse redirect_uri correspond à l'URL vers laquelle le navigateur est redirigé à l'issue de la phase d'autorisation.

Pour recevoir la réponse d'autorisation dans les applications natives, la norme RFC 8252 spécifie trois grands types de schémas d'URI de réponse: usage privé, boucle de retour et https.

  • URI à usage privé: peuvent être utilisés si le système d'exploitation autorise une application à enregistrer un schéma d'URI personnalisé. Toute tentative d'ouverture d'une URL utilisant un tel schéma personnalisé ouvrira l'application native correspondante. Voir QOAuthUriSchemeReplyHandler.
  • URI HTTPS: peuvent être utilisées si le système d’exploitation autorise l’application à enregistrer une URL HTTPS personnalisée. Toute tentative d’ouverture de cette URL lancera l’application native associée. Ce schéma est recommandé si le système d’exploitation le prend en charge. Voir QOAuthUriSchemeReplyHandler.
  • Interfaces de bouclage: elles sont couramment utilisées pour les applications de bureau et les applications en cours de développement. L’ QOAuthHttpServerReplyHandler est conçu pour gérer ces URI en configurant un serveur local chargé de la redirection.

Le choix dépend de plusieurs facteurs, tels que :

  • Les URI de redirection prises en charge par le fournisseur du serveur d’autorisation. La prise en charge varie d’un fournisseur à l’autre et est souvent spécifique à un type de client et à un système d’exploitation particuliers. De plus, elle peut varier selon que l’application est publiée ou non.
  • Les schémas d’URI de redirection pris en charge par la ou les plateformes cibles.
  • Les exigences spécifiques à l'application en matière d'ergonomie, de sécurité et autres.

La RFC 8252 recommande d’utiliser le schéma https en raison de ses avantages en termes de sécurité et d’ergonomie par rapport aux autres méthodes.

Octroi d'autorisation d'appareil OAuth 2.0

Le protocole d’autorisation des appareils OAuth 2.0(RFC 8628 ) est destiné aux appareils connectés dont les capacités de saisie sont limitées ou pour lesquels l’utilisation d’un navigateur (agent utilisateur) n’est pas pratique. Parmi les exemples d’appareils utilisant ce flux, on peut citer les appareils électroménagers intelligents qui nécessitent des périphériques externes pour l’autorisation.

Prenons l'exemple de configuration suivant :

m_deviceFlow.setAuthorizationUrl(QUrl(authorizationUrl));
m_deviceFlow.setTokenUrl(QUrl(accessTokenUrl));
m_deviceFlow.setRequestedScopeTokens({scope});
m_deviceFlow.setClientIdentifier(clientIdentifier);
// La nécessité d’un secret client dépend du serveur d’autorisation
m_deviceFlow.setClientIdentifierSharedKey(clientSecret);

connect(&m_deviceFlow, &QOAuth2DeviceAuthorizationFlow::authorizeWithUserCode, this,
    [](const QUrl&verificationUrl, const QString&userCode, const QUrl&completeVerificationUrl) {
        if (completeVerificationUrl.isValid()) {
            // Si le serveur d’autorisation a fourni une URL complète
            // contenant déjà les données nécessaires dans les paramètres de l’URL,
            // vous pouvez choisir de l’utiliser
            qDebug() << "Complete verification uri:" << completeVerificationUrl;
        } else {
            // Le serveur d'autorisation n'a fourni qu'une URL de vérification ; utilisons celle-ci
            qDebug() << "Verification uri and usercode:" << verificationUrl << userCode;
        }
    }
);

connect(&m_deviceFlow, &QAbstractOAuth::granted, this, [this](){
    // Ici, nous utilisons QNetworkRequestFactory pour stocker le jeton d'accès
    m_api.setBearerToken(m_deviceFlow.token().toLatin1());
});
m_deviceFlow.grant();

Étapes de l'autorisation d'un appareil

Le processus d’autorisation par appareil comporte trois étapes principales : l’initialisation de l’autorisation, la recherche de jetons et la finalisation de l’autorisation. Ces étapes sont éventuellement suivies de l’utilisation du jeton et de son actualisation. La figure suivante illustre ces étapes :

Processus simplifié d'octroi d'autorisation dans une application Qt utilisant un navigateur sur un appareil distinct

  • L’autorisation est initialisée par l’envoi d’une requête HTTP au serveur d’autorisation. Ce dernier fournit en réponse un code utilisateur, des URL de vérification et un code d’appareil.
  • Une fois l’autorisation initialisée, l’utilisateur reçoit un code utilisateur et une ou plusieurs URL de vérification pour finaliser l’autorisation. Le mécanisme utilisé pour l’utilisateur final peut varier : il peut s’agir d’une URL visible à l’écran, d’un code QR, d’un e-mail, etc. Pour plus d’informations, reportez-vous à la RFC 8628 – Interaction avec l’utilisateur.
  • En attendant que l’utilisateur final finalise l’autorisation, le flux de l’appareil interroge le serveur d’autorisation pour obtenir des jetons. Le code d’appareil reçu à l’étape précédente est utilisé pour établir la correspondance avec la session d’autorisation. L’intervalle d’interrogation est déterminé par le serveur d’autorisation et est généralement de 5 secondes.
  • Une fois que l’utilisateur final a accepté ou refusé l’autorisation, le serveur d’autorisation répond à une requête d’interrogation en fournissant les jetons demandés ou un code d’erreur en cas de refus, et l’autorisation est alors finalisée.

Détails et personnalisation

La figure suivante illustre plus en détail le flux d’octroi d’autorisation de l’appareil. Elle présente les principaux points de personnalisation, qui s’avèrent parfois nécessaires. Il peut s’agir, par exemple, de paramètres propriétaires ou d’informations d’identification supplémentaires.

Détails du flux d'autorisation OAuth 2.0 pour les appareils, illustrant les appels d'événements spécifiques

Jetons de rafraîchissement

L'utilisation de jetons de rafraîchissement nécessite que le serveur d'autorisation fournisse un jeton de rafraîchissement lors de l'autorisation. La fourniture d'un jeton de rafraîchissement relève de la décision du serveur d'autorisation : certains serveurs peuvent choisir de toujours le fournir, d'autres de ne jamais le fournir, et d'autres encore de le fournir si une « scope » spécifique était présente dans la requête d'autorisation.

La figure suivante illustre plus en détail le processus de rafraîchissement des jetons :

Détails sur les jetons de rafraîchissement indiquant les appels d'événements spécifiques

Comme le montre la figure ci-dessus, les points de personnalisation habituels sont également disponibles lors du rafraîchissement des jetons.

Pour actualiser les jetons après le démarrage de l'application, celle-ci doit conserver le jeton d'actualisation en toute sécurité et le définir à l'aide de la méthode ` QAbstractOAuth2::setRefreshToken`. La méthode ` QAbstractOAuth2::refreshTokens ` peut ensuite être appelée pour demander de nouveaux jetons.

Nouveauté de Qt 6.9 : les applications peuvent actualiser automatiquement les jetons — voir QAbstractOAuth2::accessTokenAboutToExpire, QAbstractOAuth2::autoRefresh et QAbstractOAuth2::refreshLeadTime.

La durée d'expiration d'un jeton de rafraîchissement n'est généralement pas indiquée par le serveur d'autorisation (à l'exception de la documentation du serveur). Leur validité peut aller de quelques jours à plusieurs mois, voire plus. De plus, comme pour les autres jetons, les jetons de rafraîchissement peuvent être révoqués par l'utilisateur et donc invalidés à tout moment. Il est donc important de détecter correctement une tentative de rafraîchissement ayant échoué à l'aide de QAbstractOAuth::requestFailed ou QAbstractOAuth2::serverReportedErrorOccurred.

Les flux OAuth 2.0 nécessitent de nombreuses interactions de la part de l’utilisateur, ce qui peut nuire à l’expérience utilisateur. Pour minimiser ces interactions, les jetons peuvent être actualisés de manière transparente pour l’utilisateur. Reportez-vous à la RFC 6749 – Actualisation des jetons d’accès pour plus d’informations.

Prise en charge de Qt OpenID Connect

OpenID Connect (OIDC) est une couche d'identité simple s'appuyant sur OAuth 2.0. OIDC peut utiliser un serveur d'autorisation pour authentifier l'identité d'un utilisateur. OIDC permet également d'accéder à des informations simples sur le profil de l'utilisateur.

La prise en charge d'OIDC par Qt se limite pour l'instant à l'obtention de jetons d'identification. Un jeton d'identification est un jeton Web JSON (JWT) qui contient des informations relatives à l'événement d'authentification.

Remarque : la validation ou le déchiffrement des jetonsd'identification n'est actuellement pas implémenté. Vous devez utiliser une bibliothèque JWT tierce pour la signature ou la vérification des jetons JWT.

En supposant que l'application soit capable de valider les jetons reçus, ceux-ci peuvent être utilisés pour établir l'identité de l'utilisateur de manière fiable (à condition que le fournisseur OIDC lui-même soit fiable).

Les jetons d’identité constituent des informations sensibles et doivent rester confidentiels ; ils ne doivent pas être confondus avec les jetons d’accès. Les jetons d’identité ne sont pas destinés à être transmis dans le cadre d’appels d’API — c’est le jeton d’accès qui est prévu à cet effet. Notez que certains fournisseurs peuvent utiliser le même format JWT pour les jetons d’accès, mais il ne faut pas confondre ceux-ci avec les véritables jetons d’identité qui utilisent le même format. Avec les jetons d’identité, c’est le client recevant le jeton qui est chargé de le vérifier, tandis qu’avec les jetons d’accès, c’est le serveur de ressources acceptant le jeton qui est responsable de la vérification.

Obtenir un jeton d’identification

L’obtention d’un jeton d’identification s’effectue de manière similaire à celle d’un jeton d’accès. Tout d’abord, il faut définir la portée appropriée. Le fournisseur du serveur d’autorisation peut prendre en charge des spécificateurs de portée supplémentaires tels que profile et email, mais toutes les requêtes OIDC doivent inclure la portée openid:

m_oauth.setRequestedScopeTokens({"openid"});

Pour l’OIDC, il est fortement recommandé d’utiliser le paramètre nonce. Pour ce faire, il faut s’assurer que le paramètre NonceMode est correctement défini.

// This is for illustrative purposes, 'Automatic' is the default mode
m_oauth.setNonceMode(QAbstractOAuth2::NonceMode::Automatic);

En dernière étape, nous pouvons écouter soit le signal « QAbstractOAuth2::granted », soit l’ QAbstractOAuth2::idTokenChanged directement :

connect(&m_oauth, &QAbstractOAuth2::idTokenChanged, this, [this](const QString &token) {
    Q_UNUSED(token); // Handle token
});

Validation d’un jeton d’identification

La validation du jeton d’identification reçu est une étape cruciale du processus d’authentification et, lorsqu’elle est pleinement mise en œuvre, une tâche quelque peu complexe. Pour plus d’informations, consultez la documentation complète sur la validation des identifiants OpenID Connect.

En résumé, la validation comprend les étapes suivantes :

  • Décryptage du jeton si nécessaire (voir JWE)
  • Extraction de l'en-tête, de la charge utile et de la signature du jeton
  • Valider la signature
  • Valider les champs de la charge utile (tels que aud, iss, exp, nonce, iat)

Qt ne prend actuellement pas en charge la validation des jetons d'identification, mais il existe des bibliothèques JWT tierces, telles que jwt-cpp.

Exemple de vérification d'un jeton d'identification

Cette section présente un exemple simple de vérification. Pour que cela fonctionne, l'environnement de développement doit disposer des bibliothèques OpenSSL, et jwt-cpp doit se trouver dans le dossier « include » du répertoire source du projet d'application.

Dans le fichier ` CMakeLists.txt ` du projet d'application, nous vérifions tout d'abord que les prérequis sont remplis :

find_package(OpenSSL 1.0.0 QUIET)
set(JWT_CPP_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include")
if(OPENSSL_FOUND AND EXISTS "${JWT_CPP_INCLUDE_DIR}/jwt-cpp/jwt.h")

Ensuite, nous ajoutons les inclusions et les bibliothèques nécessaires :

    target_include_directories(networkauth_oauth_snippets PRIVATE "${JWT_CPP_INCLUDE_DIR}")
    target_link_libraries(networkauth_oauth_snippets PRIVATE OpenSSL::SSL OpenSSL::Crypto)
    target_compile_definitions(networkauth_oauth_snippets PRIVATE JWT_CPP_AVAILABLE)

Dans les fichiers source de l'application, incluez la bibliothèque de vérification :

#ifdef JWT_CPP_AVAILABLE
#include "jwt-cpp/jwt.h"
#endif

Une fois que l'application a reçu un jeton d'identification, il est temps de le vérifier. Nous commençons par rechercher une clé correspondante dans les ensembles de clés Web JSON (JWKS) (voir « OpenID Connect Discovery »).

try {
    const auto jwt = jwt::decode(m_oauth.idToken().toStdString());
    const auto jwks = jwt::parse_jwks(m_jwks->toJson(QJsonDocument::Compact).toStdString());
    const auto jwk = jwks.get_jwk(jwt.get_key_id());

Puis, nous procédons à la vérification proprement dite :

   // Ici, nous utilisons le module et l’exposant pour dériver la clé
    const auto n = jwk.get_jwk_claim("n").as_string(); // module
   const auto e = jwk.get_jwk_claim("e").as_string(); // exposant
    if (n.empty()|| e.empty()) {
        qWarning() << "Modulus or exponent empty";
       return false;
    }
    if (jwt.get_algorithm() != "RS256") { // Cet exemple ne prend en charge que l'algorithme RS256
        qWarning() << "Unsupported algorithm:" << jwt.get_algorithm();
       return false;
    }
    if (jwk.get_jwk_claim("kty").as_string() != "RSA") {
        qWarning() << "Unsupported key type:" << jwk.get_jwk_claim("kty").as_string();
       return false;
    }
    if (jwk.has_jwk_claim("use")&& jwk.get_jwk_claim("use").as_string() != "sig") {
        qWarning() << "Key not for signature" << jwk.get_jwk_claim("use").as_string();
       return false;
    }
    // Vérification simple et minimale (ne prend pas en compte les cas particuliers ni, par exemple, la vérification « sub »).
    // jwt-cpp vérifie également les champs « exp », « iat » et « nbf » s'ils sont présents.
   const auto keyPEM = jwt::helper::create_public_key_from_rsa_components(n, e);
    auto verifier = jwt::verify()
                        .allow_algorithm(jwt::algorithm::rs256(keyPEM))
                       .with_claim("nonce", jwt::claim(m_oauth.nonce().toStdString()))
                        .with_issuer(m_oidcConfig->value("issuer"_L1).toString().toStdString())
                       .with_audience(std::string(clientIdentifier.data()))
                        .leeway(60UL);
    verifier.verify(jwt);
    qDebug() << "ID Token verified successfully";
   return true;
} catch(const std::exception &e) {
    // Gérer l'erreur. Il est également possible de transmettre le paramètre d'erreur aux appels jwt-cpp
    qWarning() << "ID Token verification failed" << e.what();
   return false;
}

Lecture des valeurs des jetons d'identification

Le jeton d'identification est au format JSON Web Token (JWT) et se compose d'un en-tête, d'une charge utile et d'une signature, séparés par des points ..

La lecture des valeurs du jeton d'identification est très simple. À titre d'exemple, supposons qu'il existe une structure :

struct IDToken {
    QJsonObject header;
    QJsonObject payload;
    QByteArray signature;
};

Et une fonction :

std::optional<IDToken> parseIDToken(const QString &token) const;

Le jeton peut être extrait à l'aide de :

if (token.isEmpty())
    return std::nullopt;

QList<QByteArray> parts = token.toLatin1().split('.');
if (parts.size() != 3)
    return std::nullopt;

QJsonParseError parsing;

QJsonDocument header = QJsonDocument::fromJson(
    QByteArray::fromBase64(parts.at(0), QByteArray::Base64UrlEncoding), &parsing);
if (parsing.error != QJsonParseError::NoError || !header.isObject())
    return std::nullopt;

QJsonDocument payload = QJsonDocument::fromJson(
    QByteArray::fromBase64(parts.at(1), QByteArray::Base64UrlEncoding), &parsing);
if (parsing.error != QJsonParseError::NoError || !payload.isObject())
    return std::nullopt;

QByteArray signature = QByteArray::fromBase64(parts.at(2), QByteArray::Base64UrlEncoding);

return IDToken{header.object(), payload.object(), signature};

Dans certains cas, le jeton peut être chiffré au format JSON Web Encryption (JWE) et contenir en interne un jeton JWT. Dans ce cas, le jeton doit d'abord être déchiffré.

Découverte OpenID Connect

La découverte OpenID Connect définit les moyens permettant de trouver les informations nécessaires sur le fournisseur OpenID afin d'interagir avec lui. Cela inclut des informations telles que les URL authorization_endpoint et token_endpoint.

Bien que ces informations puissent être configurées de manière statique dans l'application, leur découverte lors de l'exécution peut offrir davantage de flexibilité et de fiabilité dans l'interaction avec divers fournisseurs.

L'obtention du document de découverte s'effectue par une simple requête HTTP GET. Ce document se trouve généralement à l'adresse https://<domain name>/.well-known/openid_configuration.

m_network->get(request, this, [this](QRestReply &reply) {
    if (reply.isSuccess()) {
        if (auto doc = reply.readJson(); doc && doc->isObject())
            m_oidcConfig = doc->object(); // Store the configuration
    }
});

Il convient de noter que, pour la validation des jetons, le champ jwks_uri fournit un lien permettant d’accéder aux informations d’identification de sécurité (publiques) actuelles. L'utilisation de ce lien évite d'avoir à coder en dur ces informations d'identification directement dans l'application. Cela facilite également la rotation des clés ; les fournisseurs pouvant modifier les clés utilisées de temps à autre, il est donc important de s'assurer que la clé utilisée est à jour.

L'obtention des clés s'effectue de la même manière, par une simple requête HTTP GET :

m_network->get(request, this, [this](QRestReply &reply) {
    if (reply.isSuccess()) {
        if (auto doc = reply.readJson(); doc && doc->isObject())
            m_jwks = doc; // Use the keys later to verify tokens
    }
});

L'ensemble de clés contient généralement plusieurs clés. La clé correcte est indiquée dans l'en-tête JWT (il faut veiller à bien faire correspondre les clés ; il ne suffit pas de vérifier uniquement le champ « key id » ( kid)).

Point de terminaison OpenID UserInfo

Une autre façon d’accéder aux informations utilisateur consiste à utiliser le point de terminaison UserInfo d’OpenID Connect, si le fournisseur OIDC le prend en charge. L’URL de la ressource userinfo se trouve dans le champ userinfo_endpoint du document de découverte OpenID Connect.

Le point de terminaison UserInfo n'utilise pas le jeton d'identification, mais est accessible à l'aide du jeton d'accès. L'accès à UserInfo s'effectue de la même manière que l'accès à toute autre ressource à l'aide d'un jeton d'accès.

En supposant que le jeton d’accès ait été reçu et défini, par exemple par :

QNetworkRequestFactory userInfoApi(url);
userInfoApi.setBearerToken(m_oauth.token().toLatin1());

L'accès à UserInfo s'effectue alors via une requête HTTP GET :

m_network->get(userInfoApi.createRequest(), this, [this](QRestReply&reply) {
    if (reply.isSuccess()) {
        if (auto doc = reply.readJson(); doc&& doc->isObject())
            qDebug() << doc->object(); // Use the userinfo
    }
});

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.