Auf dieser Seite

OAuth 2.0 – Überblick

RFC 6749 – Das OAuth 2.0-Autorisierungsframework legt ein Protokoll für die Autorisierung von Diensten mithilfe einer Drittanbieteranwendung fest. OAuth 2.0 nutzt Tokens, um die Autorisierung vom Dienst und den Benutzern zu abstrahieren. Diese Methode ist sicherer, da der Dienstbetreiber nicht mit den Anmeldedaten der Benutzer umgehen muss. Es handelt sich um einen Ersatz für RFC 5849 OAuth 1.0.

Das OAuth 2.0-Framework definiert zwei Client-Typen – öffentlich oder vertraulich – sowie verschiedene Abläufe zur Autorisierung, wie beispielsweise den Autorisierungscode-Ablauf, die implizite Code-Gewährung und einige weitere. Eine typische Qt-Anwendung gilt als öffentliche native Anwendung. Eine öffentliche Client-Anwendung ist eine Anwendung, der es nicht anvertraut werden kann, sensible Informationen wie Passwörter zu speichern, die in die ausgelieferte Binärdatei eingebettet werden sollen.

RFC 8252 „OAuth 2.0 for Native Apps“ definiert darüber hinaus die Best Practices für native Anwendungen. Insbesondere empfiehlt RFC 8252 den Autorisierungsablauf über den Browser. Daher bieten die Klassen „ QtNetworkAuth “ eine konkrete Implementierung dieses Ablaufs.

Neu in Qt 6.9 ist die Unterstützung von RFC 8628 – OAuth 2.0 Device Authorization Grant durch „ QtNetworkAuth “. Dieser Geräteablauf ist für Geräte vorgesehen, die über eingeschränkte oder unpraktische Eingabemöglichkeiten verfügen. Bei diesem Ablauf nutzen Autorisierungsgrants ein sekundäres Gerät wie beispielsweise ein Smartphone anstelle des eigentlichen Geräts. Beispiele für solche Geräte sind Fernseher, Medienkonsolen, Maschinen-HMIs und IoT-Geräte. Der Benutzer kann dann eine Anwendung auf seinem Smartphone verwenden, um das Gerät zu autorisieren.

Die folgende Tabelle zeigt die beiden von „ Qt Network -Autorisierung“ unterstützten OAuth 2.0-Abläufe:

AspektAutorisierungscode-AblaufGeräteautorisierungsablauf
NetzwerkverbindungJaJa
BenutzerinteraktionBrowser / User-Agent auf demselben GerätBrowser / User-Agent auf einem anderen Gerät
Weiterleitungsverarbeitung erforderlichJaNein
Eingabemöglichkeiten auf dem GerätUmfangreiche EingabemöglichkeitenEingabemöglichkeiten eingeschränkt oder nicht vorhanden
ZielgruppenDesktop- und mobile AppsFernseher, Spielkonsolen, HMIs, IoT-Geräte

OAuth 2.0 erfordert die Verwendung eines User-Agents, bei dem es sich in der Regel um einen Browser handelt. Weitere Informationen finden Sie unter „Qt OAuth2 Browser Support“.

OAuth 2.0-Klassen

Qt Network „Authorization“ stellt sowohl konkrete als auch abstrakte OAuth 2.0-Klassen bereit. Die abstrakten Klassen sind für die Implementierung benutzerdefinierter Abläufe vorgesehen, während die konkreten Klassen eine konkrete Implementierung bieten.

Eine Liste der C++-Klassen finden Sie auf der Seite „ QtNetworkAuth “.

Qt Network „Authorization“ verfügt über zwei abstrakte Klassen zur Implementierung von OAuth 2.0-Abläufen:

Autorisierungscode-Ablauf

Dieser Abschnitt bietet einen Überblick über den Autorisierungscode-Ablauf gemäß RFC 6749 – „Authorization Code“ und RFC 8252 – „Authorization Request from a Native App “ für native Anwendungen.

Betrachten Sie die folgende Beispielkonfiguration:

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();
}

Phasen des Autorisierungsablaufs

Der Autorisierungscode-Ablauf gemäß RFC 6749 umfasst zwei Hauptphasen: die Ressourcenautorisierung (einschließlich einer gegebenenfalls erforderlichen Benutzerauthentifizierung), gefolgt von einer Zugriffstoken-Anforderung. Darauf folgen optional die Verwendung des Zugriffstokens und die Aktualisierung des Zugriffstokens. Die folgende Abbildung veranschaulicht diese Phasen:

Vereinfachter Autorisierungsprozess in einer Qt-Anwendung unter Verwendung eines Autorisierungsservers und eines Browsers

  • In der Autorisierungsphase wird der Benutzer authentifiziert und erteilt die Berechtigung für den Zugriff auf Ressourcen. Dies erfordert eine Interaktion des Benutzers über den Browser.
  • Nach der Autorisierung wird der erhaltene Autorisierungscode verwendet, um ein Zugriffstoken und optional ein Aktualisierungstoken anzufordern.
  • Sobald das Zugriffstoken erhalten wurde, nutzt die Anwendung es, um auf die gewünschten Ressourcen zuzugreifen. Das Zugriffstoken wird in die Ressourcenanfragen eingebunden, und es obliegt dem Ressourcenserver, die Gültigkeit des Tokens zu überprüfen. Es gibt mehrere Möglichkeiten, das Token als Teil der Anfragen mit Bearer-Tokens einzubinden. Die Einbindung des Tokens in den HTTP-Header „ Authorization “ ist wohl die gängigste Methode.
  • Aktualisierung des Zugriffstokens. Zugriffstokens verfallen in der Regel relativ schnell, beispielsweise nach einer Stunde. Hat die Anwendung zusätzlich zum Zugriffstoken ein Aktualisierungstoken erhalten, kann dieses verwendet werden, um ein neues Zugriffstoken anzufordern. Anwendungen können Aktualisierungstokens mit längerer Gültigkeitsdauer speichern, um eine neue Autorisierungsphase (und damit eine weitere Interaktion mit dem Browser) zu vermeiden.

Details und Anpassung

OAuth-2.0-Abläufe sind dynamisch, und die Umsetzung der Spezifikationen kann anfangs schwierig sein. Die folgende Abbildung veranschaulicht die wichtigsten Details eines erfolgreichen Autorisierungscode-Ablaufs.

Details zum OAuth 2.0-Ablauf mit den spezifischen Ereignisaufrufen

Der Übersichtlichkeit halber wurden in der Abbildung einige Signale weggelassen, insgesamt werden jedoch die Details und die wichtigsten Anpassungsmöglichkeiten dargestellt. Bei den Anpassungsmöglichkeiten handelt es sich um die verschiedenen Signale und Slots, die die Anwendung nutzen kann, sowie um die Callbacks, die mit ` QAbstractOAuth::setModifyParametersFunction()` und ` QAbstractOAuth2::setNetworkRequestModifier()` festgelegt werden können.

Auswahl eines Antwort-Handlers

Die Entscheidung, welcher Handler verwendet wird, hängt vom Element „redirect_uri“ ab. Die „ redirect_uri “ wird auf die Adresse gesetzt, zu der der Browser nach Abschluss der Autorisierungsphase weitergeleitet wird.

Für den Empfang der Autorisierungsantwort in nativen Anwendungen legt RFC 8252 drei Haupttypen von Antwort-URI-Schemas fest: „private-use“, „loopback“ und „https“.

  • URIs für den privaten Gebrauch: Können verwendet werden, wenn das Betriebssystem einer Anwendung erlaubt, ein benutzerdefiniertes URI-Schema zu registrieren. Der Versuch, eine URL mit einem solchen benutzerdefinierten Schema zu öffnen, führt zum Öffnen der zugehörigen nativen Anwendung. Siehe QOAuthUriSchemeReplyHandler.
  • HTTPS-URIs: Können verwendet werden, wenn das Betriebssystem der Anwendung erlaubt, eine benutzerdefinierte HTTPS-URL zu registrieren. Der Versuch, diese URL zu öffnen, führt zum Start der zugehörigen nativen Anwendung. Dieses Schema wird empfohlen, sofern es vom Betriebssystem unterstützt wird. Siehe QOAuthUriSchemeReplyHandler.
  • Loopback-Schnittstellen: Diese werden häufig für Desktop-Anwendungen und Anwendungen während der Entwicklung verwendet. Das „ QOAuthHttpServerReplyHandler “ ist so konzipiert, dass es diese URIs verarbeitet, indem es einen lokalen Server einrichtet, der die Weiterleitung übernimmt.

Die Wahl hängt von verschiedenen Faktoren ab, wie zum Beispiel:

  • Die vom Anbieter des Autorisierungsservers unterstützten Umleitungs-URIs. Die Unterstützung variiert von Anbieter zu Anbieter und ist oft spezifisch für einen bestimmten Client-Typ und ein bestimmtes Betriebssystem. Außerdem kann die Unterstützung davon abhängen, ob die Anwendung veröffentlicht ist oder nicht.
  • Von der/den Zielplattform(en) unterstützte Umleitungs-URI-Schemas.
  • Anwendungsspezifische Anforderungen hinsichtlich Benutzerfreundlichkeit, Sicherheit und anderer Aspekte.

RFC 8252 empfiehlt die Verwendung des Schemas „ https “ aufgrund der Vorteile hinsichtlich Sicherheit und Benutzerfreundlichkeit gegenüber den anderen Methoden.

OAuth 2.0-Geräteautorisierungsablauf

Derin RFC 8628 beschriebene OAuth 2.0-Geräteautorisierungsablauf ist für vernetzte Geräte vorgesehen, deren Eingabemöglichkeiten begrenzt sind oder bei denen die Verwendung eines User-Agent-Browsers nicht praktikabel ist. Beispiele für Geräte, die diesen Ablauf nutzen, sind intelligente Haushaltsgeräte, die zur Autorisierung externe Geräte benötigen.

Betrachten Sie die folgende Beispielkonfiguration:

m_deviceFlow.setAuthorizationUrl(QUrl(authorizationUrl));
m_deviceFlow.setTokenUrl(QUrl(accessTokenUrl));
m_deviceFlow.setRequestedScopeTokens({scope});
m_deviceFlow.setClientIdentifier(clientIdentifier);
// Ob ein Client-Secret erforderlich ist, hängt vom Autorisierungsserver ab
m_deviceFlow.setClientIdentifierSharedKey(clientSecret);

connect(&m_deviceFlow, &QOAuth2DeviceAuthorizationFlow::authorizeWithUserCode, this,
    [](const QUrl&verificationUrl, const QString&userCode, const QUrl&completeVerificationUrl) {
        if (completeVerificationUrl.isValid()) {
            // Wenn der Autorisierungsserver eine vollständige URL bereitgestellt hat,
            // die die erforderlichen Daten bereits als Teil der URL-Parameter enthält,
            // können Sie diese verwenden
            qDebug() << "Complete verification uri:" << completeVerificationUrl;
        } else {
            // Der Autorisierungsserver hat nur eine Verifizierungs-URL bereitgestellt; diese verwenden
            qDebug() << "Verification uri and usercode:" << verificationUrl << userCode;
        }
    }
);

connect(&m_deviceFlow, &QAbstractOAuth::granted, this, [this](){
    // Hier verwenden wir QNetworkRequestFactory, um das Zugriffstoken zu speichern
    m_api.setBearerToken(m_deviceFlow.token().toLatin1());
});
m_deviceFlow.grant();

Phasen der Geräteautorisierung

Der Ablauf der Geräteautorisierung umfasst drei Hauptphasen: Initialisierung der Autorisierung, Abfrage von Tokens und Abschluss der Autorisierung. Darauf folgen optional die Token-Nutzung und die Token-Aktualisierung. Die folgende Abbildung veranschaulicht diese Phasen:

Vereinfachter Ablauf der Autorisierungserteilung in einer Qt-Anwendung unter Verwendung eines Browsers auf einem separaten Gerät

  • Die Autorisierung wird durch das Senden einer HTTP-Anfrage an den Autorisierungsserver initialisiert. Der Autorisierungsserver stellt als Antwort einen Benutzercode, Verifizierungs-URLs und einen Gerätecode bereit.
  • Nach der Initialisierung der Autorisierung erhält der Benutzer einen Benutzercode und eine oder mehrere Verifizierungs-URLs zum Abschluss der Autorisierung. Die Art der Bereitstellung für den Endbenutzer variiert: Es kann sich um eine auf dem Bildschirm angezeigte URL, einen QR-Code, eine E-Mail usw. handeln. Weitere Informationen finden Sie in RFC 8628 – User Interaction.
  • Während darauf gewartet wird, dass der Endnutzer die Autorisierung abschließt, fragt der Geräteablauf den Autorisierungsserver nach Tokens ab. Der im vorherigen Schritt empfangene Gerätecode wird verwendet, um die Autorisierungssitzung abzugleichen. Das Abfrageintervall wird vom Autorisierungsserver festgelegt und beträgt in der Regel 5 Sekunden.
  • Sobald der Endnutzer die Autorisierung akzeptiert oder abgelehnt hat, antwortet der Autorisierungsserver auf eine Abfrageanforderung mit den angeforderten Tokens oder – im Falle einer Ablehnung – mit einem Fehlercode, und die Autorisierung ist abgeschlossen.

Details und Anpassung

Die folgende Abbildung veranschaulicht den Ablauf der Geräteautorisierung genauer. Die Abbildung zeigt die wichtigsten Anpassungspunkte, die manchmal erforderlich sind. Dazu gehören beispielsweise proprietäre Parameter oder zusätzliche Authentifizierungsdaten.

Details zum OAuth 2.0-Geräte-Grant-Ablauf mit den spezifischen Ereignisaufrufen

Aktualisierungstoken

Für die Aktualisierung von Tokens muss der Autorisierungsserver während der Autorisierung ein Aktualisierungstoken bereitstellen. Die Bereitstellung eines Aktualisierungstokens liegt im Ermessen des Autorisierungsservers: Einige Server stellen es möglicherweise immer bereit, andere niemals, und wieder andere stellen es bereit, wenn ein bestimmtes „ scope “ in der Autorisierungsanfrage enthalten war.

Die folgende Abbildung veranschaulicht die Token-Aktualisierung im Detail:

Details zur Aktualisierung von Tokens, aus denen die jeweiligen Ereignisaufrufe hervorgehen

Wie in der obigen Abbildung dargestellt, stehen auch beim Aktualisieren von Tokens die üblichen Anpassungsmöglichkeiten zur Verfügung.

Um die Token nach dem Start der Anwendung zu aktualisieren, muss die Anwendung das Aktualisierungstoken sicher speichern und es mit ` QAbstractOAuth2::setRefreshToken` setzen. Anschließend kann ` QAbstractOAuth2::refreshTokens ` aufgerufen werden, um neue Token anzufordern.

Neu in Qt 6.9 ist, dass Anwendungen die Tokens automatisch aktualisieren können – siehe QAbstractOAuth2::accessTokenAboutToExpire, QAbstractOAuth2::autoRefresh und QAbstractOAuth2::refreshLeadTime.

Die Ablaufzeit eines Aktualisierungstokens wird vom Autorisierungsserver in der Regel nicht angegeben (abgesehen von der Dokumentation des Servers). Ihre Gültigkeit kann Tage, Monate oder länger betragen. Darüber hinaus können Aktualisierungstoken, wie auch andere Token, vom Benutzer widerrufen und somit jederzeit ungültig gemacht werden. Daher ist es wichtig, einen fehlgeschlagenen Aktualisierungsversuch mit „ QAbstractOAuth::requestFailed “ oder „ QAbstractOAuth2::serverReportedErrorOccurred “ ordnungsgemäß zu erkennen.

OAuth-2.0-Abläufe erfordern zahlreiche Benutzerinteraktionen, was die Benutzererfahrung beeinträchtigen kann. Um diese Interaktionen zu minimieren, können Token für den Benutzer im Hintergrund aktualisiert werden. Weitere Informationen finden Sie im RFC 6749 – „Refreshing Access Tokens “.

Qt-Unterstützung für OpenID Connect

OpenID Connect (OIDC) ist eine einfache Identitätsschicht, die auf OAuth 2.0 aufsetzt. OIDC kann einen Autorisierungsserver zur Authentifizierung der Identität eines Benutzers nutzen. Auch der Zugriff auf einfache Benutzerprofilinformationen ist mit OIDC möglich.

Die Unterstützung von OIDC durch Qt beschränkt sich derzeit auf das Abrufen von ID-Tokens. Ein ID-Token ist ein JSON Web Token (JWT), das Angaben zum Authentifizierungsvorgang enthält.

Hinweis: Die Validierung oder Entschlüsselung vonID-Tokens ist derzeit nicht implementiert. Sie müssen eine JWT-Bibliothek eines Drittanbieters für die Signierung oder Überprüfung von JWT-Tokens verwenden.

Vorausgesetzt, die Anwendung ist in der Lage, die empfangenen Token zu validieren, kann das Token verwendet werden, um die Identität des Benutzers zuverlässig festzustellen (sofern der OIDC-Anbieter selbst vertrauenswürdig ist).

ID-Token sind sensible Informationen und sollten geheim gehalten werden; sie sind nicht mit Zugriffstoken gleichzusetzen. ID-Token sind nicht dafür vorgesehen, in API-Aufrufen versendet zu werden – hierfür ist das Zugriffstoken vorgesehen. Beachten Sie, dass einige Anbieter möglicherweise dasselbe JWT-Format für Zugriffstoken verwenden; dies ist jedoch nicht mit tatsächlichen ID-Token zu verwechseln, die dasselbe Format nutzen. Bei ID-Token ist der Client, der das Token empfängt, für die Überprüfung des Tokens verantwortlich, während bei Zugriffstoken der Ressourcenserver, der das Token akzeptiert, für die Überprüfung zuständig ist.

Bezug eines ID-Tokens

Das Abrufen eines ID-Tokens erfolgt ähnlich wie das Abrufen eines Zugriffstokens. Zunächst müssen wir den entsprechenden Geltungsbereich festlegen. Der Anbieter des Autorisierungsservers unterstützt möglicherweise zusätzliche Geltungsbereichsangaben wie „ profile “ und „ email “, doch alle OIDC-Anfragen müssen den Geltungsbereich „ openid “ enthalten:

m_oauth.setRequestedScopeTokens({"openid"});

Für OIDC wird dringend empfohlen, den Parameter „ nonce “ zu verwenden. Dies geschieht, indem sichergestellt wird, dass der entsprechende „ NonceMode “ festgelegt ist.

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

Als letzten Schritt können wir entweder auf das Signal „ QAbstractOAuth2::granted “ oder direkt auf den Wert von „ QAbstractOAuth2::idTokenChanged “ warten:

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

Überprüfung eines ID-Tokens

Die Validierung des empfangenen ID-Tokens ist ein entscheidender Bestandteil des Authentifizierungsablaufs und stellt bei vollständiger Implementierung eine etwas komplizierte Aufgabe dar. Weitere Informationen finden Sie unter „OpenID Connect ID-Validierung“.

Zusammenfassend lässt sich sagen, dass die Validierung aus folgenden Schritten besteht:

  • Entschlüsseln des Tokens, falls erforderlich (siehe JWE)
  • Extrahieren des Token-Headers, der Nutzdaten und der Signatur
  • Validierung der Signatur
  • Überprüfung der Felder der Nutzdaten (z. B. „ aud, iss, exp, nonce, iat “)

Qt bietet derzeit keine Unterstützung für die Validierung von ID-Token, es gibt jedoch JWT-Bibliotheken von Drittanbietern, wie z. B. jwt-cpp.

Beispiel für die Überprüfung eines ID-Tokens

Dieser Abschnitt veranschaulicht ein einfaches Beispiel für die Überprüfung. Als Voraussetzungen müssen in der Entwicklungsumgebung OpenSSL-Bibliotheken vorhanden sein und „jwt-cpp“ im Ordner „include“ unterhalb des Quellverzeichnisses des Anwendungsprojekts abgelegt sein.

In der Datei „ CMakeLists.txt “ des Anwendungsprojekts überprüfen wir zunächst, ob die Voraussetzungen erfüllt sind:

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")

Anschließend fügen wir die erforderlichen Include-Dateien und Bibliotheken hinzu:

    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)

Fügen Sie in den Quelldateien der Anwendung die Verifizierungsbibliothek ein:

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

Sobald die Anwendung ein ID-Token erhält, muss dieses verifiziert werden. Zunächst suchen wir einen passenden Schlüssel aus den JSON Web Key Sets (JWKS) – siehe 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());

Anschließend führen wir die eigentliche Überprüfung durch:

   // Hier verwenden wir Modulus und Exponent, um den Schlüssel abzuleiten
    const auto n = jwk.get_jwk_claim("n").as_string(); // Modulus
   const auto e = jwk.get_jwk_claim("e").as_string(); // Exponent
    if (n.empty()|| e.empty()) {
        qWarning() << "Modulus or exponent empty";
       return false;
    }
    if (jwt.get_algorithm() != "RS256") { // Dieses Beispiel unterstützt nur 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;
    }
    // Einfache, minimale Überprüfung (Sonderfälle und z. B. die „sub“-Überprüfung werden ausgelassen).
    // jwt-cpp überprüft auch „exp“, „iat“ und „nbf“, sofern diese vorhanden sind.
   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) {
    // Fehler behandeln. Alternativ den Fehlerparameter an jwt-cpp-Aufrufe übergeben
    qWarning() << "ID Token verification failed" << e.what();
   return false;
}

ID-Token-Werte auslesen

Das ID-Token liegt im JSON Web Token (JWT) -Format vor und besteht aus den Teilen „Header“, „Payload“ und „Signature“, die durch Punkte getrennt sind ..

Das Auslesen der Werte des ID-Tokens ist unkompliziert. Nehmen wir als Beispiel an, es gibt eine Struktur:

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

Und eine Funktion:

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

Das Token lässt sich wie folgt extrahieren:

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};

In einigen Fällen kann das Token als JSON Web Encryption (JWE) verschlüsselt sein, das intern ein JWT-Token enthält. In diesem Fall muss das Token zunächst entschlüsselt werden.

OpenID Connect Discovery

OpenID Connect Discovery definiert die Verfahren zur Ermittlung der erforderlichen Details eines OpenID-Anbieters, um mit diesem interagieren zu können. Dazu gehören Informationen wie die URLs „ authorization_endpoint “ und „ token_endpoint “.

Zwar können diese Anbieterangaben statisch in der Anwendung konfiguriert werden, doch bietet die Ermittlung der Angaben zur Laufzeit möglicherweise mehr Flexibilität und Robustheit bei der Interaktion mit verschiedenen Anbietern.

Das Abrufen des Discovery-Dokuments erfolgt über eine einfache HTTP-GET-Anfrage. Das Dokument befindet sich in der Regel unter 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
    }
});

Insbesondere für die Token-Validierung stellt das Feld „jwks_uri“ einen Link zum Zugriff auf die aktuellen (öffentlichen) Sicherheitszertifikate bereit. Dadurch entfällt die Notwendigkeit, solche Anmeldedaten direkt in die Anwendung fest zu programmieren. Dies ist auch bei der Schlüsselrotation von Vorteil; die Anbieter können die verwendeten Schlüssel von Zeit zu Zeit ändern, weshalb es wichtig ist, stets einen aktuellen Schlüssel zu gewährleisten.

Das Abrufen der Schlüssel erfolgt ebenfalls über eine einfache HTTP-GET-Anfrage:

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
    }
});

Der Schlüsselsatz enthält in der Regel mehrere Schlüssel. Der richtige Schlüssel wird im JWT-Header angegeben (es ist darauf zu achten, dass die Schlüssel korrekt zugeordnet werden; die bloße Überprüfung des Feldes „key id“ ( kid) reicht nicht aus).

OpenID-UserInfo-Endpunkt

Eine alternative Möglichkeit, auf Benutzerinformationen zuzugreifen, ist die Verwendung des OpenID Connect UserInfo-Endpunkts, sofern der OIDC-Anbieter diesen unterstützt. Die URL für die Benutzerinformationen befindet sich im Feld „ userinfo_endpoint “ des OpenID Connect Discovery -Dokuments.

Der UserInfo-Endpunkt verwendet kein ID-Token, sondern wird mit dem Zugriffstoken aufgerufen. Der Zugriff auf die UserInfo erfolgt ähnlich wie der Zugriff auf jede andere Ressource mit einem Zugriffstoken.

Angenommen, das Zugriffstoken wurde empfangen und beispielsweise wie folgt gesetzt:

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

Dann erfolgt der Zugriff auf „UserInfo“ über eine HTTP-GET-Anfrage:

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.